Replace Docker secrets with host bind mounts for SSH keys
ci/woodpecker/push/woodpecker Pipeline failed Details

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 <cursoragent@cursor.com>
This commit is contained in:
Leopere 2026-02-08 18:45:56 -05:00
parent 443e077e46
commit 42893cf7e7
Signed by: colin
SSH Key Fingerprint: SHA256:nRPCQTeMFLdGytxRQmPVK9VXY3/ePKQ5lGRyJhT5DY8
2 changed files with 18 additions and 42 deletions

View File

@ -112,12 +112,6 @@ steps:
from_secret: REGISTRY_USER from_secret: REGISTRY_USER
REGISTRY_PASSWORD: REGISTRY_PASSWORD:
from_secret: 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: volumes:
- /var/run/docker.sock:/var/run/docker.sock - /var/run/docker.sock:/var/run/docker.sock
commands: commands:
@ -126,26 +120,21 @@ steps:
- HOSTNAME=$(docker info --format "{{.Name}}") - HOSTNAME=$(docker info --format "{{.Name}}")
- echo "Deploying on $HOSTNAME" - echo "Deploying on $HOSTNAME"
- echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us - 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 # Remove old stack
- echo "Removing old stack..." - echo "Removing old stack..."
- docker stack rm better-argo-tunnels || true - docker stack rm better-argo-tunnels || true
- sleep 10 - sleep 10
# Refresh secrets # Verify host key files exist on the node
- | - |
echo "Refreshing Docker secrets"; \ echo "Verifying host key files..."; \
if [ -z "$${TUNNEL_SSH_HOST_KEY}" ] || [ -z "$${TUNNEL_AUTHORIZED_KEYS}" ] || [ -z "$${TUNNEL_TRAEFIK_DEPLOY_KEY}" ]; then \ docker run --rm -v /root/.ssh:/check:ro alpine sh -c \
echo "ERROR: Required secrets are empty. Aborting."; exit 1; \ 'ls -la /check/tunnel_host_key /check/authorized_keys /check/ca-userkey /check/ca-userkey-cert.pub' \
fi; \ || { echo "ERROR: Required key files missing from /root/.ssh/ on host"; exit 1; }
docker secret rm tunnel_ssh_host_key 2>/dev/null || true; \ # Deploy stack (keys are bind-mounted from /root/.ssh/ on the host)
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 "Deploying stack..." - echo "Deploying stack..."
- docker stack deploy --with-registry-auth -c ./stack.production.yml better-argo-tunnels - docker stack deploy --with-registry-auth -c ./stack.production.yml better-argo-tunnels
when: when:

View File

@ -2,38 +2,20 @@ networks:
traefik: traefik:
external: true external: true
secrets:
tunnel_ssh_host_key:
external: true
tunnel_authorized_keys:
external: true
tunnel_traefik_deploy_key:
external: true
services: services:
tunnel-server: tunnel-server:
image: git.nixc.us/colin/better-argo-tunnels:production image: git.nixc.us/colin/better-argo-tunnels:production
networks: networks:
- traefik - 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: environment:
SSH_PORT: "2222" SSH_PORT: "2222"
PORT_RANGE_START: "10000" PORT_RANGE_START: "10000"
PORT_RANGE_END: "10100" PORT_RANGE_END: "10100"
SSH_HOST_KEY: "/run/secrets/host_key" SSH_HOST_KEY: "/keys/host_key"
AUTHORIZED_KEYS: "/run/secrets/authorized_keys" AUTHORIZED_KEYS: "/keys/authorized_keys"
TRAEFIK_SSH_HOST: "ingress.nixc.us:65522" TRAEFIK_SSH_HOST: "ingress.nixc.us:65522"
TRAEFIK_SSH_USER: "root" 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" SWARM_SERVICE_NAME: "better-argo-tunnels_tunnel-server"
TRAEFIK_ENTRYPOINT: "websecure" TRAEFIK_ENTRYPOINT: "websecure"
TRAEFIK_CERT_RESOLVER: "letsencryptresolver" TRAEFIK_CERT_RESOLVER: "letsencryptresolver"
@ -42,6 +24,11 @@ services:
SERVICE_NAME: "{{.Service.Name}}" SERVICE_NAME: "{{.Service.Name}}"
TASK_ID: "{{.Task.ID}}" TASK_ID: "{{.Task.ID}}"
ENVIRONMENT: "production" 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: ports:
- target: 2222 - target: 2222
published: 2222 published: 2222