comparisons
tmux in a browser: three ways that actually work
ttyd or wetty behind your own reverse proxy, tmate's web link, or a purpose-built client — the real setup, trade-offs, and an actual ttyd + nginx recipe.
There are three honest ways to reach a tmux session from a browser: wrap it in ttyd or wetty
and put your own reverse proxy in front, use tmate's built-in web link for a quick read-only
share, or run a client purpose-built for it. All three work. They differ in who runs the server,
what's listening on a port, and whether the result is usable on a phone — not in whether tmux
itself shows up on screen.
Option 1: ttyd or wetty behind your own proxy
ttyd and wetty do the same job: wrap a terminal command in a WebSocket and serve xterm.js to
render it. Neither is tmux-specific — point either at tmux attach and the browser gets exactly
what your terminal would show. Both are free, open source, and small enough to read in an
afternoon.
The catch is in the name: you run the server. That means a reverse proxy, TLS, and authentication are your responsibility, not the tool's. Here's the actual recipe, using ttyd:
# macOS
brew install ttyd
# Debian/Ubuntu
sudo apt install ttyd
# wrap tmux, don't wrap a bare shell — this attaches to (or creates) a session named "main"
ttyd -p 7681 -i 127.0.0.1 tmux new-session -A -s mainBinding to 127.0.0.1 matters: it keeps ttyd unreachable from the network directly, so the only
path in is through nginx, where auth and TLS actually live.
server {
listen 443 ssl;
server_name term.example.com;
ssl_certificate /etc/letsencrypt/live/term.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/term.example.com/privkey.pem;
auth_basic "tmux";
auth_basic_user_file /etc/nginx/.htpasswd;
location / {
proxy_pass http://127.0.0.1:7681;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
}sudo htpasswd -c /etc/nginx/.htpasswd yourname
sudo certbot --nginx -d term.example.com
sudo nginx -t && sudo systemctl reload nginxThat's the whole thing: a session reachable at https://term.example.com, password-gated, over
TLS. It's genuinely not much machinery, and it's machinery you fully own — no third-party relay
sees your terminal at any point.
An open inbound port is now part of your threat model
This setup requires a port open to the internet (443, via nginx) and a DNS record pointing at your machine. That's the trade: full control, in exchange for being the one who patches nginx, rotates the htpasswd file, and notices if certbot's renewal silently fails.
Option 2: tmate's web link
tmate forks a second, purpose-built tmux server and hands out both an SSH command and a read-only
web URL for the same session — tmate show-messages prints both. No reverse proxy, no port to
open on your machine, nothing to patch: the web view is served from tmate's own infrastructure
(or your own, if you self-host the relay).
$ tmate
tmate identifies remote session as 3f8a2c1e...
ssh session read only: ssh [email protected]
web session read only: https://tmate.io/t/ro-3f8a2c1eThe web link is genuinely the fastest path from "I have a terminal" to "someone else can see it in a browser" of any option here — no install on the viewer's end, no account. It's also read-only by default, tied to that one ad-hoc session, and gone the moment you exit tmate. That's by design: tmate is built for sharing a session in progress, not for coming back to your own work tomorrow. More on that trade-off in tmate alternative.
Option 3: a purpose-built client
The gap both options above share is that neither was designed around a phone. ttyd and wetty
render xterm.js, which assumes a keyboard with modifier keys; tmate's web link is read-only and
desktop-oriented. A client built specifically for reaching your own tmux sessions from a browser —
mtmux is one — starts from different defaults: it dials out from your machine instead of listening
for inbound connections, so there's no port to open; it encrypts end-to-end (x25519 key agreement,
ChaCha20-Poly1305 frames) through a relay that can't read the session; and the UI is built for
touch, with the prefix key and modifiers as an on-screen row instead of a keyboard shortcut you
don't have. Setup is npm i -g mtmux and pointing it at a session, not a proxy config.
| Setup | Inbound port | Encryption | Mobile UI | Persistent session | Price | |
|---|---|---|---|---|---|---|
| ttyd / wetty + proxy | nginx, TLS, htpasswd | yes, one you open | TLS to your proxy | none — desktop keyboard assumed | yes, if tmux itself persists | free, open source |
| tmate web link | install tmate, run it | no — outbound to tmate's relay | SSH transport; relay isn't zero-knowledge unless self-hosted | read-only, no touch input | ends when tmate exits | free, open source (self-hostable) |
| Purpose-built (mtmux) | npm i -g mtmux | none — dials out | x25519 + ChaCha20-Poly1305, zero-knowledge relay | touch-first, built for phone | attaches to your existing tmux server | free (1 machine + 2 devices), Pro $8/mo |
Where each one genuinely wins
If you already run and trust your own reverse proxy, and you only ever need this from a desktop browser, ttyd is less machinery than anything else here — it's a single static binary and a config block you already know how to write. If what you need is to show someone your terminal for the next ten minutes, tmate's web link is faster than any of the alternatives and requires literally nothing on the viewer's side. If what you want is your own sessions, reachable from your phone specifically, with no inbound port to maintain, that's the gap the purpose-built option closes — full trade-offs on the comparison page and setup in the docs.
Can I view a tmux session in a browser without installing anything extra?
Not directly — tmux itself has no browser output. You need something in between: ttyd/wetty wrapping the command, tmate's hosted web link, or a purpose-built client. All three require installing something on the machine running tmux; none require anything extra to just view from a desktop browser.
Is ttyd secure enough to expose to the internet directly?
Not on its own — ttyd has no built-in authentication in its default mode. Bind it to
127.0.0.1 and put a reverse proxy with TLS and auth in front, as in the recipe above, rather
than exposing its port directly.
Does tmate's web link let me type, or only watch?
By default it's read-only — show-messages prints a ro- prefixed URL for read-only viewing.
tmate also has a read-write SSH session for participants you actually want typing alongside you,
but the plain web link is for watching.
Does a browser-based tmux client work well on a phone?
It depends which one. ttyd and wetty render a standard terminal that assumes a physical keyboard, so the tmux prefix key and modifiers are awkward on a soft keyboard. That specific problem — and what to do about it — is covered in tmux from your phone.
What's the difference between tmate and a browser-based tmux viewer?
tmate creates a new, separate tmux session for sharing; it isn't a window into a session you
already have running. A browser client that attaches to your existing tmux server — like ttyd
pointed at tmux attach, or a purpose-built client — shows you the actual session, not a copy.
Put this to work — mtmux attaches to the tmux server you already run.