Sessionboxer

Remote access

Your own address: Tailscale, a named Cloudflare Tunnel or a VPS

Serve Sessionboxer on an address you control: a Tailscale or Headscale network, a named Cloudflare Tunnel with Access in front, or a VPS behind Caddy, with the environment variables each needs.

The address itself is your choice; what Sessionboxer needs is HTTPS when you are not on localhost (browsers only allow the clipboard, notifications and the VS Code pane from a secure context) and SESSIONBOXER_PUBLIC_URL set to the URL you type in the browser, so that pairing links, the printed login link and the GitHub OAuth callback carry it. Settings → Devices says which address the Control Plane believes it is reached at.

  • Private network: Tailscale (or a Headscale server you host). Both the machine that runs Sessionboxer and your phone or laptop join a private WireGuard network; nothing is exposed to the internet and only your devices can even connect — the phone needs the Tailscale app. tailscale up, then tailscale serve --bg 4000 gives https://<server>.<tailnet>.ts.net with a real certificate, tailnet-only; set SESSIONBOXER_PUBLIC_URL to that URL and SESSIONBOXER_TRUST_PROXY=1. Headscale cannot issue certificates for its MagicDNS names, so there serve HTTPS yourself: Caddy on the server (reverse_proxy 127.0.0.1:4000, certificate via a DNS-01 challenge or tls internal with its root installed on the phone) plus SESSIONBOXER_PUBLIC_URL and SESSIONBOXER_TRUST_PROXY=1, or the Control Plane's own SESSIONBOXER_TLS_CERT / SESSIONBOXER_TLS_KEY with SESSIONBOXER_HOST=<tailnet IP>.
  • A permanent URL that works from any browser: a named Cloudflare Tunnel. The grown-up version of the quick tunnel: cloudflared tunnel on the server keeps an outbound connection to Cloudflare, which terminates TLS on a hostname of a domain you have there and forwards to http://127.0.0.1:4000; put Cloudflare Access in front for a second login (email code, Google, GitHub). Set SESSIONBOXER_PUBLIC_URL=https://box.yourdomain.tld and SESSIONBOXER_TRUST_PROXY=1. Cloudflare drops idle WebSockets after 100 s; the Control Plane pings every 25 s, so terminals and the desktop survive.
  • The server is a VPS with a public address. Run Caddy (or nginx) on it with automatic certificates, proxying to 127.0.0.1:4000, and again SESSIONBOXER_PUBLIC_URL + SESSIONBOXER_TRUST_PROXY=1. Consider still joining it to a tailnet and firewalling :443 to the tailnet, since the access token is then the only wall.

SESSIONBOXER_TRUST_PROXY=1 makes the Control Plane believe X-Forwarded-For, X-Forwarded-Proto and X-Forwarded-Host (the device list then shows the real client address and cookies are marked Secure); leave it unset when nothing sits in front. SESSIONBOXER_HOST=0.0.0.0 binds every interface, for the rare case where the proxy runs on another machine. From another machine the CLI uses SESSIONBOXER_URL and SESSIONBOXER_TOKEN (or sessionboxer pair on the server to get a link for a browser).

This chapter is generated from docs/GUIDE.md in the Sessionboxer repository. Found a mistake? Open an issue.