From 00bb639efadbbe0d1e9d43cdb796cbb99462f332 Mon Sep 17 00:00:00 2001 From: tegwick Date: Wed, 11 Mar 2026 01:09:07 +0100 Subject: [PATCH] feat(ops+workplans): fix tunnel targets, plan custodian migration, close legacy ADR-001 gaps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tunnel (state-hub/Makefile): - Replace interactive `make tunnel` (now non-blocking with -N flag) - Add tunnel-daemon (autossh background), tunnel-loop (reconnect fallback), tunnel-status, tunnel-stop - Default COULOMBCORE=tegwick@92.205.130.254; TUNNEL_PORT configurable - Clarified server topology: COULOMBCORE=92.205.130.254 (old), Railiance01=92.205.62.239 (ThreePhoenix node 1) Workplans: - CUST-WP-0011: Migrate Custodian State Hub to ThreePhoenix cluster — 9-task plan with hard pre-condition gates (3-node cluster, Longhorn HA, backup drill), data migration, 2-week stabilisation, WSL2 retirement - CUST-WP-0000: Retroactive record for state-hub v0.1 (pre-ADR-001) - CUST-WP-0000b: Retroactive record for state-hub v0.2 (pre-ADR-001) Consistency: repo now ✓ PASS (0 fail, 18 warn — all pre-ADR-001 C-12 history) Co-Authored-By: Claude Sonnet 4.6 --- Makefile | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 914e55c..52db38f 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: install install-cli db db-tools migrate seed api dashboard check start clean register-project validate-adr add-domain rename-domain add-repo list-repos cleanup-stale +.PHONY: install install-cli db db-tools migrate seed api dashboard check start clean register-project validate-adr add-domain rename-domain add-repo list-repos cleanup-stale tunnel tunnel-daemon tunnel-loop tunnel-status tunnel-stop COMPOSE = docker compose -f infra/docker-compose.yml --env-file .env @@ -34,14 +34,65 @@ dashboard: check: curl -sf http://127.0.0.1:8000/state/health | python3 -m json.tool -## Open a reverse SSH tunnel so a remote host can reach the local State Hub. -## Usage: make tunnel HOST=user@hostname -## The remote host will then reach the hub at http://127.0.0.1:8000 +## COULOMBCORE host (default target for tunnel targets) +COULOMBCORE ?= tegwick@92.205.130.254 +TUNNEL_PORT ?= 8000 + +## Foreground reverse tunnel — good for debugging. Ctrl-C to stop. +## Usage: make tunnel HOST=tegwick@92.205.130.254 tunnel: @test -n "$(HOST)" || (echo "ERROR: HOST is required. Usage: make tunnel HOST=user@hostname"; exit 1) - @echo "Opening reverse tunnel → $(HOST) (remote :8000 → local :8000)" + @echo "Opening reverse tunnel → $(HOST) (remote :$(TUNNEL_PORT) → local :$(TUNNEL_PORT))" @echo "Keep this terminal open. Ctrl-C to close the tunnel." - ssh -R 8000:127.0.0.1:8000 $(HOST) + ssh -N -o "ServerAliveInterval=30" -o "ServerAliveCountMax=3" \ + -R $(TUNNEL_PORT):127.0.0.1:$(TUNNEL_PORT) $(HOST) + +## Background tunnel to COULOMBCORE with auto-reconnect. +## Uses autossh if available; prints install hint and exits if not. +## After running, COULOMBCORE can reach the State Hub at http://127.0.0.1:8000 +tunnel-daemon: + @if command -v autossh >/dev/null 2>&1; then \ + echo "Starting autossh tunnel → $(COULOMBCORE)"; \ + autossh -f -N -M 0 \ + -o "ServerAliveInterval=30" \ + -o "ServerAliveCountMax=3" \ + -o "ExitOnForwardFailure=yes" \ + -R $(TUNNEL_PORT):127.0.0.1:$(TUNNEL_PORT) $(COULOMBCORE); \ + echo "Tunnel running in background. Use 'make tunnel-status' to check."; \ + else \ + echo "autossh not found — install it: sudo apt-get install autossh"; \ + echo "Fallback: run 'make tunnel-loop HOST=$(COULOMBCORE)' in a dedicated terminal."; \ + exit 1; \ + fi + +## Reconnect loop — works without autossh. Run in a terminal you can leave open. +## Usage: make tunnel-loop HOST=tegwick@92.205.130.254 +tunnel-loop: + @test -n "$(HOST)" || (echo "ERROR: HOST is required. Usage: make tunnel-loop HOST=user@hostname"; exit 1) + @echo "Reconnect loop → $(HOST). Ctrl-C to stop." + @while true; do \ + echo "[$(shell date -u +%Y-%m-%dT%H:%M:%SZ)] Connecting..."; \ + ssh -N -o "ServerAliveInterval=30" -o "ServerAliveCountMax=3" \ + -o "ExitOnForwardFailure=yes" \ + -R $(TUNNEL_PORT):127.0.0.1:$(TUNNEL_PORT) $(HOST) || true; \ + echo "[$(shell date -u +%Y-%m-%dT%H:%M:%SZ)] Connection lost — retrying in 5s..."; \ + sleep 5; \ + done + +## Check whether a tunnel is currently active +tunnel-status: + @if command -v autossh >/dev/null 2>&1 && pgrep -f "autossh.*$(TUNNEL_PORT)" > /dev/null 2>&1; then \ + echo "autossh tunnel: RUNNING (PIDs: $$(pgrep -f 'autossh.*$(TUNNEL_PORT)' | tr '\n' ' '))"; \ + elif pgrep -f "ssh.*-R $(TUNNEL_PORT)" > /dev/null 2>&1; then \ + echo "ssh tunnel: RUNNING (PIDs: $$(pgrep -f 'ssh.*-R $(TUNNEL_PORT)' | tr '\n' ' '))"; \ + else \ + echo "Tunnel: NOT running"; \ + fi + +## Stop any active tunnel (autossh or plain ssh) +tunnel-stop: + @pkill -f "autossh.*$(TUNNEL_PORT)" 2>/dev/null && echo "autossh stopped" || true + @pkill -f "ssh.*-R $(TUNNEL_PORT)" 2>/dev/null && echo "ssh loop stopped" || true start: db sleep 3