_$ LinuxOnTab

_$ Real Linux. In a browser tab.
No install. No server. No Docker.

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.

Launch Linux (in window) → Launch Linux (new tab) How it works
Real x86 kernel Runs offline Open source stack Free, no signup Get notified of updates →

What is LinuxOnTab?

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.

Features

Real Linux kernel

Boots an actual x86 kernel image plus an Alpine userland inside the v86 WebAssembly emulator — not a faked terminal.

Local-first

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.

Zero install

Static site over HTTPS. No daemon, no kernel modules, no admin rights, no package install. Works on Mac, Windows, Linux, ChromeOS.

apk package manager

Full Alpine package ecosystem: apk add python3 nodejs git openssh syncthing — install whatever you need, persist via snapshot.

Persistent snapshots

Save full VM state to IndexedDB. Restore on next boot with installed packages, files, and shell history intact.

SSH from your host

Tunnel guest TCP ports out through a pairing-code WebSocket bridge. Run ssh -p 2222 root@localhost on your Mac and you're in.

Public file viewer

Anything you drop in ~/public in the guest is browsable from any HTTPS client via a 4-character pairing code.

Nostr-backed social layer

Share folders peer-to-peer over Nostr relays. No accounts, no servers — just keypairs and public manifests.

Works offline

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.

Use cases

LinuxOnTab vs Docker vs cloud shells

For ephemeral, browser-side Linux work, LinuxOnTab and Docker are not really competitors — they cover different ground. Here's the rough split:

LinuxOnTabDockerCloud 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 snapshotsPersistent volumes Persistent disk
Cleanup overhead Close the tabContainers, volumes, networksStop / destroy VM
Resource cost Browser RAM onlyDaemon + kernel resources$ per hour
Sandboxed from host Browser-gradeNamespaces only Network-isolated
Best for Disposable shells, teaching, demosReproducible builds, prod imagesLong-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.

Technology

v86

x86 emulator in WebAssembly. Boots real kernel images in any modern browser. The core that makes LinuxOnTab possible.

Alpine Linux

Minimal, fast-booting userland with a great package manager. Default ISO ships with BusyBox and apk.

xterm.js

Front-end terminal that renders the guest serial console.

WISP v1 over WebSocket

Streaming TCP-over-WS protocol. Lets the in-browser kernel speak real TCP through a backend server.

Cloudflare Workers + Fly.io

Optional services for DoH, port tunnels, and TCP egress. Source is in this repo — self-host the whole stack if you want.

IndexedDB

Stores full VM snapshots client-side, so reload doesn't blow away your work.

URL parameters & embedding

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=1

Boot 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> secrets

URL 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=1

Skip 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.

Hotkeys

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.

JS API

window.fsBrowser.{show,hide,setUrl,toggleUrlBar} drives the browser overlay. window.termPip.{show,hide,toggle,set,getRect} drives the terminal PiP.

Demo URL

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 →

Quickstart

1. Boot & set a password

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.

2. Open a tunnel

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.

3. Connect from your host — two approaches

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.

4. SFTP with FileZilla

Once the helper script is running (port 2222 open on localhost), connect with any SFTP client:

  1. Open FileZilla → File › Site Manager › New Site
  2. Protocol: SFTP – SSH File Transfer Protocol
  3. Host: localhost  ·  Port: 2222
  4. Logon type: Normal  ·  User: root  ·  Password: the one you set in step 1
  5. Click Connect — accept the host key warning (the guest key is ephemeral)

You 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.

5. Embed LinuxOnTab in your own page

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:

Users 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.

Frequently asked questions

Is this a real Linux kernel or some kind of fake terminal?

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.

Is it a Docker alternative?

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.

Does it work offline?

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.

Can I SSH into the in-browser Linux from my Mac / Linux host?

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.

Is my data persistent across reloads?

Snapshots are stored in IndexedDB on demand. Save before closing the tab and you'll boot back into the same state next time.

What about security?

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.

Is the source open?

Yes. The shell page, helper scripts, and backend services are all in the public LinuxOnTab repo. The v86 emulator is upstream and BSD-licensed.

How is this different from Replit / Codespaces / WebContainers / cloud IDEs?

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.

Stay in the loop

Get notified about new features, snapshot releases, and early access to upcoming tools.