LinuxOnTab boots a real x86 Linux kernel and Alpine userland inside your browser using WebAssembly and the v86 emulator. A zero-install, local-first, in-browser Linux terminal — a lightweight Docker alternative for instant sandboxes, teaching, demos, and disposable shells.
LinuxOnTab is a browser-only Linux desktop. Open the page and a real x86 Linux kernel boots inside the v86 WebAssembly emulator, presenting an Alpine Linux shell over xterm.js. Every system call hits a real kernel running in your tab — not a transpiled toy, not a remote container, not a cloud VM you have to log into.
Networking is opt-in. When you want it, the guest connects to a backend over a WISP v1 WebSocket and gets full TCP egress. You can then expose in-guest ports back to your host over a pairing-code tunnel and SSH, SCP, SFTP, or rsync into the browser tab as if it were any other Linux box.
Boots an actual x86 kernel image plus an Alpine userland inside the v86 WebAssembly emulator — not a faked terminal.
Code runs in your tab. Your data lives in IndexedDB. Close the tab and the VM is gone — no orphan containers, no zombie processes on your laptop.
Static site over HTTPS. No daemon, no kernel modules, no admin rights, no package install. Works on Mac, Windows, Linux, ChromeOS.
Full Alpine package ecosystem: apk add python3 nodejs git openssh syncthing — install whatever you need, persist via snapshot.
Save full VM state to IndexedDB. Restore on next boot with installed packages, files, and shell history intact.
Tunnel guest TCP ports out through a pairing-code WebSocket bridge. Run ssh -p 2222 root@localhost on your Mac and you're in.
Anything you drop in ~/public in the guest is browsable from any HTTPS client via a 4-character pairing code.
Share folders peer-to-peer over Nostr relays. No accounts, no servers — just keypairs and public manifests.
Once the page and ISO are cached, the VM boots without a network connection. Networking inside the guest is the only piece that needs the internet.
man page — no SSH keys, no cloud accounts, no install.python3 -m http.server, a static site, a tiny API) and expose it via the tunnel CDN.docker run -it alpine sh just to get a quick shell — open a tab instead.~/public, share linuxontab.com/viewer/?code=XXXX.For ephemeral, browser-side Linux work, LinuxOnTab and Docker are not really competitors — they cover different ground. Here's the rough split:
| LinuxOnTab | Docker | Cloud shell (e.g. SSH VM) | |
|---|---|---|---|
| Install required | No | Yes (daemon) | No (but account needed) |
| Account / signup | No | No | Yes |
| Real Linux kernel | Yes (in WASM) | Yes (host kernel) | Yes |
| Runs offline | Yes | Yes | No |
| State after closing tab | IndexedDB snapshots | Persistent volumes | Persistent disk |
| Cleanup overhead | Close the tab | Containers, volumes, networks | Stop / destroy VM |
| Resource cost | Browser RAM only | Daemon + kernel resources | $ per hour |
| Sandboxed from host | Browser-grade | Namespaces only | Network-isolated |
| Best for | Disposable shells, teaching, demos | Reproducible builds, prod images | Long-running compute |
Verdict: LinuxOnTab is a complement to Docker, not a replacement for it. For one-off shells, demos, and "I just need a Linux box for two minutes," it is dramatically faster and lighter than spinning up a container or a VM.
x86 emulator in WebAssembly. Boots real kernel images in any modern browser. The core that makes LinuxOnTab possible.
Minimal, fast-booting userland with a great package manager. Default ISO ships with BusyBox and apk.
Front-end terminal that renders the guest serial console.
Streaming TCP-over-WS protocol. Lets the in-browser kernel speak real TCP through a backend server.
Optional services for DoH, port tunnels, and TCP egress. Source is in this repo — self-host the whole stack if you want.
Stores full VM snapshots client-side, so reload doesn't blow away your work.
The shell page is fully URL-driven. Compose any of the parameters below to launch a pre-configured environment — great for demos, embeds, and one-click reproductions.
?pip=1Boot into Picture-in-Picture mode: floating, resizable terminal panel + fullscreen browser overlay. Combine with ?pipx=&pipy=&pipw=&piph= to set the initial frame rect.
?browser=<url>Override the landing page of the Ctrl+Alt+F2 browser overlay. Bare hosts auto-prefix https://; non-URL strings fall through to a DuckDuckGo search.
?postboot=<cmd-or-url>Run a command (or wget+exec an http(s) script) inside the guest after init has finished. Repeat the param to chain multiple steps in order. Example: ?postboot=https://getclaw.site/install.sh auto-installs claw and drops you into the REPL.
#postboot=<cmd> secretsURL fragment form. Fragments are never sent to the server, never appear in access logs, and don't leak via Referer — so they're the right channel for env-var exports like #postboot=export%20OPENAI_API_KEY%3Dsk-...&postboot=https://getclaw.site/install.sh. The key gets export'd before claw launches.
?reset=1Skip snapshot restore and boot fresh. Useful when a saved state is corrupted or you want a clean slate without clearing IndexedDB by hand. Alias for ?restore=0.
Ctrl+Alt+F1 URL bar · Ctrl+Alt+F2 show browser · Ctrl+Alt+F3 hide browser · Ctrl+Alt+F4 toggle terminal PiP. When an iframe steals focus, use the floating ✕ / ☰ buttons.
window.fsBrowser.{show,hide,setUrl,toggleUrlBar} drives the browser overlay. window.termPip.{show,hide,toggle,set,getRect} drives the terminal PiP.
One link, full layout:/shell/?pip=1&pipx=20&pipy=50&pipw=600&piph=400&browser=https://linuxontab.com&postboot=https://getclaw.site/install.sh
With a secret API key (fragment, never logged):/shell/#postboot=export%20OPENAI_API_KEY%3Dsk-...&postboot=https://getclaw.site/install.sh
Full release notes: Changelog →
Launch the shell and wait for the Alpine login prompt. Then set a root password and install the tools you'll need:
# set root password (replace 'changeme' with something real)
printf 'changeme\nchangeme\n' | passwd root
apk add websocat curl jq openssh-server unbound
The password is required for SSH/SFTP. It lives only in the guest VM — set something you'll remember or save a snapshot right after.
Inside the guest, run tunnel-up.sh to register a 4-character pairing code and start WebSocket bridges from the guest to the relay:
wget -qO- https://linuxontab.com/local/tunnel-up.sh | sh
# → tunnel ready — code: ARXN
By default this exposes ports 22 (SSH/SFTP), 8080 (~/public HTTP), 22000 (Syncthing sync), and 8384 (Syncthing GUI). Pass explicit port numbers to change the set: tunnel-up.sh 22 8080 3000.
Option A — helper script (easiest, requires websocat on your host)
The helper downloads websocat, looks up the pairing code on the relay, and opens a local TCP port that forwards to the guest. Install websocat once (brew install websocat on Mac, apt install websocat on Linux), then:
# opens localhost:2222 → guest port 22
sh <(curl -sS https://linuxontab.com/local/tunnel-listen.sh) ARXN
# SSH
ssh -p 2222 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null root@localhost
# SCP / rsync
scp -P 2222 -o StrictHostKeyChecking=no ./myfile root@localhost:/root/
rsync -avz -e 'ssh -p 2222 -o StrictHostKeyChecking=no' ./folder/ root@localhost:/root/folder/
The script auto-selects the fastest relay endpoint and keeps the local port open until you Ctrl-C it. Run it in a dedicated terminal.
Option B — relay bridged ports (no local install needed)
The relay at linuxontab-tunnel.fly.dev also exposes each registered port directly as a WebSocket endpoint. Any WebSocket-capable TCP client can reach the guest with just the pairing code — no helper script, no local daemon:
# Direct WebSocket endpoints (one per port):
wss://linuxontab-tunnel.fly.dev/port/client?code=ARXN&port=22
wss://linuxontab-tunnel.fly.dev/port/client?code=ARXN&port=8080
# HTTP ports are also proxied over plain HTTPS (no client-side tooling at all):
https://linuxontab-tunnel.fly.dev/port/http/ARXN/8080/
# Check registered ports + connection status:
curl https://linuxontab-tunnel.fly.dev/port/status?code=ARXN
This is the approach used internally by tunnel-listen.sh — it just wraps the WS endpoint in a local TCP listener via websocat. If you have a tool that speaks WebSocket natively (Cloudflare Tunnel, custom proxy, etc.) you can talk to the relay directly without any local helper.
Once the helper script is running (port 2222 open on localhost), connect with any SFTP client:
localhost · Port: 2222root · Password: the one you set in step 1You can now drag-and-drop files between your host and the in-browser Linux VM. The guest filesystem is fully writable; files land in the running VM and persist if you save a snapshot.
Any other SFTP client works the same way: Cyberduck, WinSCP, sftp -P 2222 root@localhost in a terminal, etc.
Drop a floating terminal on any web page by pointing an <iframe> at the shell URL with PiP enabled and a ?browser= URL set to your own site. The terminal floats above your content; your page is visible in the background iframe.
<!-- minimal embed — floating terminal, your page in the background -->
<iframe
src="https://linuxontab.com/shell/?pip=1&pipx=20&pipy=50&pipw=600&piph=400
&browser=https://YOUR-SITE.com"
style="position:fixed;inset:0;width:100%;height:100%;border:0;z-index:9999"
allow="cross-origin-isolated"
></iframe>
Key parameters:
pip=1 — enable Picture-in-Picture mode (floating terminal + browser overlay)pipx / pipy — initial position of the terminal frame in px from top-leftpipw / piph — initial width / height of the terminal frame in pxbrowser=URL — URL loaded in the background browser overlay (your page, a demo, docs…)postboot=URL — script or command to run in the guest after boot (e.g. auto-install your CLI)#postboot=export KEY=value — hash fragment form: injects secrets that never hit server logsUsers can drag the terminal window, resize it, or press Ctrl-Alt-F2 / Ctrl-Alt-F3 to show/hide the browser overlay. See the URL parameters reference above for the full list of options.
Real kernel. LinuxOnTab boots an x86 Linux kernel image and an Alpine userland inside the v86 WebAssembly emulator. Every syscall, every /proc entry, every man page is genuine.
For ephemeral browser-side shells: yes. LinuxOnTab gives you a disposable Linux box without a daemon, an install, or a cleanup step. For reproducible production builds and image distribution, stick with Docker — the two are complementary.
Once the page and ISO have been fetched, the VM runs entirely in your browser and survives going offline. Networking inside the guest needs internet, but the kernel itself doesn't.
Yes. Run the in-guest tunnel-up.sh script to register a pairing code, then run tunnel-listen.sh on your host. SSH, SCP, SFTP, and rsync all work as if the guest were a remote box.
Snapshots are stored in IndexedDB on demand. Save before closing the tab and you'll boot back into the same state next time.
The kernel runs inside the browser's WebAssembly sandbox. It has no direct access to your filesystem, devices, or other tabs. Network egress only happens through the explicit WISP/WebSocket tunnel — and you can disable that entirely.
Yes. The shell page, helper scripts, and backend services are all in the public LinuxOnTab repo. The v86 emulator is upstream and BSD-licensed.
Replit and Codespaces run on remote servers — you're paying for a cloud VM. WebContainers (StackBlitz) runs Node.js in the browser via a custom kernel — fast, but it's not a real Linux kernel. LinuxOnTab is the rare combination: real kernel + fully local + no account.
Get notified about new features, snapshot releases, and early access to upcoming tools.