12# TAILCAT_CLIENT_KEY (secret): this edge's client key file contents.3# FORGE_TAILCAT_ADDR (secret): the forge container's tailcat address.4# FORGE_DOMAIN, FORGE_MIRROR_URL (fly.toml env): the offline copy (Caddyfile).5# FORGE_MIRROR_TOKEN (secret, optional): sent to the mirror bucket with each6# request for the offline copy, for a rule in front of the bucket to require.7set -eu8: "${TAILCAT_CLIENT_KEY:?set the edge client key secret}"9: "${FORGE_TAILCAT_ADDR:?set the forge tailcat address secret}"10umask 07711mkdir -p /run/tailcat12printf '%s' "$TAILCAT_CLIENT_KEY" >/run/tailcat/client.private.json1314# ssh goes straight through on :2222. HTTP comes in on :8081, behind Caddy.15forward() {16 tailcat --key=/run/tailcat/client.private.json forward --bind=0.0.0.0 "$FORGE_TAILCAT_ADDR" 2222:2222 8081:8080 &17 pid=$!18}1920# tailcat can close its listeners on SIGTERM and then never exit, which left21# a bare `wait` (and so this whole watchdog) hanging with the edge offline.22# Give it 5 seconds, then kill it outright.23stop_forward() {24 kill "$pid" 2>/dev/null || true25 n=026 while kill -0 "$pid" 2>/dev/null && [ "$n" -lt 5 ]; do27 sleep 128 n=$((n + 1))29 done30 kill -9 "$pid" 2>/dev/null || true31 wait "$pid" 2>/dev/null || true32}3334# Caddy on :8080 sends requests to the forward, and serves the pages mirror35# for those the forge doesn't answer. It runs as its own user.36web() {37 su -s /bin/sh caddy -c 'exec caddy run --config /etc/caddy/Caddyfile --adapter caddyfile' &38 web=$!39}4041# A running forward doesn't re-establish its session when the forge42# container restarts (redeploy, reboot), so probe through the tunnel itself,43# not through Caddy (which answers from the mirror), and restart the forward44# after two failed probes. Any HTTP status line counts as reachable; only a45# dead tunnel fails.46forward47web48fails=049while sleep 15; do50 if ! kill -0 "$web" 2>/dev/null; then51 echo "edge: caddy exited, restarting" >&252 web53 fi54 if ! kill -0 "$pid" 2>/dev/null; then55 echo "edge: forward exited, restarting" >&256 forward57 fails=058 continue59 fi60 if wget -S -T 5 -O /dev/null http://127.0.0.1:8081/ 2>&1 | grep -q 'HTTP/'; then61 fails=062 else63 fails=$((fails + 1))64 fi65 if [ "$fails" -ge 2 ]; then66 echo "edge: forge unreachable through tailcat, restarting forward" >&267 stop_forward68 forward69 fails=070 fi71done