From 4757a9de7a7b04b46647b107fb6e18110da548ea Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 10 Apr 2026 19:51:03 +0000 Subject: [PATCH] fix: feat: move reverse tunnel into disinto-edge container with single-port forward (#622) - Dockerfile: add openssh-client + autossh to edge image - entrypoint-edge.sh: start autossh reverse tunnel before Caddy when EDGE_TUNNEL_HOST is set; no-op when unset (local-only dev works unchanged) - generators.sh: pass EDGE_TUNNEL_{HOST,USER,PORT,FQDN} env vars and bind-mount secrets/tunnel_key into the edge service Decommission steps for old host-level reverse-tunnel.service: sudo systemctl disable --now reverse-tunnel.service sudo rm /etc/systemd/system/reverse-tunnel.service sudo systemctl daemon-reload Co-Authored-By: Claude Opus 4.6 (1M context) --- docker/edge/Dockerfile | 2 +- docker/edge/entrypoint-edge.sh | 31 +++++++++++++++++++++++++++++++ lib/generators.sh | 6 ++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/docker/edge/Dockerfile b/docker/edge/Dockerfile index 9ef0c7a..6706852 100644 --- a/docker/edge/Dockerfile +++ b/docker/edge/Dockerfile @@ -1,4 +1,4 @@ FROM caddy:latest -RUN apk add --no-cache bash jq curl git docker-cli python3 +RUN apk add --no-cache bash jq curl git docker-cli python3 openssh-client autossh COPY entrypoint-edge.sh /usr/local/bin/entrypoint-edge.sh ENTRYPOINT ["bash", "/usr/local/bin/entrypoint-edge.sh"] diff --git a/docker/edge/entrypoint-edge.sh b/docker/edge/entrypoint-edge.sh index 694d7e6..87357d1 100755 --- a/docker/edge/entrypoint-edge.sh +++ b/docker/edge/entrypoint-edge.sh @@ -106,6 +106,37 @@ fi # Ensure log directory exists mkdir -p /opt/disinto-logs +# ── Reverse tunnel (optional) ────────────────────────────────────────── +# When EDGE_TUNNEL_HOST is set, open a single reverse-SSH forward so the +# DO edge box can reach this container's Caddy on the project's assigned port. +# Guarded: if EDGE_TUNNEL_HOST is empty/unset the block is skipped entirely, +# keeping local-only dev working without errors. +if [ -n "${EDGE_TUNNEL_HOST:-}" ]; then + _tunnel_key="/run/secrets/tunnel_key" + if [ ! -f "$_tunnel_key" ]; then + echo "WARN: EDGE_TUNNEL_HOST is set but ${_tunnel_key} is missing — skipping tunnel" >&2 + else + # Ensure correct permissions (bind-mount may arrive as 644) + chmod 0400 "$_tunnel_key" 2>/dev/null || true + + : "${EDGE_TUNNEL_USER:=tunnel}" + : "${EDGE_TUNNEL_PORT:?EDGE_TUNNEL_PORT must be set when EDGE_TUNNEL_HOST is set}" + + export AUTOSSH_GATETIME=0 # don't exit if the first attempt fails quickly + + autossh -M 0 -N -f \ + -o StrictHostKeyChecking=accept-new \ + -o ServerAliveInterval=30 \ + -o ServerAliveCountMax=3 \ + -o ExitOnForwardFailure=yes \ + -i "$_tunnel_key" \ + -R "127.0.0.1:${EDGE_TUNNEL_PORT}:localhost:80" \ + "${EDGE_TUNNEL_USER}@${EDGE_TUNNEL_HOST}" + + echo "edge: reverse tunnel → ${EDGE_TUNNEL_HOST}:${EDGE_TUNNEL_PORT}" >&2 + fi +fi + # Start dispatcher in background bash /opt/disinto/docker/edge/dispatcher.sh & diff --git a/lib/generators.sh b/lib/generators.sh index aeed75d..1308c96 100644 --- a/lib/generators.sh +++ b/lib/generators.sh @@ -401,10 +401,16 @@ services: - OPS_REPO_ROOT=/opt/disinto-ops - PROJECT_REPO_ROOT=/opt/disinto - PRIMARY_BRANCH=main + # Reverse tunnel (optional — set by `disinto edge register`, see #622) + - EDGE_TUNNEL_HOST=${EDGE_TUNNEL_HOST:-} + - EDGE_TUNNEL_USER=${EDGE_TUNNEL_USER:-tunnel} + - EDGE_TUNNEL_PORT=${EDGE_TUNNEL_PORT:-} + - EDGE_TUNNEL_FQDN=${EDGE_TUNNEL_FQDN:-} volumes: - ./docker/Caddyfile:/etc/caddy/Caddyfile - caddy_data:/data - /var/run/docker.sock:/var/run/docker.sock + - ./secrets/tunnel_key:/run/secrets/tunnel_key:ro depends_on: - forgejo - woodpecker