WebSocket + Web terminal emulator backed by a shared QEMU Linux VM.
접속하는 누구나 sudo 명령어를 사용할 수 있으며, 일부 위험한 명령어는 필터링됩니다.
VM 이미지가 손상되면 자동으로 초기 상태로 재시작됩니다.
| Tool | Version | Notes |
|---|---|---|
| Node.js | 18+ | nodejs.org |
| QEMU | any recent | qemu-system-x86_64 must be in PATH |
| qemu-img | same package as QEMU | used to create the disk image |
| wget | any | used by the image creation script |
| mtools | any | mcopy used by the image creation script |
| bash | 4+ | for the setup script |
Linux (Debian/Ubuntu):
sudo apt install qemu-system-x86 qemu-utils wget mtoolsmacOS (Homebrew):
brew install qemu wget mtoolsWindows: Use Docker (see below) or WSL2 with the Linux instructions above.
# 1. Clone and enter the project
git clone <repo-url> democratic-linux
cd democratic-linux
# 2. Install Node dependencies
npm install
# 3. Build the base Alpine Linux image (~2–5 min, one-time)
bash scripts/create-image.sh
# 4. Start the server
npm startOpen http://localhost:3000 in your browser.
# 1. Clone the project
git clone <repo-url> democratic-linux
cd democratic-linux
# 2. Build and start
docker compose up --buildThe first run will download Alpine Linux and build the base image automatically.
Open http://localhost:3000 once you see Democratic Linux running at http://localhost:3000.
| Variable | Default | Description |
|---|---|---|
HTTP_PORT (or PORT) |
3000 |
HTTP / WebSocket listen port. HTTP_PORT wins if both are set. |
QEMU_BIN |
qemu-system-x86_64 |
Path to the QEMU binary |
QEMU_MEM |
256M |
VM memory |
QEMU_CPUS |
1 |
VM virtual CPU count |
# Example: more memory, custom port
PORT=8080 QEMU_MEM=512M npm startBrowser (xterm.js)
│ WebSocket /ws
▼
server.js (Express + ws)
│ TCP 127.0.0.1:4444
▼
QEMU VM (Alpine Linux, serial console)
- All connected browsers share one terminal session (broadcast model).
- Input from any browser is forwarded to the VM; VM output is broadcast to every browser.
- On every boot,
vm/base.qcow2is copied tovm/work.qcow2so the VM always starts clean. - If QEMU exits unexpectedly, the VM manager automatically resets and relaunches after 3 s.
Dangerous inputs are dropped before reaching the VM:
| What is blocked | Why |
|---|---|
Ctrl-A byte (0x01) |
Prevents QEMU monitor escape sequence takeover |
| Fork bomb pattern `:(){: | :&};:` |
Everything else — including rm -rf /, mkfs, dd — is intentionally allowed.
The VM resets to a clean state on every restart, so destruction is temporary.
To add more blocked patterns, edit src/filter.js:
const BLOCKED_PATTERNS = [
/:\(\)\s*\{\s*:|&\s*\}/, // fork bomb
// add your own RegExp here
];
const BLOCKED_SUBSTRINGS = [
// 'shutdown', 'reboot', // uncomment to block these
];The VM resets automatically whenever:
- QEMU process exits (crash,
poweroff,rebootfrom inside the VM, etc.)
On reset:
vm/base.qcow2is copied fresh tovm/work.qcow2.- QEMU is relaunched.
- All connected browsers receive a yellow banner: VM is resetting, please wait…
To rebuild the base image from scratch:
rm vm/base.qcow2
bash scripts/create-image.shdemocratic-linux/
├── src/
│ ├── server.js # HTTP + WebSocket server (entry point)
│ ├── vm.js # QEMU process manager (start / auto-reset)
│ └── filter.js # Input filter (fork bombs, Ctrl-A, etc.)
├── public/
│ └── index.html # xterm.js web terminal frontend
├── scripts/
│ └── create-image.sh # One-time Alpine Linux image builder
├── vm/ # base.qcow2 lives here (git-ignored)
├── package.json
├── Dockerfile
└── docker-compose.yml