# Woodpecker CI Configuration for better-argo-tunnels # # SYNTAX NOTES: # - Environment variables from secrets MUST use $${VAR} syntax (double dollar) # - Single $ will be interpreted literally and won't expand variables labels: location: manager clone: git: image: woodpeckerci/plugin-git settings: partial: false depth: 1 steps: # Build and test Go binaries test: name: test image: golang:1.24-alpine commands: - go version | cat - go vet ./... - go build ./cmd/server/ - go build ./cmd/client/ - echo "Build and vet passed" when: branch: main event: [push, pull_request] # Build and Push Docker images for production (x86) build-push-production: name: build-push-production image: woodpeckerci/plugin-docker-buildx depends_on: ["test"] environment: REGISTRY_USER: from_secret: REGISTRY_USER REGISTRY_PASSWORD: from_secret: REGISTRY_PASSWORD volumes: - /var/run/docker.sock:/var/run/docker.sock commands: - echo "nameserver 1.1.1.1" > /etc/resolv.conf - echo "nameserver 1.0.0.1" >> /etc/resolv.conf - HOSTNAME=$(docker info --format "{{.Name}}") - echo "Building on $HOSTNAME" - echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us - apk add --no-cache git || true - export GIT_COMMIT=$${CI_COMMIT_SHA} - echo "Building GIT_COMMIT=$GIT_COMMIT" # Build server image - docker build --target server -t git.nixc.us/colin/better-argo-tunnels:production . - docker push git.nixc.us/colin/better-argo-tunnels:production # Build client image - docker build --target client -t git.nixc.us/colin/better-argo-tunnels:client-production . - docker push git.nixc.us/colin/better-argo-tunnels:client-production when: branch: main event: [push, cron] # Smoke test - verify server binary starts smoke-production: name: smoke-production image: woodpeckerci/plugin-docker-buildx depends_on: ["build-push-production"] environment: REGISTRY_USER: from_secret: REGISTRY_USER REGISTRY_PASSWORD: from_secret: REGISTRY_PASSWORD volumes: - /var/run/docker.sock:/var/run/docker.sock commands: - echo "nameserver 1.1.1.1" > /etc/resolv.conf - echo "nameserver 1.0.0.1" >> /etc/resolv.conf - echo "$${REGISTRY_PASSWORD}" | docker login git.nixc.us -u "$${REGISTRY_USER}" --password-stdin - docker pull git.nixc.us/colin/better-argo-tunnels:production - docker rm -f tunnel-smoke || true # Smoke: verify the binary runs and prints startup log - mkdir -p /tmp/smoke-keys - ssh-keygen -t ed25519 -f /tmp/smoke-keys/host_key -N "" -q - ssh-keygen -t ed25519 -f /tmp/smoke-keys/client_key -N "" -q - cat /tmp/smoke-keys/client_key.pub > /tmp/smoke-keys/authorized_keys - | docker run -d --name tunnel-smoke \ -e SSH_PORT=2222 \ -e SSH_HOST_KEY=/keys/host_key \ -e AUTHORIZED_KEYS=/keys/authorized_keys \ -e TRAEFIK_SSH_HOST=127.0.0.1 \ -e TRAEFIK_SSH_KEY=/keys/host_key \ -e SWARM_SERVICE_NAME=smoke-test \ -v /tmp/smoke-keys:/keys:ro \ git.nixc.us/colin/better-argo-tunnels:production - sleep 3 - docker logs tunnel-smoke 2>&1 | head -20 - docker rm -f tunnel-smoke || true - rm -rf /tmp/smoke-keys - echo "Smoke test passed" when: branch: main event: [push, cron] # Deploy to Swarm on ingress.nixc.us deploy-production: name: deploy-production image: woodpeckerci/plugin-docker-buildx depends_on: ["test", "build-push-production", "smoke-production"] environment: REGISTRY_USER: from_secret: REGISTRY_USER REGISTRY_PASSWORD: from_secret: REGISTRY_PASSWORD volumes: - /var/run/docker.sock:/var/run/docker.sock commands: - echo "nameserver 1.1.1.1" > /etc/resolv.conf - echo "nameserver 1.0.0.1" >> /etc/resolv.conf - 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 # Verify host key files exist on the node - | 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: branch: main event: [push, cron]