DorkOS
Self-Hosting

Reverse Proxy

Put DorkOS on your own domain with HTTPS, using nginx or Caddy

Reverse Proxy

Want DorkOS to live at dorkos.example.com instead of a bare port number, with a real HTTPS certificate? That's what a reverse proxy does: it sits in front of DorkOS and forwards traffic to it. This page covers the two most common ones, Caddy and nginx.

You only need this page if you're self-hosting on your own domain, or running DorkOS alongside other services on the same machine. Just testing on localhost? Skip it. Want remote access without setting up a domain at all? See Tunnel Setup instead.

DorkOS streams agent output live as it works. Your proxy has to let that through, and default settings get it wrong in two different ways:

  • Buffering. Proxies hold a response until they have "enough" of it, which turns live output into one delayed dump at the end.
  • Upgrades. The DorkOS app opens its live streams as WebSockets, and most proxies do not forward a WebSocket upgrade unless you tell them to. Get this wrong and the failure is nasty and quiet: the app loads, buttons work, your agent really does run — and nothing it says ever appears on screen.

The configs below handle both. Don't trim them down.

Default proxy settings will break live streaming, and the WebSocket half fails silently. Copy the whole config for your proxy rather than just the parts that look relevant.

Proxy Configuration

Caddy handles HTTPS certificates automatically, and forwards WebSocket upgrades on its own — there is nothing to add for that.

dorkos.example.com {
    reverse_proxy localhost:4242 {
        flush_interval -1
    }
}

flush_interval -1 disables response buffering, which is what live streaming needs.

Running a proxy with login off? Name your domain, or every API call comes back 403 Forbidden. DorkOS answers only to addresses it trusts, and your proxy passes its own address through. Add it:

DORKOS_TRUSTED_HOSTS=dorkos.example.com

Separate several names with commas and leave the port off. Turning on login covers most of it the other way: DorkOS trusts your sign-in instead of the address for ordinary requests and for live streams. Set this anyway. The embedded terminal is authorized by holding a hard-to-guess id rather than by your sign-in, so it always checks the address — with login on and this unset, the app works and the terminal will not open. See Securing Your Instance.

Running DorkOS on your own domain, behind this proxy? Set DORKOS_PUBLIC_URL to that domain (for example https://dorkos.example.com). Without it, DorkOS advertises its internal bind address instead of your real URL wherever it needs to share a link to itself. See Deployment for how to set environment variables.

If DorkOS itself is running in Docker, localhost:4242 in the configs above needs to become the container's name (for example dorkos:4242) or its address on the Docker network instead. See Docker for a worked example.

Key streaming settings (nginx)

Most people never touch these once the config above is working. Here's what each line does, if you're curious:

Prop

Type

The app loads but no reply ever appears? Your proxy is not forwarding WebSocket upgrades. Check the two Upgrade/Connection lines above, including the map block. A 403 in the browser console instead means DorkOS does not trust the address you are reaching it on — set DORKOS_TRUSTED_HOSTS to your domain, as described above.

Common Issues

SSE events arrive in batches instead of real-time

Cause: Response buffering is enabled in the proxy.

Fix: Set proxy_buffering off (nginx) or flush_interval -1 (Caddy).

Connection drops after 60 seconds

Cause: Default proxy timeout is too short for SSE.

Fix: Increase proxy_read_timeout to at least 3600s.

502 Bad Gateway on long requests

Cause: Upstream timeout is shorter than the Claude response time.

Fix: Increase both proxy_read_timeout and proxy_send_timeout.

HTTPS with Let's Encrypt

Point your domain's DNS to the server and Caddy obtains and renews certificates automatically. The Caddy config above already handles this: no separate step needed.

Next Steps