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, thentailscale serve --bg 4000giveshttps://<server>.<tailnet>.ts.netwith a real certificate, tailnet-only; setSESSIONBOXER_PUBLIC_URLto that URL andSESSIONBOXER_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 ortls internalwith its root installed on the phone) plusSESSIONBOXER_PUBLIC_URLandSESSIONBOXER_TRUST_PROXY=1, or the Control Plane's ownSESSIONBOXER_TLS_CERT/SESSIONBOXER_TLS_KEYwithSESSIONBOXER_HOST=<tailnet IP>. - A permanent URL that works from any browser: a named Cloudflare Tunnel. The grown-up version of the quick tunnel:
cloudflared tunnelon the server keeps an outbound connection to Cloudflare, which terminates TLS on a hostname of a domain you have there and forwards tohttp://127.0.0.1:4000; put Cloudflare Access in front for a second login (email code, Google, GitHub). SetSESSIONBOXER_PUBLIC_URL=https://box.yourdomain.tldandSESSIONBOXER_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 againSESSIONBOXER_PUBLIC_URL+SESSIONBOXER_TRUST_PROXY=1. Consider still joining it to a tailnet and firewalling:443to 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.