docs: update QEMU mode docs for =PATH syntax and uncompressed initramfs
CI / Check (push) Successful in 1m7s
CI / Format (push) Successful in 14s
CI / Clippy (push) Successful in 1m8s
CI / Test (push) Successful in 1m24s

This commit is contained in:
2026-09-20 22:37:33 +02:00
parent 240a66c532
commit 2c47a5c662
2 changed files with 27 additions and 22 deletions
+7 -5
View File
@@ -38,7 +38,7 @@ ecr [OPTIONS] <DISTRO[:VERSION]> [-- COMMAND...]
| `--no-cache` | Force a fresh download, bypassing the cache |
| `-v, --verbose` | Print diagnostic output (URLs, layer info, extraction steps) |
| `-a, --arch <ARCH>` | Target architecture (`amd64`, `arm64`, `armhf`, `riscv64`, …) |
| `--kernel [PATH]` | Boot with QEMU system emulation. Downloads Alpine's `linux-virt` kernel if no path provided |
| `--kernel[=PATH]` | Boot with QEMU system emulation. Downloads Alpine's `linux-virt` kernel if no `=PATH` given |
| `-m, --memory <SIZE>` | Memory for QEMU VM (default: 2G, only with `--kernel`) |
## Examples
@@ -62,8 +62,8 @@ ecr --no-cache fedora
# Boot with QEMU system emulation (auto-downloads default kernel)
ecr --kernel alpine
# Boot with your own kernel
ecr --kernel /boot/vmlinuz ubuntu
# Boot with your own kernel (note the `=` — a space would parse the path as the distro)
ecr --kernel=/boot/vmlinuz ubuntu
# Boot with custom memory
ecr --kernel --memory 4G alpine
@@ -78,16 +78,18 @@ When `--kernel` is specified, ecr boots the rootfs in a full QEMU virtual machin
ecr --kernel alpine
# Use your own kernel
ecr --kernel /boot/vmlinuz ubuntu
ecr --kernel=/boot/vmlinuz ubuntu
```
This mode:
- Creates a gzipped CPIO initramfs from the rootfs
- Creates an uncompressed CPIO initramfs from the rootfs (streamed to disk)
- Boots QEMU with your kernel (or auto-downloads Alpine's `linux-virt` kernel)
- Provides full VM isolation
- Works for any architecture (no binfmt_misc needed)
- Caches the default kernel in `~/.cache/ecr/`
Host bind mounts (`--bind`, `--bind-rw`) are not applied in this mode.
Requirements:
- `qemu-system-<arch>` installed
- For custom kernels: kernel must have serial console support
+20 -17
View File
@@ -22,7 +22,7 @@ ecr [OPTIONS] <DISTRO[:VERSION]> -- [COMMAND]...
| `--bind-rw <path>` | none | Read-write bind mount at `/mnt/<basename>` (can be specified multiple times, overrides `--bind` for same path) |
| `--no-cache` | false | Download fresh tarball, ignore cache |
| `--no-bind` | false | Skip mounting any directory |
| `--kernel <path>` | none | Boot with QEMU system emulation using specified kernel (triggers disk image creation) |
| `--kernel[=PATH]` | none | Boot with QEMU system emulation; downloads the default Alpine `linux-virt` kernel when no `=PATH` is given |
| `-m, --memory <size>` | 2G | Memory size for QEMU VM (only used with `--kernel`) |
| `-v, --verbose` | false | Print diagnostic messages |
| `-h, --help` | - | Show help |
@@ -187,35 +187,38 @@ No action required. Modern qemu-user-static packages register binfmt_misc with t
## QEMU System Emulation Mode
When `--kernel` is specified, ecr switches from namespace/chroot mode to QEMU system emulation. The extracted rootfs is converted to a gzipped CPIO initramfs and booted with the provided kernel.
When `--kernel` is specified, ecr switches from namespace/chroot mode to QEMU system emulation. The extracted rootfs is converted to an uncompressed CPIO initramfs and booted with the provided kernel.
### Usage
The kernel path uses `=` syntax (`--kernel=PATH`); `--kernel` without a value downloads the default kernel. Without `=`, a following path would be parsed as the DISTRO argument.
```sh
ecr --kernel /boot/vmlinuz ubuntu:noble
ecr --kernel /boot/vmlinuz --memory 4G alpine
ecr --kernel /boot/vmlinuz debian -- /bin/sh -c "echo hello"
ecr --kernel ubuntu:noble
ecr --kernel=/boot/vmlinuz ubuntu:noble
ecr --kernel=/boot/vmlinuz --memory 4G alpine
ecr --kernel=/boot/vmlinuz debian -- /bin/sh -c "echo hello"
```
### Execution Flow
1. Download/cache rootfs tarball (same as namespace mode)
2. Extract tarball to temporary directory
3. Create gzipped CPIO initramfs from rootfs
3. Create uncompressed CPIO initramfs from rootfs (streamed to disk), including essential device nodes (/dev/ttyS0, /dev/null, /dev/tty) and an `/init` script that mounts proc/sys/dev, sets the hostname, execs the requested command argv verbatim (each argv element base64-encoded in the cmdline as `ECR_ARGV`), and powers off on exit
4. Launch QEMU with:
- `-kernel <path>` - provided kernel
- `-initrd initramfs.cpio.gz` - rootfs as initramfs
- `-append "console=ttyS0 quiet rdinit=/bin/sh -- -c \"setsid sh -c 'exec sh </dev/ttyS0 >/dev/ttyS0 2>&1'\""` - kernel command line
7. Essential device nodes (/dev/ttyS0, /dev/null, /dev/tty) are added to initramfs for proper console support
- `-kernel <path>` - provided (or downloaded) kernel
- `-initrd initramfs.cpio` - rootfs as initramfs
- `-append "console=ttyS0 [quiet] ECR_SHELL=... [ECR_ARGV=...] ECR_HOSTNAME=..."` - kernel command line (`quiet` unless `-v`)
- `-m <memory>` - memory size (default 2G)
- `-display none -serial mon:stdio` - console on stdio
- `-netdev user,id=net0 -device virtio-net-pci,netdev=net0` - network
5. Wait for QEMU to exit
- `-netdev user,id=net0 -device virtio-net-pci,netdev=net0` - network NIC
- `-enable-kvm -cpu host` - when the host supports KVM and the target matches the host architecture
5. Wait for QEMU to exit (init powers the VM off when the command/shell exits; `-no-reboot` makes QEMU terminate)
6. Cleanup temporary files
### Initramfs Creation
The rootfs directory is converted to a gzipped CPIO archive (newc format) using the `cpio` crate.
The rootfs directory is converted to an uncompressed CPIO archive (newc format) using the `cpio` crate, streamed entry by entry so large rootfs images never need to fit in memory. Hard links are preserved: the first occurrence of a (device, inode) pair carries the data with a synthetic inode, subsequent occurrences are zero-size entries sharing that inode, which the kernel's initramfs loader turns into real hard links.
### Architecture Support
@@ -238,11 +241,11 @@ The rootfs directory is converted to a gzipped CPIO archive (newc format) using
| Feature | Namespace Mode | QEMU Mode |
|---------|---------------|-----------|
| Isolation | User namespace | Full VM |
| Performance | Near-native | Emulated (slower) |
| Root access | No | No |
| Performance | Near-native | Emulated (KVM-accelerated when available) |
| Root access | No | Yes (inside the VM) |
| Foreign arch | binfmt_misc required | Built-in emulation |
| Bind mounts | Overlay/bind | Not supported |
| Network | Host network | User-mode network |
| Bind mounts | Overlay/bind | Not supported (flags are ignored with a warning) |
| Network | Host network | User-mode NIC (not configured inside the guest) |
## File Handling