diff --git a/docs/reference/environment-variables.md b/docs/reference/environment-variables.md index fe95e62..76e4187 100644 --- a/docs/reference/environment-variables.md +++ b/docs/reference/environment-variables.md @@ -17,6 +17,8 @@ it is absent. | `KEY_ENCRYPTION_KEY` | yes in practice | | 64 hex characters (32 bytes) for AES-256-GCM. Required for private keys, vault secrets, OIDC client secrets and console credentials | | `GITEA_HOST` | yes | `gitea.example.com` | Used to build the install scripts and agent download URLs. The default is a placeholder that will not resolve | | `GUACD_ADDR` | no | `guacd:4822` | The [browser console](../vantage/browser-console.md) daemon | +| `PROXY_ADVERTISE_HOST` | no | `server` | The hostname **guacd** uses to reach the control plane's console relay. Wrong here and every console session fails at connect with guacd unable to resolve the relay | +| `PROXY_LISTEN_HOST` | no | `0.0.0.0` | Interface the ephemeral relay listeners bind. Narrow it only if guacd shares a known interface | | `APP_ROOT_LABEL` | no | `vantage` | The app root label for the host and session organisation guard | | `VANTAGE_WORKFLOW_LOG_DIR` | no | | Where workflow run logs are written | diff --git a/docs/reference/ports-and-networking.md b/docs/reference/ports-and-networking.md index 983db52..e747fe2 100644 --- a/docs/reference/ports-and-networking.md +++ b/docs/reference/ports-and-networking.md @@ -24,7 +24,8 @@ flowchart LR W --> S["server :8080"] A["Agent on a managed server"] -->|"gRPC/TLS :9090, outbound"| S S --> G["guacd :4822"] - G -->|"SSH / RDP / VNC"| T["Target machine"] + G -->|"relayed over the :9090 stream"| A + A -->|"SSH / RDP / VNC, loopback"| T["Target machine (same host as agent)"] ``` Two things are worth reading off that diagram. @@ -33,9 +34,13 @@ Two things are worth reading off that diagram. NAT is not an obstacle. The only requirement is that the machine can reach `GRPC_HOST`. -**The console does not use the agent.** guacd connects directly to the target on -the protocol port. A machine reachable only by its agent behind NAT, on a -private subnet cannot be consoled, even though every other feature works. +**The console rides the agent's connection too.** guacd never dials the target +directly; the server pushes a command down the agent's existing outbound gRPC +stream on `9090`, and the agent relays the protocol traffic from its own +loopback. No route from the control plane to the target's address is needed, +and no new inbound port opens on the target — the same connection that carries +key sync carries console traffic. This is what makes the console work for a +machine behind NAT on a private subnet, as long as its agent is online. ## What to open @@ -49,7 +54,9 @@ private subnet cannot be consoled, even though every other feature works. - `gitea.hostxtra.co.uk`, for agent releases and version checks. - Anything a server-run [monitor](../vantage/monitors.md) checks. - SMTP, if you use an SMTP notification channel. -- Protocol ports on machines you intend to console. + +No route to the machines you intend to console is needed — that traffic rides +the agent's existing outbound `9090` connection instead. ### Outbound from a managed machine diff --git a/docs/reference/troubleshooting.md b/docs/reference/troubleshooting.md index acee941..d37119d 100644 --- a/docs/reference/troubleshooting.md +++ b/docs/reference/troubleshooting.md @@ -86,7 +86,7 @@ instantaneous. | Connects, then closes at once | guacd unreachable. Check `GUACD_ADDR` and that the container is running | | SSH rejects the key | The stored key has no private half, or is not on the target | | RDP fails on retry | Credentials are single-use and consumed at tunnel open enter them again | -| Hangs at "connecting" | The **control plane** cannot reach the target on the protocol port. The agent's reachability is irrelevant here | +| Hangs at connecting | The agent is offline, or nothing is listening on the protocol port on the target's own loopback address. Check the audit log for `console.proxy_failed` — its reason names which | | Fails only in production | The reverse proxy is not forwarding WebSocket upgrade headers | ## Monitors report down when the service is up diff --git a/docs/vantage/browser-console.md b/docs/vantage/browser-console.md index 03b4ce4..f35afa1 100644 --- a/docs/vantage/browser-console.md +++ b/docs/vantage/browser-console.md @@ -15,17 +15,20 @@ to a **guacd** daemon and manages credentials around it. - `guacd` running and reachable from the server. The bundled Compose stack includes it; `GUACD_ADDR` defaults to `guacd:4822`. - `KEY_ENCRYPTION_KEY` set, since every credential involved is stored encrypted. -- Network reachability **from the control plane to the target** on the protocol - port. This is the one part of Vantage that is not agent-mediated: guacd - connects directly, so a machine reachable only by its agent cannot be - consoled. +- The target's **agent must be online**. Console traffic is relayed over the + agent's existing outbound connection, so the control plane never needs a route + to the server's address — but it does need the agent. +- No inbound port on the target, beyond what the protocol already listens on + locally. A service bound only to `127.0.0.1` works, because the agent dials + loopback on the target itself. ## Opening a session From a server's page, choose **Console**. Then: 1. The UI calls `POST /api/console/connect`, which mints a **one-time** session - token. + token. If the target's agent is not connected, this fails immediately with + `409 agent_offline` rather than hanging. 2. The browser opens a WebSocket to `GET /api/console/tunnel` with that token. 3. The server marks the token consumed atomically, so a second use cannot race and proxies the connection to guacd. @@ -67,4 +70,4 @@ keystroke log. If you need that, it has to come from the target machine. | Connects then closes immediately | guacd unreachable check `GUACD_ADDR` and that the container is up | | SSH refuses the key | The stored key has no private half, or is not in the target's `authorized_keys` | | RDP fails on a fresh credential | Credentials are consumed on open; a retry needs them entered again | -| Hangs at connecting | The control plane cannot reach the target on the protocol port | +| Hangs at connecting | The agent is offline, or nothing is listening on the protocol port on the target's own loopback address. Check the audit log for `console.proxy_failed` — its reason names which |