Remote access¶
Run terminux on one machine (a headless server, a desktop tower, a NUC, a Raspberry Pi) and connect from another (your laptop). Your shells live on the server: long-running builds keep going while you switch networks, sleep your laptop, or move to a different room.
The architecture is intentionally thin:
- Server (
--server) is the existing Starlette/uvicorn backend with a persistent auth token and a connect-banner. The full frontend (xterm.js, sidebar, persistence) is served from the same process. - Client (
--connect URL) is a native pywebview window pointed at the server's URL. No local backend, no local PTYs. Everything runs on the remote.
The recommended setup: SSH port-forward¶
The token is a 9-letter Google-Meet-style code (e.g. abc-def-ghi),
which is short enough to dictate or paste but not strong enough for
unrestricted exposure on the open internet. Use an SSH tunnel and keep
the server bound to loopback:
uv run terminux --server --port 8443
# prints, prominently:
#
# terminux server listening — connect with:
# http://127.0.0.1:8443/?t=abc-def-ghi
The token is persisted to
~/.local/share/terminux/server.token (Linux) or
~/Library/Application Support/terminux/server.token (macOS) with
mode 0600. The same URL keeps working across server restarts;
bookmark it.
That completes the common case. SSH already solved the hard parts, so there are no new ports, certificates, or auth layers to manage.
Multiple clients¶
The server's WebSocket fan-out already supports multiple subscribers per
PTY, so opening a second --connect window from a phone or a second
laptop attaches to the same shells. Typing in one window is visible in
all of them, like tmux attach from multiple sessions.
What lives where¶
State on the server, kept across client disconnects, sleeps, and client reboots:
- Workspaces, tabs, their working directories
- Live shells and the processes they're running
- Scrollback (up to 2 MB per tab, replayed on reconnect)
- Sidebar order, font size, UI prefs
State on the client, per connection:
- Window position and size: each launch uses the defaults. Per-client geometry persistence is not implemented in v1.
- Selection, the fuzzy-switcher's typed query, and other in-page state, which reset when the window closes.
File drag-and-drop¶
Dropping a file from Finder / Files / your file manager onto a tab works
the same way in --connect mode as it does locally. Under the hood the
client POSTs the dropped path(s) to POST /api/paste-paths on the
server, which writes the shell-quoted path to the currently active
terminal: the same UX and shell quoting, plus one HTTP round trip.
Bypassing SSH: --host 0.0.0.0¶
If you trust your network (a home LAN, a Tailscale tailnet, a WireGuard mesh) and want a direct connection without setting up SSH forwarding, you can bind the server to a non-loopback address:
The token is now your only line of defense. The 9-letter token plus the per-IP rate limiter (10 failures → 60 s lockout) is enough to frustrate casual brute-force, but it's not enough for raw open-internet exposure. Restrict the route to your trusted network at the OS / router firewall.
For the open internet, terminate TLS upstream (Caddy, nginx, Cloudflare Tunnel) and put a real auth layer in front. terminux itself does not ship TLS support and intentionally keeps the token short.
Security model summary¶
| Setup | Token strength | Recommended use |
|---|---|---|
| SSH tunnel + loopback (default) | Fine: token guards a loopback-bound port | Any remote use over the open internet |
--host 0.0.0.0 on a trusted LAN / VPN |
Fine: 43 bits + per-IP lockout | Home network, Tailscale, WireGuard |
--host 0.0.0.0 on the open internet |
Not enough: front it with a real auth layer | Avoid unless you've layered something in front |
Lifecycle / running it as a service¶
terminux doesn't ship with a daemonizer. On a personal server, the simplest options are:
- systemd user service: a single
WantedBy=default.targetunit that runsuv run terminux --server. The token file persists across service restarts, so your bookmarked URL keeps working. - tmux session:
tmux new-session -d -s terminux 'uv run terminux --server'. Trivial, and it keeps running after logout. - macOS launchd: a per-user
LaunchAgentplist if you want it to auto-start at login.
Pick whichever matches the host's idiom. The watchdog and --debug /
--trace flags described in Debugging knobs
work the same in server mode and write to stderr; point that at a file
in your service definition.
Known limitations (v1)¶
- No predictive local echo. Each keystroke is a WebSocket frame to the server; on a high-latency WAN (50 ms+ RTT) typing will feel slightly laggy. For high-latency cases, SSH + mosh + tmux gives better typing UX. terminux's strength is the workspace/tab model on LAN or low-latency WAN.
- No transport security in terminux itself. Use SSH or a TLS
terminator upstream. Do not run
--host 0.0.0.0straight on the open internet. - Per-client window geometry is not persisted yet: every
--connectlaunch opens at default size. - No "rotate token" CLI:
rm ~/.../server.tokenand restart the server to force a new one. The previous URL stops working.