Real Linux. In a browser tab. No install. No server. No Docker
摘要
LinuxOnTab 通过 v86 WebAssembly 模拟器在浏览器中引导真实 x86 Linux 内核和 Alpine 用户空间,提供 xterm.js 终端、apk 包管理、IndexedDB 快照持久化,以及可选的 WISP WebSocket 隧道实现 SSH / SFTP 端口暴露和 TCP 出口。支持离线运行、零安装静态站点、可通过 URL 参数嵌入或预配置环境(如 ?pip = 1、?postboot= 命令),并附有与 Docker、云 shell 的对比表格、使用场景(一次性 shell、教学、演示)和常见问题解答。
荐读理由
你打开页面就能在浏览器 tab 里启动真实 x86 Alpine Linux 内核,用 apk 装包、IndexedDB 保存 snapshot 持久化,跑 tunnel-up.sh 后从 host 用 SSH/SCP 连进去测试脚本,关 tab 就清零。
原文
_$ 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
Disposable sandbox. Try a CLI tool, run an untrusted script, evaluate a package, then close the tab and forget about it.
Teaching Linux. Hand a student a URL. They get a real shell, a real kernel, a real
manpage — no SSH keys, no cloud accounts, no install.Demos and reproducers. Share a snapshot URL that boots straight into the broken state. Reviewers don't need to clone anything.
Local-first dev environment. Run a small server (
python3 -m http.server, a static site, a tiny API) and expose it via the tunnel CDN.Lightweight Docker alternative. When you'd reach for
docker run -it alpine shjust to get a quick shell — open a tab instead.Self-host a public folder. Drop files in
~/public, sharelinuxontab.com/viewer/?code=XXXX.Air-gapped tinkering. Boot once with a network connection, save a snapshot, then keep working from a plane / cafe / sealed environment.
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:
| 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.
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:
Open FileZilla → File › Site Manager › New Site
Protocol: SFTP – SSH File Transfer Protocol
Host:
localhost· Port:2222Logon type: Normal · User:
root· Password: the one you set in step 1Click 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:
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 logs
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.
这条对你有帮助吗?