| name | relay-troubleshoot |
| description | Diagnose a broken relay connection symptom→cause: client won't connect, browser/login redirect at the edge, TLS "unknown certificate authority", requests hang ~30s then context-canceled, balance/credit block, admin console won't load, or a stuck client. Probes the path layer by layer (local tunnel → CDN Access edge → mTLS → gateway) and applies the known fix. Use when the user says the relay/Claude/Codex "isn't working", "can't connect", "hangs", or "times out". |
| allowed-tools | Read, Bash, Agent, TodoWrite |
Relay connection triage
Read CLAUDE.md (gotchas) and docs/SECURITY-CHECKLIST.md. Work the path outward-in and probe —
don't guess. Start with bash local/verify.sh (edge-gate probe, no-token refusal, full-path 200,
lockdown) to localize the break, then match the symptom:
| Symptom | Likely cause → fix |
|---|
| Browser/login redirect in the edge-access log | CDN service-token wrong/stale → re-pull from the VPS .env. The edge must open headlessly (one Service-Auth policy, no identity policy). |
| TLS / "unknown certificate authority" in the ghostunnel log | client cert not signed by the CLIENT CA the VPS trusts (/etc/ghostunnel/client-ca.crt), the device's server-ca.crt isn't the server's signing CA, or --allow-cn missing → relay-add-device flow. |
Every request hangs ~30s → context canceled | DOCKER-USER regressed (RETURN must be above the DROP) → the health check auto-remediates; or re-run vps/02. Verify sudo iptables -S DOCKER-USER shows RETURN first. |
| Balance/credit block | owner wallet empty + cached → use the relay-ops skill (raise balance AND clear the cached snapshot). |
| Admin console page won't load | the forward's SSH process exited → re-run it in your own terminal (relay-admin-console skill). |
| Health check FAILs after a change you made | drift detection working — if intentional, re-baseline (relay-healthcheck). |
| Stuck client / port busy | the client's stop script or fuser -k <port>/tcp. Never pkill -f "ghostunnel client"/"cloudflared access" (matches your own shell). |
Layer probes (when the table isn't enough — delegate VPS probes to relay-operator)
- Local stack: is the client up? Check its access/ghostunnel logs; is the local listener up?
- Edge: does the service token open the tunnel without a browser? (verify.sh covers this.)
- mTLS/origin: on the VPS,
systemctl is-active ghostunnel-server cloudflared; origin port
listening; connector HEALTHY.
- App: the gateway returns
401 unauthenticated on its loopback port (alive); container egress to
the upstream returns 401 (proves DOCKER-USER didn't regress).
Guardrails
- Never "fix" by weakening an invariant (no opening a port, no switching the CDN to http://, no second
Access policy, no non-loopback bind). If a fix would, stop and explain.
- Never print secrets while reading logs/env. If the fix is balance/device/health, hand off to the
matching
relay-ops / relay-add-device / relay-healthcheck skill.