Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ jobs:
with:
node-version: "20"
cache: npm
- run: sudo apt-get update && sudo apt-get install -y libslirp-dev libglib2.0-dev
- run: npm ci --ignore-scripts
- run: npm run build
- run: npm run test:unit
Expand Down Expand Up @@ -101,6 +102,7 @@ jobs:
with:
node-version: "20"
cache: npm
- run: sudo apt-get update && sudo apt-get install -y libslirp-dev libglib2.0-dev
- run: npm ci --ignore-scripts
- run: npm run build
- run: node --test dist/test/native.test.js
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-prebuilds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ jobs:
with:
node-version: "20"
cache: npm
- run: sudo apt-get update && sudo apt-get install -y g++ libslirp-dev
- run: sudo apt-get update && sudo apt-get install -y g++ libslirp-dev libglib2.0-dev
- run: npm ci --ignore-scripts
- name: Build native addon
env:
Expand Down
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,8 @@ Linux/KVM runtime:
- Linux x64 npm installs use the bundled native prebuild by default
- `python3`, `make`, and `g++` are only needed when forcing or falling back to a
local `node-gyp` build
- `libslirp-dev` and `libglib2.0-dev` are needed when forcing a local build
that should support `network: "slirp"` / `--net slirp`
- `mkfs.ext4`, `mount`, `umount`, `truncate`, `install`
- `ip`, `iptables`, `sysctl` for `network: "auto"` / `--net auto`
- `git` for `--repo` / SDK repo builds
Expand Down Expand Up @@ -385,8 +387,8 @@ macOS/HVF runtime:
| Run `--image alpine:3.20` from cache | Yes | Yes | Yes | Cache must already contain the prepared rootfs |
| Run unsupported `--image ...` from cold cache | Yes | Yes, with WSL2 | Yes, when the OCI image has arm64 layers | OCI network access and ext4 builder |
| Interactive shell / getty console | Yes | Yes | Yes | Host terminal |
| `apk add`, DNS, outbound network | Yes | Yes | Yes | Linux TAP/NAT or Slirp on Windows/macOS |
| TCP port forwarding | Yes | Yes | Yes | Linux TAP/NAT or Slirp on Windows/macOS |
| `apk add`, DNS, outbound network | Yes | Yes | Yes | Linux TAP/NAT or explicit Slirp; Slirp on Windows/macOS |
| TCP port forwarding | Yes | Yes | Yes | Linux TAP/NAT or explicit Slirp; Slirp on Windows/macOS |
| Pause, resume, stop | Yes | Yes | Yes | Native backend |
| RNG device for guest entropy | Yes | Yes | Host kernel entropy path | Native backend |
| Multi-vCPU native runner | Yes | Yes | Yes | Full Linux guest SMP parity remains backend work |
Expand All @@ -400,7 +402,8 @@ macOS/HVF runtime:

Yes, VM execution can run without `sudo` when the host user can open `/dev/kvm`
and the VM does not need root-only setup. The root-only parts are rootfs
creation/mounting and `--net auto`.
creation/mounting and `--net auto`; `--net slirp` avoids TAP/iptables setup when
the Linux native addon was built with libslirp.

One simple workflow is:

Expand Down
9 changes: 8 additions & 1 deletion binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,14 @@
"-fstack-protector-strong",
"-D_FORTIFY_SOURCE=2"
],
"ldflags": ["-Wl,-z,relro", "-Wl,-z,now", "-Wl,-z,noexecstack"]
"ldflags": ["-Wl,-z,relro", "-Wl,-z,now", "-Wl,-z,noexecstack"],
"conditions": [
["\"<!(node -e \"process.stdout.write(process.env.NODE_VMM_HAVE_LIBSLIRP || '')\")\"=='1'", {
"defines+": ["NODE_VMM_HAVE_LIBSLIRP"],
"cflags_cc+": ["<!@(node -e \"process.stdout.write(process.env.NODE_VMM_LIBSLIRP_CFLAGS || '')\")"],
"libraries+": ["<!@(node -e \"process.stdout.write(process.env.NODE_VMM_LIBSLIRP_LIBS || '')\")"]
Comment on lines +23 to +26
}]
]
}],
["OS=='win'", {
"sources": [
Expand Down
4 changes: 2 additions & 2 deletions docs/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ sub-100ms warm starts.
| Dockerfile rootfs | Available on Linux/KVM | Dockerfile and repo rootfs builds still require Linux. |
| Git repository builds | Available on Linux/KVM | `--repo`, `--ref`, and `--subdir` clone to temp storage before build. |
| JavaScript app servers | Available on Linux/KVM; WHP/HVF runtime smoke | Linux release gate covers Dockerfile-built plain Node, Express, Fastify, Next.js, Vite React, and Vite Vue. WHP smoke covers the same app families built inside `node:22-alpine`; HVF covers Node image/runtime and port publishing on ARM64. |
| Docker-style TCP ports | Available | Linux/KVM uses TAP/NAT; Windows/WHP and macOS/HVF use libslirp host forwarding. |
| Docker-style TCP ports | Available | Linux/KVM supports TAP/NAT through `--net auto` and user-mode libslirp through `--net slirp`; Windows/WHP and macOS/HVF use libslirp host forwarding. |
| Rootless run from prepared disk | Available | Linux/KVM works with `/dev/kvm` access and `--net none`; WHP runs without Linux sudo; HVF runs as a signed normal user process. |
| Live VM handle | Available | `startVm()`, `pause()`, `resume()`, `stop()`, `wait()`. WHP and HVF lifecycle paths are covered by native tests. |
| Prepared sandbox exec | Available | `createSandbox().process.exec()` reuses a rootfs but boots per exec today. |
Expand Down Expand Up @@ -54,7 +54,7 @@ sub-100ms warm starts.
| Real rootfs boot | Available | Available locally through WSL2-built OCI rootfs images; full e2e gated by `NODE_VMM_WHP_FULL_E2E=1` | Available through local ARM64 OCI rootfs build; covered by `npm run test:macos-hvf` |
| Prebuilt rootfs boot | Available for x86_64 assets | Available for published x86_64 release assets; no WSL2 required when fetch/checksum succeeds or the cache already has the rootfs | Planned for future ARM64 assets; current x86_64 assets are intentionally skipped |
| Virtio block/rootfs | Available | Available with sparse overlay support | Available with sparse overlay support |
| Networking and port publishing | TAP/NAT and Docker-style TCP publish | libslirp user-mode networking and host forwarding | libslirp user-mode networking and host forwarding by default; vmnet/socket_vmnet optional |
| Networking and port publishing | TAP/NAT by default, plus explicit libslirp user-mode networking and host forwarding | libslirp user-mode networking and host forwarding | libslirp user-mode networking and host forwarding by default; vmnet/socket_vmnet optional |
| Interactive console | UART/PTY helper | UART/PTY helper; idle CPU and guest Ctrl-C covered by WHP e2e | PL011 `/dev/ttyAMA0`; boot loading, TTY size, and guest Ctrl-C covered by HVF e2e |
| Guest entropy | `/dev/random`, `/dev/urandom`, host kernel RNG | plus virtio-rng `/dev/hwrng` on WHP | host kernel entropy path through the ARM64 guest |
| SMP | 1-64 vCPUs | 1-64 vCPUs | 1-64 vCPUs through PSCI |
Expand Down
10 changes: 6 additions & 4 deletions docs/sdk.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ uses safe defaults and cleans temporary rootfs/cache artifacts it owns.

Linux/KVM and Windows/WHP are the supported x64 host backends. VM execution
expects a Linux guest kernel. Linux/KVM uses `/dev/kvm` and needs root
privileges for rootfs mounting and automatic TAP/NAT setup; Windows/WHP runs the
VM as the current Windows user and only uses WSL2 when it must build a fresh
rootfs locally from OCI layers.
privileges for rootfs mounting and automatic TAP/NAT setup. Explicit
`net: "slirp"` uses user-mode networking when the Linux native addon was built
with libslirp. Windows/WHP runs the VM as the current Windows user and only uses
WSL2 when it must build a fresh rootfs locally from OCI layers.

## Running Without Sudo

Expand Down Expand Up @@ -38,7 +39,8 @@ console.log(result.guestOutput);
```

Root is still required on Linux when the SDK builds/mounts rootfs images or
creates automatic TAP/NAT networking. Windows/WHP does not use Linux `sudo`.
creates automatic TAP/NAT networking. Use `net: "slirp"` with a prepared rootfs
to avoid TAP/iptables setup. Windows/WHP does not use Linux `sudo`.

## Simple API

Expand Down
17 changes: 16 additions & 1 deletion docs/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ node dist/src/main.js run \
--net none
```

Rootless runs must avoid rootfs building/mounting and `--net auto`.
Rootless runs must avoid rootfs building/mounting and `--net auto`. `--net
slirp` avoids TAP/iptables setup when the Linux native addon was built with
libslirp.

## Port Publishing Smoke

Expand All @@ -101,6 +103,19 @@ sudo -n node dist/src/main.js run \
curl http://127.0.0.1:18080
```

Linux/KVM also supports explicit libslirp user-mode networking:

```bash
sudo -n node dist/src/main.js run \
--image node:22-alpine \
--cmd "node -e \"require('node:http').createServer((_, r) => r.end('ok\\n')).listen(3000, '0.0.0.0')\"" \
--net slirp \
-p 18081:3000 \
--timeout-ms 30000

curl http://127.0.0.1:18081
```

`-p 3000`, `-p 18080:3000`, and
`-p 127.0.0.1:18080:3000/tcp` follow Docker's common TCP publish form. UDP and
publish-all are not implemented in the current Linux/KVM release.
Expand Down
Loading
Loading