- Arm the unclaimed-relay watchdog in NewSession rather than Serve, so an agent that never opens its ProxyStream is bounded to 10s and reports reason "agent_timeout", per the design spec's failure-mode table. - Session.Close now also closes the accepted net.Conn (stored via setConn), so ConsoleProxy.Close() is an unconditional kill of the whole relay chain instead of only closing an already-idle listener. - Emit console.proxy_failed and end the console session from a defer in consoleTunnel guarded on relay.Reason(), since guac's OnDisconnect never runs when the connect callback errors -- which is the path every relay failure this feature introduces takes. Update the two docsite troubleshooting rows to match what the audit event can now actually show.
3.3 KiB
id, title, sidebar_label
| id | title | sidebar_label |
|---|---|---|
| browser-console | Browser console | Browser console |
An SSH, RDP or VNC session in a browser tab, with no client software and no inbound port on the target beyond the one the protocol already uses.
Protocol handling is Apache Guacamole's the control plane proxies a WebSocket to a guacd daemon and manages credentials around it.
Requirements
guacdrunning and reachable from the server. The bundled Compose stack includes it;GUACD_ADDRdefaults toguacd:4822.KEY_ENCRYPTION_KEYset, since every credential involved is stored encrypted.- 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.1works, because the agent dials loopback on the target itself.
Opening a session
From a server's page, choose Console. Then:
- The UI calls
POST /api/console/connect, which mints a one-time session token. If the target's agent is not connected, this fails immediately with409 agent_offlinerather than hanging. - The browser opens a WebSocket to
GET /api/console/tunnelwith that token. - The server marks the token consumed atomically, so a second use cannot race and proxies the connection to guacd.
Credentials
SSH
Authenticates with a private key stored in the key library. The key must have its private half uploaded; a public-only key cannot open a session.
RDP and VNC
You supply credentials when connecting. They are encrypted, single-use, and consumed when the tunnel opens. They are not retained for the next session.
:::info Why single-use A stored console credential is a standing grant to that machine for anyone who can reach the endpoint. Consuming it at tunnel-open means a leaked session token is worth one connection at most, and only until it is used. :::
Session behaviour
Closing the tab ends the session. There is no reconnect and no session persistence reopening mints a new token and a new connection.
Auditing
Opening a console is an audited action, with actor, server and time. What happens inside the session is not recorded: there is no session capture or keystroke log. If you need that, it has to come from the target machine.
When it does not work
| Symptom | Cause |
|---|---|
| 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, then disconnects | The agent never claimed the relay, nothing is listening on the protocol port on the target's own loopback address, or guacd never dialled in time. Check the audit log for console.proxy_failed — its reason (agent_timeout, dial_refused, guacd_timeout, rejected) names which |