ci/woodpecker/push/woodpecker Pipeline was successfulDetails
The bcrypt hash was escaping $ to $$ which is only needed in compose
files. docker service update --label-add with single-quoted values
preserves dollar signs literally, so doubling them broke Traefik auth.
Co-authored-by: Cursor <cursoragent@cursor.com>
ci/woodpecker/push/woodpecker Pipeline was successfulDetails
docker-compose.test.yml spins up an nginx + tunnel-client pointing at
testrst.nixc.us with basicauth test:test for end-to-end validation.
Co-authored-by: Cursor <cursoragent@cursor.com>
Clients can now set TUNNEL_AUTH_USER and TUNNEL_AUTH_PASS to have the
server add a Traefik basicauth middleware in front of the tunnel route.
Credentials are sent as tunnel metadata over the SSH channel and the
server generates a bcrypt htpasswd entry for Traefik's Docker labels.
Co-authored-by: Cursor <cursoragent@cursor.com>
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>
- keyutil.go / client ssh.go: if <key>-cert.pub exists next to
the private key, load it automatically (mirrors openssh behavior)
- stack.production.yml: TRAEFIK_SSH_HOST uses port 65522
Co-authored-by: Cursor <cursoragent@cursor.com>
Local dev override mounts real SSH keys for testing the tunnel
server and client without needing Swarm secrets.
Co-authored-by: Cursor <cursoragent@cursor.com>
- labels.go: use `docker service update --label-add/rm` via SSH to
dynamically manage Traefik labels on the Swarm service itself,
matching how traefik-http discovers routes from Docker swarm labels
- stack.production.yml: constrain to ingress.nixc.us, host-mode port
2222, base traefik.enable labels, SWARM_SERVICE_NAME env
- cmd/server/main.go: SWARM_SERVICE_NAME replaces TRAEFIK_CONFIG_DIR
- .woodpecker.yml: hardcode stack name better-argo-tunnels, update
smoke test env vars
Co-authored-by: Cursor <cursoragent@cursor.com>
- .woodpecker.yml: test, build+push x86 images, smoke test, deploy to Swarm
- docker-compose.production.yml: CI build targets for server + client images
- stack.production.yml: Swarm stack with secrets, Traefik TCP labels, port range
- docker-compose.yml: simplified to minimal build+image (matches smsbridge pattern)
Co-authored-by: Cursor <cursoragent@cursor.com>
Go binary pair (server + client) that establishes reverse SSH tunnels
and dynamically registers Traefik routes by SSHing into the ingress
host to write file-provider config. Clients need only a private key,
server address, domain, and local port as envvars.
Co-authored-by: Cursor <cursoragent@cursor.com>