How to Forward Sandbox Portspublic
Last verified 9 Oct 2026
DigitalOcean Harness Runtime provides managed, hardware-isolated microVM sandboxes with built-in tools such as Chromium to run harnesses and execute arbitrary code. Rich lifecycle APIs preserve conversational history and working state across sessions, letting you pause, resume, and fork work to control costs and adapt to the nonlinear nature of agentic workflows. Scale complete agents such as Claude Code or use sandboxes independently for code execution, all through the same service. See What You Can Build for example use cases.
You use port forwarding to preview a dev server running in the sandbox, reach a loopback-only admin interfaces (such as the Hermes dashboard on port 9119), or connect to any other loopback service the agent starts.
doctl harness-runtime port-forward opens a local TCP listener on your machine and tunnels it to a port inside the session’s sandbox over an authenticated WebSocket. You connect to localhost:<local-port> and traffic flows to the matching port in the sandbox. Nothing in the sandbox is published to the internet. The tunnel exists only while the command runs, and only you (or another authenticated caller with access to the session) can use it.
- Preview a dev server. The agent starts a dev server on port
3000in the sandbox. Rundoctl harness-runtime port-forward <session> 3000and openhttp://127.0.0.1:3000. - Reach the Hermes dashboard on port
9119. See Run a Hermes Agent. - Connect to any other loopback service the agent starts inside the sandbox.
If you ask the agent, How do I preview this? or How do I reach this server?, the agent replies with a ready-to-run doctl harness-runtime port-forward command that already includes the session ID.
The command has the following syntax:
doctl harness-runtime port-forward <session> [<local-port>:]<remote-port> [[<local-port>:]<remote-port> ...]<session> is either a session name or a session ID. Press Ctrl+C to stop. A paused session resumes automatically before the tunnel opens. If the session is bound to a reuse trigger, the trigger’s firings fail until you pause the session again. For details, see Choose a Session Mode.
Each port argument takes one of the following:
<port>: Forward the same port on both ends.<local>:<remote>: Bind<local>on your machine and forward to<remote>in the sandbox.0:<remote>: Let your operating system pick a free local port. The chosen port is printed on theForwardingline for that pair.
For example, forward one port with the same number on both ends:
doctl harness-runtime port-forward sess_abc123 8080The output looks like this:
Forwarding 127.0.0.1:8080 -> port 8080 in session sess_abc123
Ready. Press Ctrl-C to stop.To remap the local port, and forward several ports in one command, run:
doctl harness-runtime port-forward sess_abc123 3000 8080:8000 0:9119That command sets up three tunnels at once:
3000forwards local3000to remote3000.8080:8000forwards local8080to remote8000.0:9119lets the operating system pick a free local port for remote9119. The picked port is printed on theForwardingline for that pair.
Change the local bind address (for example, to expose the tunnel to another host on your LAN) with --address:
doctl harness-runtime port-forward --address 0.0.0.0 sess_abc123 8080The default bind address is 127.0.0.1.
Port forwarding has the following rules and limits:
- Remote port range: Must be between
1024and65535. A request outside that range is rejected with a403. - Port 22 is not usable: It is below the port floor, and no template runs an SSH daemon by default.
- Local listener: Binds to
127.0.0.1by default. Use--addressto change it. One listener per port pair. - Connections: One WebSocket per TCP connection through the tunnel.
- Authorization: Same as reading the session itself. The caller must have access to the session in that team.
- Lifetime: The tunnel is up only while the command runs. It is not a published URL and cannot be shared with an unauthenticated user.