From edfe160b4f87db1b18d88dce3dca21b0ffd26f0e Mon Sep 17 00:00:00 2001 From: Michael Trip Date: Tue, 23 Jun 2026 15:29:06 +0200 Subject: [PATCH 01/29] Update entrypoint.sh to prevent failure on missing password entry and modify deployment.yaml to use latest image tag with Always pull policy --- entrypoint.sh | 3 ++- k8s/deployment.yaml | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/entrypoint.sh b/entrypoint.sh index 22436d7..30d4e14 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -70,7 +70,8 @@ store_generated_password() { read_generated_password() { local username="$1" - grep -E "^${username}=" "${GENERATED_PASSWORDS_FILE}" | tail -n 1 | cut -d '=' -f 2- + # Return an empty string if no entry exists; never fail under `set -euo pipefail`. + awk -F '=' -v username="${username}" '$1 == username { value = substr($0, index($0, "=") + 1) } END { if (value != "") print value }' "${GENERATED_PASSWORDS_FILE}" } write_authorized_keys() { diff --git a/k8s/deployment.yaml b/k8s/deployment.yaml index 2972315..1bfb963 100644 --- a/k8s/deployment.yaml +++ b/k8s/deployment.yaml @@ -21,8 +21,8 @@ spec: type: RuntimeDefault containers: - name: k8s-mgmt-pod - image: git.alcatrash.net/michael/k8s-mgmt-pod/k8s-mgmt-pod:v1.0.0 - imagePullPolicy: IfNotPresent + image: git.alcatrash.net/michael/k8s-mgmt-pod/k8s-mgmt-pod:latest + imagePullPolicy: Always ports: - name: ssh containerPort: 22 From b715b4bb59c4753ebc326084cd8cf9977762e391 Mon Sep 17 00:00:00 2001 From: Michael Trip Date: Tue, 23 Jun 2026 15:31:09 +0200 Subject: [PATCH 02/29] Remove paths filter from push event in build workflow --- .github/workflows/build-workflow.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/build-workflow.yaml b/.github/workflows/build-workflow.yaml index 5df5f7a..3036ab7 100644 --- a/.github/workflows/build-workflow.yaml +++ b/.github/workflows/build-workflow.yaml @@ -5,9 +5,6 @@ on: - cron: '0 3 * * 6' push: branches: ["main"] - paths: - - "Dockerfile" - - ".github/workflows/build-workflow.yaml" tags: ["v*.*.*"] pull_request: branches: ["main"] From 5584dc1f29798c06fce447add7b2605e0e52a582 Mon Sep 17 00:00:00 2001 From: Michael Trip Date: Tue, 23 Jun 2026 15:48:15 +0200 Subject: [PATCH 03/29] Update SSH port from 22 to 2222 in Dockerfile, entrypoint, and Kubernetes configurations --- Dockerfile | 7 ++++--- README.md | 16 ++++++++-------- docker-compose.yaml | 2 +- docker/sshd/10-lfk-base.conf | 1 - entrypoint.sh | 9 ++++++++- k8s/README.md | 2 +- k8s/deployment.yaml | 12 ++++++------ k8s/networkpolicy.yaml | 2 +- k8s/service.yaml | 4 ++-- 9 files changed, 31 insertions(+), 24 deletions(-) diff --git a/Dockerfile b/Dockerfile index 70f8ad1..4faf09a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -31,7 +31,8 @@ ENV DEBIAN_FRONTEND=noninteractive \ WEB_SSH_PORT=3000 \ WEBSSH2_LISTEN_PORT=3001 \ WEBSSH2_SSH_HOST=127.0.0.1 \ - WEBSSH2_SSH_PORT=22 \ + WEBSSH2_SSH_PORT=2222 \ + SSH_PORT=2222 \ WEBSSH2_HEADER_TEXT=k8s-mgmt-pod \ WEBSSH2_SSH_HOSTKEY_ENABLED=false @@ -99,9 +100,9 @@ COPY entrypoint.sh /usr/local/bin/entrypoint.sh RUN chmod 0755 /usr/local/bin/entrypoint.sh \ && chmod 0644 /etc/profile.d/20-k8s-tools-completion.sh -EXPOSE 22 3000 +EXPOSE 2222 3000 HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \ - CMD nc -z 127.0.0.1 22 || exit 1 + CMD nc -z 127.0.0.1 "${SSH_PORT:-2222}" || exit 1 ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/entrypoint.sh"] diff --git a/README.md b/README.md index 308526d..62f3935 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ - `helm` preinstalled from a pinned upstream binary release - `k9s` preinstalled from a pinned GitHub release tarball - `kubectl` and `helm` bash autocompletion enabled for both `admin` and `user` -- local `openssh-server` on port `22` +- local `openssh-server` on port `2222` - a browser-based SSH client on port `3000` - a custom ASCII-art MOTD on login - two provisioned users: `admin` and `user` @@ -20,7 +20,7 @@ One caveat is worth stating clearly: browser-based SSH tools do not keep the pri ## Ports -- `22`: native SSH into the container's local `sshd` +- `2222`: native SSH into the container's local `sshd` - `3000`: browser UI entrypoint; `/` and `/ssh` are forced to a fixed local WebSSH2 session for `127.0.0.1` and rewritten back to that host if changed in the URL ## Runtime environment variables @@ -113,7 +113,7 @@ If `${HOME}/.kube/config` is missing on the host, the container logs that bootst ```bash docker run --rm \ - -p 2222:22 \ + -p 2222:2222 \ -p 3000:3000 \ -e ADMIN_SSH_PUBKEY="$(cat ~/.ssh/id_ed25519.pub)" \ -e USER_SSH_PUBKEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIexample user@example" \ @@ -132,7 +132,7 @@ Or in a browser at `http://localhost:3000/`. ```bash docker run --rm \ - -p 2222:22 \ + -p 2222:2222 \ -p 3000:3000 \ -e ADMIN_PASSWORD='change-this-admin-password' \ -e USER_PASSWORD='change-this-user-password' \ @@ -143,7 +143,7 @@ If that fails with a message like `unable to upgrade to tcp, received 500`, the ```bash docker run -d --name k8s-mgmt-pod \ - -p 2222:22 \ + -p 2222:2222 \ -p 3000:3000 \ -e ADMIN_PASSWORD='change-this-admin-password' \ -e USER_PASSWORD='change-this-user-password' \ @@ -156,7 +156,7 @@ If Docker reports `bind: address already in use`, change the host-side ports or ```bash docker run --rm \ - -p 127.0.0.1::22 \ + -p 127.0.0.1::2222 \ -p 127.0.0.1::3000 \ -e ADMIN_PASSWORD='change-this-admin-password' \ -e USER_PASSWORD='change-this-user-password' \ @@ -167,7 +167,7 @@ docker run --rm \ ```bash docker run --rm \ - -p 2222:22 \ + -p 2222:2222 \ -p 3000:3000 \ -e ADMIN_SSH_PUBKEY="$(cat ~/.ssh/id_ed25519.pub)" \ -e ADMIN_PASSWORD='change-this-admin-password' \ @@ -184,7 +184,7 @@ If you omit both the public-key and password variables for a user, the container ```bash docker run --rm \ - -p 2222:22 \ + -p 2222:2222 \ -p 3000:3000 \ -e ADMIN_SSH_PUBKEY="$(cat ~/.ssh/id_ed25519.pub)" \ k8s-mgmt-pod:local diff --git a/docker-compose.yaml b/docker-compose.yaml index 4f81d2e..95ff74a 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -6,7 +6,7 @@ services: dockerfile: Dockerfile container_name: k8s-mgmt-pod ports: - - "${HOST_SSH_PORT:-2222}:22" + - "${HOST_SSH_PORT:-2222}:2222" - "${HOST_WEBSSH_PORT:-3000}:3000" environment: ADMIN_PASSWORD: ${ADMIN_PASSWORD:-change-this-admin-password} diff --git a/docker/sshd/10-lfk-base.conf b/docker/sshd/10-lfk-base.conf index 5b59dd1..cf982a6 100644 --- a/docker/sshd/10-lfk-base.conf +++ b/docker/sshd/10-lfk-base.conf @@ -1,4 +1,3 @@ -Port 22 Protocol 2 PermitRootLogin no PubkeyAuthentication yes diff --git a/entrypoint.sh b/entrypoint.sh index 30d4e14..458bd77 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -10,6 +10,12 @@ WEBSSH2_PID="" NGINX_PID="" BOOTSTRAP_KUBECONFIG="${BOOTSTRAP_KUBECONFIG:-/bootstrap/kubeconfig/config}" ENABLE_BOOTSTRAP_KUBECONFIG="${ENABLE_BOOTSTRAP_KUBECONFIG:-false}" +SSH_PORT="${SSH_PORT:-2222}" + +if [[ -z "${WEBSSH2_SSH_PORT:-}" ]]; then + WEBSSH2_SSH_PORT="${SSH_PORT}" +fi +export WEBSSH2_SSH_PORT ensure_host_keys() { if [[ ! -f "${STATE_DIR}/ssh_host_rsa_key" ]]; then @@ -187,6 +193,7 @@ render_sshd_auth_config() { fi cat > "${SSH_DYNAMIC_CONFIG}" < Date: Tue, 23 Jun 2026 16:00:46 +0200 Subject: [PATCH 04/29] Add SYS_CHROOT capability to container security context --- k8s/deployment.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/k8s/deployment.yaml b/k8s/deployment.yaml index 9bc3445..9881843 100644 --- a/k8s/deployment.yaml +++ b/k8s/deployment.yaml @@ -85,7 +85,7 @@ spec: readOnlyRootFilesystem: false capabilities: drop: ["ALL"] - add: ["CHOWN", "DAC_OVERRIDE", "FOWNER", "SETGID", "SETUID"] + add: ["CHOWN", "DAC_OVERRIDE", "FOWNER", "SETGID", "SETUID", "SYS_CHROOT"] volumes: - name: state emptyDir: {} From 41d4b36345e191d40073b1c3f3fb6a1181723ef2 Mon Sep 17 00:00:00 2001 From: Michael Trip Date: Tue, 23 Jun 2026 16:37:14 +0200 Subject: [PATCH 05/29] Enhance entrypoint and deployment configurations for Kubernetes management pod - Add K8S_RUNTIME_ENV_PROFILE and KUBERNETES_SECRETS_DIR variables in entrypoint.sh - Implement service account kubeconfig installation and environment variable persistence - Update deployment.yaml to include fsGroup and fsGroupChangePolicy in securityContext - Modify container ports and resource limits for better management --- entrypoint.sh | 97 +++++++++++++++++++++++++++++++++++++++++++-- k8s/deployment.yaml | 30 ++++++++++---- 2 files changed, 117 insertions(+), 10 deletions(-) diff --git a/entrypoint.sh b/entrypoint.sh index 458bd77..eb5a055 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -4,12 +4,14 @@ set -Eeuo pipefail STATE_DIR="/var/lib/k8s-mgmt-pod" GENERATED_PASSWORDS_FILE="${STATE_DIR}/generated-passwords.env" SSH_DYNAMIC_CONFIG="/etc/ssh/sshd_config.d/20-k8s-mgmt-pod-auth.conf" +K8S_RUNTIME_ENV_PROFILE="/etc/profile.d/30-kubernetes-runtime-env.sh" PASSWORD_AUTH_REQUIRED=0 SSHD_PID="" WEBSSH2_PID="" NGINX_PID="" BOOTSTRAP_KUBECONFIG="${BOOTSTRAP_KUBECONFIG:-/bootstrap/kubeconfig/config}" ENABLE_BOOTSTRAP_KUBECONFIG="${ENABLE_BOOTSTRAP_KUBECONFIG:-false}" +KUBERNETES_SECRETS_DIR="${KUBERNETES_SECRETS_DIR:-/var/run/kubernetes.io}" SSH_PORT="${SSH_PORT:-2222}" if [[ -z "${WEBSSH2_SSH_PORT:-}" ]]; then @@ -96,12 +98,84 @@ write_authorized_keys() { install_kubeconfig_for_user() { local username="$1" + local source_kubeconfig="$2" local home_dir="/home/${username}" local kube_dir="${home_dir}/.kube" local kube_config="${kube_dir}/config" mkdir -p "${kube_dir}" - install -m 0600 -o "${username}" -g "${username}" "${BOOTSTRAP_KUBECONFIG}" "${kube_config}" + install -m 0600 -o "${username}" -g "${username}" "${source_kubeconfig}" "${kube_config}" +} + +resolve_kubernetes_secrets_dir() { + local configured_dir="${KUBERNETES_SECRETS_DIR}" + local fallback_dir="/var/run/secrets/kubernetes.io/serviceaccount" + + if [[ -f "${configured_dir}/token" && -f "${configured_dir}/ca.crt" && -f "${configured_dir}/namespace" ]]; then + printf '%s\n' "${configured_dir}" + return 0 + fi + + if [[ "${configured_dir}" != "${fallback_dir}" ]] \ + && [[ -f "${fallback_dir}/token" && -f "${fallback_dir}/ca.crt" && -f "${fallback_dir}/namespace" ]]; then + printf '%s\n' "${fallback_dir}" + return 0 + fi + + return 1 +} + +install_serviceaccount_kubeconfig() { + local sa_dir="" + local token_file="" + local ca_file="" + local namespace_file="" + local namespace="" + local kubernetes_host="${KUBERNETES_SERVICE_HOST:-kubernetes.default.svc}" + local kubernetes_port="${KUBERNETES_SERVICE_PORT_HTTPS:-443}" + local server="" + local generated_kubeconfig="${STATE_DIR}/incluster.kubeconfig" + + if ! sa_dir="$(resolve_kubernetes_secrets_dir)"; then + log "Skipping in-cluster kubeconfig generation because no service-account mount was found in ${KUBERNETES_SECRETS_DIR} or /var/run/secrets/kubernetes.io/serviceaccount." + return + fi + + token_file="${sa_dir}/token" + ca_file="${sa_dir}/ca.crt" + namespace_file="${sa_dir}/namespace" + namespace="$(tr -d '\n' < "${namespace_file}")" + if [[ -z "${namespace}" ]]; then + namespace="default" + fi + + server="https://${kubernetes_host}:${kubernetes_port}" + + cat > "${generated_kubeconfig}" < "${K8S_RUNTIME_ENV_PROFILE}" < Date: Wed, 24 Jun 2026 09:12:27 +0200 Subject: [PATCH 06/29] Refactor RBAC configuration to use ClusterRole and ClusterRoleBinding for k8s-mgmt-pod with expanded resource permissions, while retaining security. --- k8s/rbac.yaml | 166 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 153 insertions(+), 13 deletions(-) diff --git a/k8s/rbac.yaml b/k8s/rbac.yaml index ab13028..b884b0c 100644 --- a/k8s/rbac.yaml +++ b/k8s/rbac.yaml @@ -1,49 +1,189 @@ apiVersion: rbac.authorization.k8s.io/v1 -kind: Role +kind: ClusterRole metadata: name: k8s-mgmt-pod rules: - # This is intentionally broader than the strict minimum so lfk and kubectl are usable. - # Scope it down to the smallest verb and resource set your operators actually need. - apiGroups: [""] resources: - configmaps - endpoints - events + - limitranges + - namespaces + - nodes - persistentvolumeclaims + - persistentvolumes - pods - - pods/exec - pods/log - - secrets + - pods/portforward + - pods/proxy + - replicationcontrollers + - replicationcontrollers/scale + - resourcequotas - serviceaccounts - services - verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] + - services/proxy + verbs: ["*"] - apiGroups: ["apps"] resources: + - controllerrevisions - daemonsets - deployments + - deployments/scale - replicasets + - replicasets/scale - statefulsets - verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] + - statefulsets/scale + verbs: ["*"] - apiGroups: ["batch"] resources: - cronjobs - jobs - verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] + verbs: ["*"] + - apiGroups: ["autoscaling"] + resources: + - horizontalpodautoscalers + verbs: ["*"] - apiGroups: ["networking.k8s.io"] resources: + - ingressclasses - ingresses - - networkpolicies - verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] + verbs: ["*"] + - apiGroups: ["extensions"] + resources: + - ingresses + verbs: ["*"] + - apiGroups: ["policy"] + resources: + - poddisruptionbudgets + verbs: ["*"] + - apiGroups: ["coordination.k8s.io"] + resources: + - leases + verbs: ["*"] + - apiGroups: ["storage.k8s.io"] + resources: + - csidrivers + - csinodes + - csistoragecapacities + - storageclasses + - volumeattachments + verbs: ["*"] + - apiGroups: ["apiextensions.k8s.io"] + resources: + - customresourcedefinitions + verbs: ["*"] + - apiGroups: ["admissionregistration.k8s.io"] + resources: + - mutatingadmissionpolicies + - mutatingwebhookconfigurations + - validatingadmissionpolicies + - validatingwebhookconfigurations + verbs: ["*"] + - apiGroups: ["metrics.k8s.io"] + resources: + - nodes + - pods + verbs: ["get", "list", "watch"] + - apiGroups: ["gateway.networking.k8s.io"] + resources: + - gatewayclasses + - gateways + - httproutes + - referencegrants + - tcproutes + - tlsroutes + - udproutes + verbs: ["*"] + - apiGroups: ["cert-manager.io"] + resources: + - certificates + - certificaterequests + - clusterissuers + - issuers + verbs: ["*"] + - apiGroups: ["monitoring.coreos.com"] + resources: + - alertmanagers + - podmonitors + - prometheuses + - prometheusrules + - servicemonitors + - thanosrulers + verbs: ["*"] + - apiGroups: ["argoproj.io"] + resources: + - applications + - appprojects + verbs: ["*"] + - apiGroups: ["traefik.containo.us", "traefik.io"] + resources: + - ingressroutes + - middlewares + - traefikservices + verbs: ["*"] + - apiGroups: ["k8s.cni.cncf.io"] + resources: + - network-attachment-definitions + verbs: ["*"] + - apiGroups: ["kubevirt.io"] + resources: + - virtualmachineinstances + - virtualmachines + verbs: ["*"] + - apiGroups: ["subresources.kubevirt.io"] + resources: + - "*" + verbs: ["*"] + - apiGroups: ["instancetype.kubevirt.io"] + resources: + - "*" + verbs: ["*"] + - apiGroups: ["cdi.kubevirt.io"] + resources: + - "*" + verbs: ["*"] + - apiGroups: ["pool.kubevirt.io"] + resources: + - "*" + verbs: ["*"] + - apiGroups: ["cluster.x-k8s.io"] + resources: + - clusters + - machinedeployments + - machinepools + - machines + - machinesets + verbs: ["*"] + - apiGroups: ["controlplane.cluster.x-k8s.io"] + resources: + - kubeadmcontrolplanes + verbs: ["*"] + - apiGroups: ["bootstrap.cluster.x-k8s.io"] + resources: + - kubeadmconfigs + - kubeadmconfigtemplates + verbs: ["*"] + - apiGroups: ["infrastructure.cluster.x-k8s.io"] + resources: + - kubevirtclusters + - kubevirtmachinetemplates + verbs: ["*"] + - apiGroups: ["addons.cluster.x-k8s.io"] + resources: + - clusterresourcesets + verbs: ["*"] + --- apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding +kind: ClusterRoleBinding metadata: - name: k8s-mgmt-pod + name: k8s-mgmt-pod-access subjects: - kind: ServiceAccount name: k8s-mgmt-pod + namespace: k8s-mgmt-pod roleRef: apiGroup: rbac.authorization.k8s.io - kind: Role + kind: ClusterRole name: k8s-mgmt-pod From e48f76441d1044575057a663226798f97f2497e6 Mon Sep 17 00:00:00 2001 From: Michael Trip Date: Wed, 24 Jun 2026 11:01:13 +0200 Subject: [PATCH 07/29] Add PersistentVolumeClaim for pod state persistence and update README --- k8s/README.md | 1 + k8s/deployment.yaml | 3 ++- k8s/kustomization.yaml | 1 + k8s/pvc.yaml | 10 ++++++++++ 4 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 k8s/pvc.yaml diff --git a/k8s/README.md b/k8s/README.md index 8533a42..69b6bf6 100644 --- a/k8s/README.md +++ b/k8s/README.md @@ -7,6 +7,7 @@ These manifests deploy `k8s-mgmt-pod` as a single-replica bastion deployment ins 1. Build and publish the image. 2. Replace the placeholder image in `deployment.yaml` with a pinned tag or digest. 3. Create the real `k8s-mgmt-pod-auth` Secret instead of applying `secret.yaml.example`. +4. The pod state directory is now backed by a PVC, so SSH host keys and generated fallback passwords survive pod recreation until you delete the claim. ## Create the Secret diff --git a/k8s/deployment.yaml b/k8s/deployment.yaml index 3f23603..01e85f9 100644 --- a/k8s/deployment.yaml +++ b/k8s/deployment.yaml @@ -104,4 +104,5 @@ spec: volumes: - name: state - emptyDir: {} \ No newline at end of file + persistentVolumeClaim: + claimName: k8s-mgmt-pod-state \ No newline at end of file diff --git a/k8s/kustomization.yaml b/k8s/kustomization.yaml index 3687f1b..45d635a 100644 --- a/k8s/kustomization.yaml +++ b/k8s/kustomization.yaml @@ -5,6 +5,7 @@ resources: - namespace.yaml - serviceaccount.yaml - rbac.yaml + - pvc.yaml - deployment.yaml - service.yaml - networkpolicy.yaml diff --git a/k8s/pvc.yaml b/k8s/pvc.yaml new file mode 100644 index 0000000..c954184 --- /dev/null +++ b/k8s/pvc.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: k8s-mgmt-pod-state +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi \ No newline at end of file From 43aa568452571c9755664e9a7cb612b76a4e5b7a Mon Sep 17 00:00:00 2001 From: Michael Trip Date: Wed, 24 Jun 2026 11:11:10 +0200 Subject: [PATCH 08/29] Update base images in Dockerfile from bookworm to trixie --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 4faf09a..d3710bc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -ARG NODE_IMAGE=node:22-bookworm-slim +ARG NODE_IMAGE=node:22-trixie-slim FROM ${NODE_IMAGE} AS webssh2-builder ENV DEBIAN_FRONTEND=noninteractive @@ -19,7 +19,7 @@ RUN apt-get update \ && rm -f "/tmp/webssh2-${WEBSSH2_VERSION}.tar.gz" "/tmp/webssh2-${WEBSSH2_VERSION}.tar.gz.sha256" \ && npm cache clean --force -FROM debian:bookworm-slim +FROM debian:trixie-slim ARG LFK_VERSION=0.14.9 ARG KUBECTL_VERSION=1.31.0 From f0e72c69a0810cfefe0423e01851eb09e0057209 Mon Sep 17 00:00:00 2001 From: Michael Trip Date: Wed, 24 Jun 2026 11:17:12 +0200 Subject: [PATCH 09/29] Add locales support and set UTF-8 environment variables in Dockerfile --- Dockerfile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Dockerfile b/Dockerfile index d3710bc..6e0d6b8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -52,6 +52,9 @@ RUN apt-get update \ openssl \ sudo \ tini \ + locales \ + && echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen \ + && locale-gen \ && rm -rf /var/lib/apt/lists/* \ && mkdir -p /var/run/sshd /var/lib/k8s-mgmt-pod /etc/ssh/sshd_config.d \ && useradd --create-home --shell /bin/bash admin \ @@ -100,6 +103,10 @@ COPY entrypoint.sh /usr/local/bin/entrypoint.sh RUN chmod 0755 /usr/local/bin/entrypoint.sh \ && chmod 0644 /etc/profile.d/20-k8s-tools-completion.sh +ENV LANG=en_US.UTF-8 +ENV LANGUAGE=en_US:en +ENV LC_ALL=en_US.UTF-8 + EXPOSE 2222 3000 HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \ From 60c4ed3c02d69fa9856918ca98fb38bea5416c01 Mon Sep 17 00:00:00 2001 From: Michael Trip Date: Wed, 24 Jun 2026 12:42:34 +0200 Subject: [PATCH 10/29] Refactor Dockerfile ARG declarations for better organization and add renovate configuration for automated dependency updates --- Dockerfile | 16 +++++++++++----- renovate.json | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 renovate.json diff --git a/Dockerfile b/Dockerfile index 6e0d6b8..fe36d91 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,8 +3,19 @@ FROM ${NODE_IMAGE} AS webssh2-builder ENV DEBIAN_FRONTEND=noninteractive +# renovate: datasource=github-releases depName=janosmiko/lfk +ARG LFK_VERSION=0.14.9 +# renovate: datasource=github-releases depName=kubernetes/kubectl +ARG KUBECTL_VERSION=1.31.0 +# renovate: datasource=github-releases depName=helm/helm +ARG HELM_VERSION=3.16.2 +# renovate: datasource=github-releases depName=derailed/k9s +ARG K9S_VERSION=0.40.10 +# renovate: datasource=github-releases depName=billchurch/webssh2 ARG WEBSSH2_VERSION=5.0.1 + + RUN apt-get update \ && apt-get install -y --no-install-recommends ca-certificates curl \ && rm -rf /var/lib/apt/lists/* \ @@ -21,11 +32,6 @@ RUN apt-get update \ FROM debian:trixie-slim -ARG LFK_VERSION=0.14.9 -ARG KUBECTL_VERSION=1.31.0 -ARG HELM_VERSION=3.16.2 -ARG K9S_VERSION=0.40.10 -ARG WEBSSH2_VERSION=5.0.1 ENV DEBIAN_FRONTEND=noninteractive \ WEB_SSH_PORT=3000 \ diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..5e4291b --- /dev/null +++ b/renovate.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:recommended" + ], + "customManagers": [ + { + "customType": "regex", + "managerFilePatterns": ["/^Dockerfile$/", "/Dockerfile.*/"], + "matchStrings": [ + "# renovate: datasource=(?.*?) depName=(?.*?)\\s+ARG .*?_VERSION=(?.*)\\s" + ], + "datasourceTemplate": "{{{datasource}}}" + } + ] +} \ No newline at end of file From 89c1e900b8f90b1645388caa4c50b0a1de7bfbf5 Mon Sep 17 00:00:00 2001 From: Michael Trip Date: Wed, 24 Jun 2026 12:58:49 +0200 Subject: [PATCH 11/29] Fix typo in Dockerfile ARG comment for kubectl datasource --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index fe36d91..aca87bc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,7 @@ ENV DEBIAN_FRONTEND=noninteractive # renovate: datasource=github-releases depName=janosmiko/lfk ARG LFK_VERSION=0.14.9 -# renovate: datasource=github-releases depName=kubernetes/kubectl +# renovate: datasource=github-releases depName=kubernetes/kubernetes ARG KUBECTL_VERSION=1.31.0 # renovate: datasource=github-releases depName=helm/helm ARG HELM_VERSION=3.16.2 From 709dd6d0b617df4f29e821ba4859458b7899fd39 Mon Sep 17 00:00:00 2001 From: michael Date: Wed, 24 Jun 2026 11:18:15 +0000 Subject: [PATCH 12/29] revert f0e72c69a0810cfefe0423e01851eb09e0057209 revert Add locales support and set UTF-8 environment variables in Dockerfile --- Dockerfile | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index aca87bc..e3d0044 100644 --- a/Dockerfile +++ b/Dockerfile @@ -58,9 +58,6 @@ RUN apt-get update \ openssl \ sudo \ tini \ - locales \ - && echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen \ - && locale-gen \ && rm -rf /var/lib/apt/lists/* \ && mkdir -p /var/run/sshd /var/lib/k8s-mgmt-pod /etc/ssh/sshd_config.d \ && useradd --create-home --shell /bin/bash admin \ @@ -109,10 +106,6 @@ COPY entrypoint.sh /usr/local/bin/entrypoint.sh RUN chmod 0755 /usr/local/bin/entrypoint.sh \ && chmod 0644 /etc/profile.d/20-k8s-tools-completion.sh -ENV LANG=en_US.UTF-8 -ENV LANGUAGE=en_US:en -ENV LC_ALL=en_US.UTF-8 - EXPOSE 2222 3000 HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \ From 0553a4815c06b3efc68b19bcf791d6b81a745ab4 Mon Sep 17 00:00:00 2001 From: Michael Trip Date: Wed, 24 Jun 2026 13:21:35 +0200 Subject: [PATCH 13/29] reverting back to working example --- Dockerfile | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/Dockerfile b/Dockerfile index e3d0044..2e4d40d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,19 +3,8 @@ FROM ${NODE_IMAGE} AS webssh2-builder ENV DEBIAN_FRONTEND=noninteractive -# renovate: datasource=github-releases depName=janosmiko/lfk -ARG LFK_VERSION=0.14.9 -# renovate: datasource=github-releases depName=kubernetes/kubernetes -ARG KUBECTL_VERSION=1.31.0 -# renovate: datasource=github-releases depName=helm/helm -ARG HELM_VERSION=3.16.2 -# renovate: datasource=github-releases depName=derailed/k9s -ARG K9S_VERSION=0.40.10 -# renovate: datasource=github-releases depName=billchurch/webssh2 ARG WEBSSH2_VERSION=5.0.1 - - RUN apt-get update \ && apt-get install -y --no-install-recommends ca-certificates curl \ && rm -rf /var/lib/apt/lists/* \ @@ -32,6 +21,11 @@ RUN apt-get update \ FROM debian:trixie-slim +ARG LFK_VERSION=0.14.9 +ARG KUBECTL_VERSION=1.31.0 +ARG HELM_VERSION=3.16.2 +ARG K9S_VERSION=0.40.10 +ARG WEBSSH2_VERSION=5.0.1 ENV DEBIAN_FRONTEND=noninteractive \ WEB_SSH_PORT=3000 \ @@ -111,4 +105,4 @@ EXPOSE 2222 3000 HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \ CMD nc -z 127.0.0.1 "${SSH_PORT:-2222}" || exit 1 -ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/entrypoint.sh"] +ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/entrypoint.sh"] \ No newline at end of file From d4e935c470b19ff32e71e81d0b17de3b8dabf1c8 Mon Sep 17 00:00:00 2001 From: Michael Trip Date: Wed, 24 Jun 2026 13:26:14 +0200 Subject: [PATCH 14/29] Add renovate comments for dependency tracking in Dockerfile --- Dockerfile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 2e4d40d..19522fb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,6 +3,7 @@ FROM ${NODE_IMAGE} AS webssh2-builder ENV DEBIAN_FRONTEND=noninteractive +# renovate: datasource=github-releases depName=billchurch/webssh2 ARG WEBSSH2_VERSION=5.0.1 RUN apt-get update \ @@ -21,11 +22,15 @@ RUN apt-get update \ FROM debian:trixie-slim +# renovate: datasource=github-releases depName=janosmiko/lfk ARG LFK_VERSION=0.14.9 +# renovate: datasource=github-releases depName=kubernetes/kubernetes ARG KUBECTL_VERSION=1.31.0 +# renovate: datasource=github-releases depName=helm/helm ARG HELM_VERSION=3.16.2 +# renovate: datasource=github-releases depName=derailed/k9s ARG K9S_VERSION=0.40.10 -ARG WEBSSH2_VERSION=5.0.1 + ENV DEBIAN_FRONTEND=noninteractive \ WEB_SSH_PORT=3000 \ From a7532c9292e8f55cf6cc5b6f96bf03854f01cbef Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Wed, 24 Jun 2026 11:27:11 +0000 Subject: [PATCH 15/29] Update dependency janosmiko/lfk to v0.14.15 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 19522fb..3c507e5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ RUN apt-get update \ FROM debian:trixie-slim # renovate: datasource=github-releases depName=janosmiko/lfk -ARG LFK_VERSION=0.14.9 +ARG LFK_VERSION=0.14.15 # renovate: datasource=github-releases depName=kubernetes/kubernetes ARG KUBECTL_VERSION=1.31.0 # renovate: datasource=github-releases depName=helm/helm From 335b11f4114c897b370c606343e2a354e91376dd Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Wed, 24 Jun 2026 11:27:17 +0000 Subject: [PATCH 16/29] Update dependency derailed/k9s to v0.51.0 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 19522fb..17cb607 100644 --- a/Dockerfile +++ b/Dockerfile @@ -29,7 +29,7 @@ ARG KUBECTL_VERSION=1.31.0 # renovate: datasource=github-releases depName=helm/helm ARG HELM_VERSION=3.16.2 # renovate: datasource=github-releases depName=derailed/k9s -ARG K9S_VERSION=0.40.10 +ARG K9S_VERSION=0.51.0 ENV DEBIAN_FRONTEND=noninteractive \ From 93b5f89e59a9c81e772493cad530f9fe344c47bb Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Wed, 24 Jun 2026 11:27:22 +0000 Subject: [PATCH 17/29] Update dependency helm/helm to v3.21.2 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 19522fb..c4f9a1a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,7 @@ ARG LFK_VERSION=0.14.9 # renovate: datasource=github-releases depName=kubernetes/kubernetes ARG KUBECTL_VERSION=1.31.0 # renovate: datasource=github-releases depName=helm/helm -ARG HELM_VERSION=3.16.2 +ARG HELM_VERSION=3.21.2 # renovate: datasource=github-releases depName=derailed/k9s ARG K9S_VERSION=0.40.10 From 32292556d4cacb8bcba0aa63afc8ed0dffaf6840 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Wed, 24 Jun 2026 11:27:27 +0000 Subject: [PATCH 18/29] Update dependency kubernetes/kubernetes to v1.36.2 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 19522fb..6d70be9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,7 +25,7 @@ FROM debian:trixie-slim # renovate: datasource=github-releases depName=janosmiko/lfk ARG LFK_VERSION=0.14.9 # renovate: datasource=github-releases depName=kubernetes/kubernetes -ARG KUBECTL_VERSION=1.31.0 +ARG KUBECTL_VERSION=1.36.2 # renovate: datasource=github-releases depName=helm/helm ARG HELM_VERSION=3.16.2 # renovate: datasource=github-releases depName=derailed/k9s From 91e9afc3556f5b96314542a9be92eec79103d41c Mon Sep 17 00:00:00 2001 From: Michael Trip Date: Wed, 24 Jun 2026 14:59:41 +0200 Subject: [PATCH 19/29] Add apt-get clean to Dockerfile to reduce image size --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index e65f657..314e38e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -57,6 +57,7 @@ RUN apt-get update \ openssl \ sudo \ tini \ + && apt-get clean \ && rm -rf /var/lib/apt/lists/* \ && mkdir -p /var/run/sshd /var/lib/k8s-mgmt-pod /etc/ssh/sshd_config.d \ && useradd --create-home --shell /bin/bash admin \ From 0613ebca661185e73ba484360370ae3e8c78a602 Mon Sep 17 00:00:00 2001 From: Michael Trip Date: Wed, 24 Jun 2026 15:00:17 +0200 Subject: [PATCH 20/29] Add apt-get clean to Dockerfile to optimize image size --- Dockerfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 314e38e..8fd38ac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -57,7 +57,6 @@ RUN apt-get update \ openssl \ sudo \ tini \ - && apt-get clean \ && rm -rf /var/lib/apt/lists/* \ && mkdir -p /var/run/sshd /var/lib/k8s-mgmt-pod /etc/ssh/sshd_config.d \ && useradd --create-home --shell /bin/bash admin \ @@ -95,7 +94,9 @@ RUN apt-get update \ /tmp/README.md \ /tmp/LICENSE \ /tmp/k9s_Linux_amd64.tar.gz \ - && rm -f /etc/ssh/ssh_host_* + && rm -f /etc/ssh/ssh_host_* \ + && apt-get clean + COPY docker/sshd/10-lfk-base.conf /etc/ssh/sshd_config.d/10-lfk-base.conf COPY docker/nginx/webssh.conf /etc/nginx/conf.d/webssh.conf From 68c6789ac4099a503b1ce2aca874427ac6555075 Mon Sep 17 00:00:00 2001 From: Michael Trip Date: Mon, 29 Jun 2026 08:52:08 +0200 Subject: [PATCH 21/29] Add OIDC login support and unzip utility to Dockerfile --- Dockerfile | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Dockerfile b/Dockerfile index 8fd38ac..1ccdb90 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,6 +30,8 @@ ARG KUBECTL_VERSION=1.36.2 ARG HELM_VERSION=3.21.2 # renovate: datasource=github-releases depName=derailed/k9s ARG K9S_VERSION=0.51.0 +# renovate: datasource=github-releases depName=int128/kubelogin +ARG OIDC_LOGIN_VERSION=1.34.0 ENV DEBIAN_FRONTEND=noninteractive \ @@ -49,6 +51,7 @@ RUN apt-get update \ bash-completion \ ca-certificates \ curl \ + unzip \ tar \ nginx-light \ netcat-openbsd \ @@ -81,6 +84,11 @@ RUN apt-get update \ && curl -fsSLo "/tmp/k9s_Linux_amd64.tar.gz" "https://github.com/derailed/k9s/releases/download/v${K9S_VERSION}/k9s_Linux_amd64.tar.gz" \ && tar -xzf "/tmp/k9s_Linux_amd64.tar.gz" -C /tmp \ && install -m 0755 /tmp/k9s /usr/local/bin/k9s \ + && curl -fsSLo "/tmp/kubelogin_linux_amd64.zip" "https://github.com/int128/kubelogin/releases/download/v${OIDC_LOGIN_VERSION}/kubelogin_linux_amd64.zip" \ + && curl -fsSLo "/tmp/kubelogin_linux_amd64.zip.sha256" "https://github.com/int128/kubelogin/releases/download/v${OIDC_LOGIN_VERSION}/kubelogin_linux_amd64.zip.sha256" \ + && sed 's#\*kubelogin_linux_amd64.zip$#*/tmp/kubelogin_linux_amd64.zip#' /tmp/kubelogin_linux_amd64.zip.sha256 | sha256sum -c - \ + && unzip -p /tmp/kubelogin_linux_amd64.zip kubelogin > /usr/local/bin/kubectl-oidc_login \ + && chmod 0755 /usr/local/bin/kubectl-oidc_login \ && mkdir -p /etc/bash_completion.d \ && kubectl completion bash > /etc/bash_completion.d/kubectl \ && helm completion bash > /etc/bash_completion.d/helm \ @@ -93,6 +101,8 @@ RUN apt-get update \ /tmp/k9s \ /tmp/README.md \ /tmp/LICENSE \ + /tmp/kubelogin_linux_amd64.zip \ + /tmp/kubelogin_linux_amd64.zip.sha256 \ /tmp/k9s_Linux_amd64.tar.gz \ && rm -f /etc/ssh/ssh_host_* \ && apt-get clean From b6f7d1e1b7a6256d2668ab902f4bac33b3549200 Mon Sep 17 00:00:00 2001 From: Michael Trip Date: Mon, 29 Jun 2026 09:14:20 +0200 Subject: [PATCH 22/29] Update kubeconfig handling in entrypoint script for better clarity --- README.md | 2 ++ entrypoint.sh | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 62f3935..20446e9 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,8 @@ The included [docker-compose.yaml](docker-compose.yaml) enables kubeconfig boots That bootstrap is explicitly opt-in and defaults to off in the container itself, so it does not run in Kubernetes unless you deliberately enable it. +When both are available, the bootstrap kubeconfig is applied after the service-account kubeconfig and therefore takes precedence. + Start it with: ```bash diff --git a/entrypoint.sh b/entrypoint.sh index eb5a055..0a2d319 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -291,8 +291,13 @@ EOF prepare_runtime() { mkdir -p /var/run/sshd ensure_host_keys - install_serviceaccount_kubeconfig - install_bootstrap_kubeconfig + if [[ "${ENABLE_BOOTSTRAP_KUBECONFIG}" == "true" ]]; then + log "Kubeconfig mode: bootstrap-only (serviceaccount kubeconfig generation disabled)." + install_bootstrap_kubeconfig + else + log "Kubeconfig mode: in-cluster serviceaccount." + install_serviceaccount_kubeconfig + fi persist_kubernetes_login_env configure_user_auth admin ADMIN_SSH_PUBKEY ADMIN_PASSWORD configure_user_auth user USER_SSH_PUBKEY USER_PASSWORD From 62d68bea0ce890d1b01045d8126acc3f000210be Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Mon, 29 Jun 2026 07:24:07 +0000 Subject: [PATCH 23/29] Update dependency janosmiko/lfk to v0.14.18 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 1ccdb90..f9793af 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ RUN apt-get update \ FROM debian:trixie-slim # renovate: datasource=github-releases depName=janosmiko/lfk -ARG LFK_VERSION=0.14.15 +ARG LFK_VERSION=0.14.18 # renovate: datasource=github-releases depName=kubernetes/kubernetes ARG KUBECTL_VERSION=1.36.2 # renovate: datasource=github-releases depName=helm/helm From fba15a73c09f71f2b906ee8d9f562f9fe1f45263 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Mon, 29 Jun 2026 07:24:11 +0000 Subject: [PATCH 24/29] Update dependency int128/kubelogin to v1.36.2 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 1ccdb90..4e8d067 100644 --- a/Dockerfile +++ b/Dockerfile @@ -31,7 +31,7 @@ ARG HELM_VERSION=3.21.2 # renovate: datasource=github-releases depName=derailed/k9s ARG K9S_VERSION=0.51.0 # renovate: datasource=github-releases depName=int128/kubelogin -ARG OIDC_LOGIN_VERSION=1.34.0 +ARG OIDC_LOGIN_VERSION=1.36.2 ENV DEBIAN_FRONTEND=noninteractive \ From 47fe90296e7658bfa225301705261260542ea6b8 Mon Sep 17 00:00:00 2001 From: Michael Trip Date: Mon, 29 Jun 2026 09:26:47 +0200 Subject: [PATCH 25/29] Create cache directory and set ownership/permissions for kubeconfig --- entrypoint.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/entrypoint.sh b/entrypoint.sh index 0a2d319..0253f38 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -104,6 +104,9 @@ install_kubeconfig_for_user() { local kube_config="${kube_dir}/config" mkdir -p "${kube_dir}" + mkdir -p "${kube_dir}/cache" + chown -R "${username}:${username}" "${kube_dir}" + chmod 0700 "${kube_dir}" install -m 0600 -o "${username}" -g "${username}" "${source_kubeconfig}" "${kube_config}" } From 998012fdff27ba06fdada335f9868841027dce67 Mon Sep 17 00:00:00 2001 From: Michael Trip Date: Mon, 29 Jun 2026 09:42:12 +0200 Subject: [PATCH 26/29] Add locale support and environment variables to Dockerfile --- Dockerfile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Dockerfile b/Dockerfile index 1ccdb90..0531748 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,6 +35,9 @@ ARG OIDC_LOGIN_VERSION=1.34.0 ENV DEBIAN_FRONTEND=noninteractive \ + LANG=en_US.UTF-8 \ + LANGUAGE=en_US:en \ + LC_ALL=en_US.UTF-8 \ WEB_SSH_PORT=3000 \ WEBSSH2_LISTEN_PORT=3001 \ WEBSSH2_SSH_HOST=127.0.0.1 \ @@ -51,6 +54,7 @@ RUN apt-get update \ bash-completion \ ca-certificates \ curl \ + locales \ unzip \ tar \ nginx-light \ @@ -93,6 +97,9 @@ RUN apt-get update \ && kubectl completion bash > /etc/bash_completion.d/kubectl \ && helm completion bash > /etc/bash_completion.d/helm \ && chmod 0644 /etc/bash_completion.d/kubectl /etc/bash_completion.d/helm \ + && sed -i 's/^# *en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen \ + && locale-gen en_US.UTF-8 \ + && update-locale LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 \ && rm -f /tmp/kubectl.sha256 \ && rm -rf /tmp/linux-amd64 \ && rm -f \ From e4f9f0667471dfdabf42f90ca9d639c6653640d1 Mon Sep 17 00:00:00 2001 From: Michael Trip Date: Mon, 29 Jun 2026 10:51:20 +0200 Subject: [PATCH 27/29] Fix formatting in the motd file for consistency --- docker/motd | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docker/motd b/docker/motd index 134af58..86ca94f 100644 --- a/docker/motd +++ b/docker/motd @@ -1,13 +1,13 @@ ╔════════════════════════════════════════════════════════════════╗ ║ ║ - ║ ██╗ ███████╗██╗ ██╗ ██╗ ██╗ █████╗ ███████╗ ║ - ║ ██║ ██╔════╝██║ ██╔╝ ██║ ██╔╝██╔══██╗██╔════╝ ║ - ║ ██║ █████╗ █████╔╝ █████╔╝ ╚█████╔╝███████╗ ║ - ║ ██║ ██╔══╝ ██╔═██╗ ██╔═██╗ ██╔══██╗╚════██║ ║ - ║ ███████╗██║ ██║ ██╗ ██║ ██╗╚█████╔╝███████║ ║ - ║ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚════╝ ╚══════╝ ║ - ║ Kubernetes Management Pod - Jump Box ║ + ║ ██╗ ███████╗██╗ ██╗ ██╗ ██╗ █████╗ ███████╗ ║ + ║ ██║ ██╔════╝██║ ██╔╝ ██║ ██╔╝██╔══██╗██╔════╝ ║ + ║ ██║ █████╗ █████╔╝ █████╔╝ ╚█████╔╝███████╗ ║ + ║ ██║ ██╔══╝ ██╔═██╗ ██╔═██╗ ██╔══██╗╚════██║ ║ + ║ ███████╗██║ ██║ ██╗ ██║ ██╗╚█████╔╝███████║ ║ + ║ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚════╝ ╚══════╝ ║ + ║ Kubernetes Management Pod - Jump Box ║ ║ ║ ╠════════════════════════════════════════════════════════════════╣ ║ Toolbelt ║ From d5823119172a7bb51e6be7f5483be57642de4c4b Mon Sep 17 00:00:00 2001 From: Michael Trip Date: Mon, 29 Jun 2026 10:54:20 +0200 Subject: [PATCH 28/29] Update ASCII art in motd for improved branding and consistency --- docker/motd | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docker/motd b/docker/motd index 86ca94f..9a3de0c 100644 --- a/docker/motd +++ b/docker/motd @@ -1,12 +1,12 @@ ╔════════════════════════════════════════════════════════════════╗ ║ ║ - ║ ██╗ ███████╗██╗ ██╗ ██╗ ██╗ █████╗ ███████╗ ║ - ║ ██║ ██╔════╝██║ ██╔╝ ██║ ██╔╝██╔══██╗██╔════╝ ║ - ║ ██║ █████╗ █████╔╝ █████╔╝ ╚█████╔╝███████╗ ║ - ║ ██║ ██╔══╝ ██╔═██╗ ██╔═██╗ ██╔══██╗╚════██║ ║ - ║ ███████╗██║ ██║ ██╗ ██║ ██╗╚█████╔╝███████║ ║ - ║ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚════╝ ╚══════╝ ║ + ║ ║ + ║ _ __ ___ ____ __ __ ____ __ __ _____ ║ + ║ | |/ / / _ \ / ___| | \/ | / ___|| \/ ||_ _| ║ + ║ | ' / | (_) |\___ \ | |\/| || | _ | |\/| | | | ║ + ║ | . \ \__, | ___) | | | | || |_| || | | | | | ║ + ║ |_|\_\ /_/ |____/ |_| |_| \____||_| |_| |_| ║ ║ Kubernetes Management Pod - Jump Box ║ ║ ║ ╠════════════════════════════════════════════════════════════════╣ From df0eaf0a218dd2141e0d35dc6d31f77bb1411ca5 Mon Sep 17 00:00:00 2001 From: Michael Trip Date: Mon, 29 Jun 2026 13:40:34 +0200 Subject: [PATCH 29/29] Add kubectx and kubens support to Dockerfile and bash completion scripts --- Dockerfile | 12 +++++++++++- README.md | 4 +++- docker/motd | 2 +- docker/profile/20-k8s-tools-completion.sh | 8 ++++++++ 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index c21f111..481e097 100644 --- a/Dockerfile +++ b/Dockerfile @@ -32,6 +32,8 @@ ARG HELM_VERSION=3.21.2 ARG K9S_VERSION=0.51.0 # renovate: datasource=github-releases depName=int128/kubelogin ARG OIDC_LOGIN_VERSION=1.36.2 +# renovate: datasource=github-tags depName=ahmetb/kubectx +ARG KUBECTX_VERSION=0.9.5 ENV DEBIAN_FRONTEND=noninteractive \ @@ -54,9 +56,12 @@ RUN apt-get update \ bash-completion \ ca-certificates \ curl \ + jq \ locales \ unzip \ tar \ + vim \ + yq \ nginx-light \ netcat-openbsd \ openssh-client \ @@ -93,10 +98,15 @@ RUN apt-get update \ && sed 's#\*kubelogin_linux_amd64.zip$#*/tmp/kubelogin_linux_amd64.zip#' /tmp/kubelogin_linux_amd64.zip.sha256 | sha256sum -c - \ && unzip -p /tmp/kubelogin_linux_amd64.zip kubelogin > /usr/local/bin/kubectl-oidc_login \ && chmod 0755 /usr/local/bin/kubectl-oidc_login \ + && curl -fsSLo /usr/local/bin/kubectx "https://raw.githubusercontent.com/ahmetb/kubectx/v${KUBECTX_VERSION}/kubectx" \ + && curl -fsSLo /usr/local/bin/kubens "https://raw.githubusercontent.com/ahmetb/kubectx/v${KUBECTX_VERSION}/kubens" \ + && chmod 0755 /usr/local/bin/kubectx /usr/local/bin/kubens \ && mkdir -p /etc/bash_completion.d \ + && curl -fsSLo /etc/bash_completion.d/kubectx "https://raw.githubusercontent.com/ahmetb/kubectx/v${KUBECTX_VERSION}/completion/kubectx.bash" \ + && curl -fsSLo /etc/bash_completion.d/kubens "https://raw.githubusercontent.com/ahmetb/kubectx/v${KUBECTX_VERSION}/completion/kubens.bash" \ && kubectl completion bash > /etc/bash_completion.d/kubectl \ && helm completion bash > /etc/bash_completion.d/helm \ - && chmod 0644 /etc/bash_completion.d/kubectl /etc/bash_completion.d/helm \ + && chmod 0644 /etc/bash_completion.d/kubectl /etc/bash_completion.d/helm /etc/bash_completion.d/kubectx /etc/bash_completion.d/kubens \ && sed -i 's/^# *en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen \ && locale-gen en_US.UTF-8 \ && update-locale LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 \ diff --git a/README.md b/README.md index 20446e9..ca220cc 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,9 @@ - `kubectl` preinstalled from a pinned upstream binary release - `helm` preinstalled from a pinned upstream binary release - `k9s` preinstalled from a pinned GitHub release tarball -- `kubectl` and `helm` bash autocompletion enabled for both `admin` and `user` +- `kubectx` and `kubens` preinstalled from a pinned upstream release +- `jq`, `yq`, and `vim` preinstalled from Debian packages +- `kubectl`, `helm`, `kubectx`, and `kubens` bash autocompletion enabled for both `admin` and `user` - local `openssh-server` on port `2222` - a browser-based SSH client on port `3000` - a custom ASCII-art MOTD on login diff --git a/docker/motd b/docker/motd index 9a3de0c..859b382 100644 --- a/docker/motd +++ b/docker/motd @@ -15,7 +15,7 @@ ║ - lfk : LFK kubernetes management ║ ║ - k9s : interactive cluster navigation ║ ║ - helm : chart install, upgrade, and rollback ║ - ║ - plus : kubectx, kubens, jq, yq, and more ║ + ║ - plus : kubectx, kubens, jq, yq, vim, and more ║ ║ ║ ╠════════════════════════════════════════════════════════════════╣ ║ Quick start ║ diff --git a/docker/profile/20-k8s-tools-completion.sh b/docker/profile/20-k8s-tools-completion.sh index b9092e6..5cb4a72 100644 --- a/docker/profile/20-k8s-tools-completion.sh +++ b/docker/profile/20-k8s-tools-completion.sh @@ -13,6 +13,14 @@ if [ -n "${BASH_VERSION:-}" ]; then if [ -r /etc/bash_completion.d/helm ]; then . /etc/bash_completion.d/helm fi + + if [ -r /etc/bash_completion.d/kubectx ]; then + . /etc/bash_completion.d/kubectx + fi + + if [ -r /etc/bash_completion.d/kubens ]; then + . /etc/bash_completion.d/kubens + fi fi alias k=kubectl