From 42893cf7e7fdd7e8fd0e8c14a48dd0cc0b6c23b8 Mon Sep 17 00:00:00 2001 From: Leopere Date: Sun, 8 Feb 2026 18:45:56 -0500 Subject: [PATCH] Replace Docker secrets with host bind mounts for SSH keys Keys are now mounted directly from /root/.ssh/ on the host node instead of using Docker Swarm secrets. CI deploy step simplified to verify key files exist and clean up leftover secrets. Co-authored-by: Cursor --- .woodpecker.yml | 31 ++++++++++--------------------- stack.production.yml | 29 ++++++++--------------------- 2 files changed, 18 insertions(+), 42 deletions(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index 19b5742..3d399f6 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -112,12 +112,6 @@ steps: from_secret: REGISTRY_USER REGISTRY_PASSWORD: from_secret: REGISTRY_PASSWORD - TUNNEL_SSH_HOST_KEY: - from_secret: tunnel_ssh_host_key - TUNNEL_AUTHORIZED_KEYS: - from_secret: tunnel_authorized_keys - TUNNEL_TRAEFIK_DEPLOY_KEY: - from_secret: tunnel_traefik_deploy_key volumes: - /var/run/docker.sock:/var/run/docker.sock commands: @@ -126,26 +120,21 @@ steps: - HOSTNAME=$(docker info --format "{{.Name}}") - echo "Deploying on $HOSTNAME" - echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us + # Clean up any leftover Docker secrets from previous deployments + - docker secret rm tunnel_ssh_host_key 2>/dev/null || true + - docker secret rm tunnel_authorized_keys 2>/dev/null || true + - docker secret rm tunnel_traefik_deploy_key 2>/dev/null || true # Remove old stack - echo "Removing old stack..." - docker stack rm better-argo-tunnels || true - sleep 10 - # Refresh secrets + # Verify host key files exist on the node - | - echo "Refreshing Docker secrets"; \ - if [ -z "$${TUNNEL_SSH_HOST_KEY}" ] || [ -z "$${TUNNEL_AUTHORIZED_KEYS}" ] || [ -z "$${TUNNEL_TRAEFIK_DEPLOY_KEY}" ]; then \ - echo "ERROR: Required secrets are empty. Aborting."; exit 1; \ - fi; \ - docker secret rm tunnel_ssh_host_key 2>/dev/null || true; \ - docker secret rm tunnel_authorized_keys 2>/dev/null || true; \ - docker secret rm tunnel_traefik_deploy_key 2>/dev/null || true; \ - sleep 3; \ - echo "$${TUNNEL_SSH_HOST_KEY}" | docker secret create tunnel_ssh_host_key -; \ - echo "$${TUNNEL_AUTHORIZED_KEYS}" | docker secret create tunnel_authorized_keys -; \ - echo "$${TUNNEL_TRAEFIK_DEPLOY_KEY}" | docker secret create tunnel_traefik_deploy_key -; \ - echo "Secrets created:"; \ - docker secret ls | grep tunnel_ - # Deploy stack + echo "Verifying host key files..."; \ + docker run --rm -v /root/.ssh:/check:ro alpine sh -c \ + 'ls -la /check/tunnel_host_key /check/authorized_keys /check/ca-userkey /check/ca-userkey-cert.pub' \ + || { echo "ERROR: Required key files missing from /root/.ssh/ on host"; exit 1; } + # Deploy stack (keys are bind-mounted from /root/.ssh/ on the host) - echo "Deploying stack..." - docker stack deploy --with-registry-auth -c ./stack.production.yml better-argo-tunnels when: diff --git a/stack.production.yml b/stack.production.yml index 08dca3d..ac8cf56 100644 --- a/stack.production.yml +++ b/stack.production.yml @@ -2,38 +2,20 @@ networks: traefik: external: true -secrets: - tunnel_ssh_host_key: - external: true - tunnel_authorized_keys: - external: true - tunnel_traefik_deploy_key: - external: true - services: tunnel-server: image: git.nixc.us/colin/better-argo-tunnels:production networks: - traefik - secrets: - - source: tunnel_ssh_host_key - target: host_key - mode: 0400 - - source: tunnel_authorized_keys - target: authorized_keys - mode: 0440 - - source: tunnel_traefik_deploy_key - target: traefik_deploy_key - mode: 0400 environment: SSH_PORT: "2222" PORT_RANGE_START: "10000" PORT_RANGE_END: "10100" - SSH_HOST_KEY: "/run/secrets/host_key" - AUTHORIZED_KEYS: "/run/secrets/authorized_keys" + SSH_HOST_KEY: "/keys/host_key" + AUTHORIZED_KEYS: "/keys/authorized_keys" TRAEFIK_SSH_HOST: "ingress.nixc.us:65522" TRAEFIK_SSH_USER: "root" - TRAEFIK_SSH_KEY: "/run/secrets/traefik_deploy_key" + TRAEFIK_SSH_KEY: "/keys/deploy_key" SWARM_SERVICE_NAME: "better-argo-tunnels_tunnel-server" TRAEFIK_ENTRYPOINT: "websecure" TRAEFIK_CERT_RESOLVER: "letsencryptresolver" @@ -42,6 +24,11 @@ services: SERVICE_NAME: "{{.Service.Name}}" TASK_ID: "{{.Task.ID}}" ENVIRONMENT: "production" + volumes: + - /root/.ssh/tunnel_host_key:/keys/host_key:ro + - /root/.ssh/authorized_keys:/keys/authorized_keys:ro + - /root/.ssh/ca-userkey:/keys/deploy_key:ro + - /root/.ssh/ca-userkey-cert.pub:/keys/deploy_key-cert.pub:ro ports: - target: 2222 published: 2222