pelagos-mac runs one or more persistent Linux VMs as background daemons.
Each VM is identified by a profile name. The default profile is the
Alpine container VM; additional profiles (e.g. build) run other operating
systems for different purposes. Each VM boots once and stays alive between
invocations, giving warm-start latency of ~100 ms for subsequent commands.
Every user-facing command (run, exec, ping, ps, logs, stop,
rm, vm shell, vm console, vm ssh) starts the daemon automatically
if it is not already running. There is no separate "start" step.
pelagos ping # boots VM if needed, returns "pong"
pelagos run alpine /bin/echo hello
pelagos vm ssh # boots VM if needed, then SSH in
Cold boot takes ~1–2 s. All subsequent commands reuse the running VM.
# Show all configured profiles and their state (recommended starting point)
pelagos vm ls
# Single-profile status/stop (defaults to "default" profile)
pelagos vm status # running (pid …) OR stopped
pelagos vm stop # stop the default container VM
# Same commands for a named profile
pelagos vm status --profile build # running (pid …) OR stopped
pelagos vm stop --profile build # cleanly stop the build VMvm stop sends SIGTERM and waits up to 15 s for the daemon to exit.
After vm stop, the next command triggers a cold boot automatically.
pelagos vm ls scans all configured profiles and prints a table:
PROFILE ACCESS MEMORY CPUS STATUS
---------- ---------- ------- ----- --------------------
default vsock/shell 2048 MB 2 running (pid 6495)
build ssh 4096 MB 4 running (pid 58661)
debian ssh 2048 MB 2 stopped
Profiles are discovered by scanning ~/.local/share/pelagos/profiles/ plus the
root data directory (the default profile). A profile shows as stopped if no
daemon PID file exists or the recorded PID is no longer alive.
Three modes for getting a shell or running commands directly in the VM:
| Command | Transport | Notes |
|---|---|---|
pelagos vm shell |
vsock | Busybox /bin/sh; fastest; default profile only |
pelagos vm console |
hvc0 serial | Raw boot console; Ctrl-] to detach |
pelagos vm ssh [-- cmd] |
SSH (dropbear) | Full SSH; supports port-forwarding |
All three auto-start the daemon if needed.
vm shell uses the vsock control plane and only works for profiles with
ping_mode = vsock (the Alpine container VM). For SSH-based profiles like
build, use vm ssh:
pelagos vm shell # shell into default (Alpine) VM
pelagos vm ssh # SSH into default VM
pelagos vm ssh --profile build # SSH into build (Ubuntu) VM
pelagos vm ssh --profile build -- uname -aConvenience wrappers:
scripts/vm-shell.sh
scripts/vm-console.sh
scripts/vm-ssh.sh [-- cmd args]Stored in ~/.local/share/pelagos/ (respects $XDG_DATA_HOME):
| File | Purpose |
|---|---|
vm.pid |
Daemon PID |
vm.sock |
Unix socket — vsock proxy for container commands |
console.sock |
Unix socket — hvc0 serial relay |
vm.mounts |
Active virtiofs shares (JSON) |
vm_key |
Ed25519 private key for vm ssh (generated by make image) |
vm_key.pub |
Corresponding public key (baked into initramfs as root's authorized_keys) |
A VM profile is a named configuration (kernel + disk + memory + cpus) stored in
~/.local/share/pelagos/profiles/<name>/vm.conf. The default profile runs the
Alpine pelagos VM. Named profiles can run entirely different operating systems.
The control plane differs by OS, and this affects which pelagos commands
work:
| Alpine VM (default) | Ubuntu build VM (--profile build) |
|
|---|---|---|
| Control plane | vsock → pelagos-guest | SSH → openssh-server |
pelagos ping |
vsock pong from pelagos-guest | SSH connectivity check |
pelagos vm ssh |
works (smoltcp relay) | works (smoltcp relay) |
pelagos run/exec/ps |
works | N/A — no containers |
| smoltcp NAT relay | outbound + SSH inbound | outbound + SSH inbound |
| Purpose | run containers | native aarch64 build/test |
vm.conf accepts a ping_mode key (vsock or ssh):
ping_mode = ssh
When ping_mode = ssh, pelagos ping starts the VM daemon (for the smoltcp
relay) then waits for SSH to be available, printing pong on success. This
makes pelagos ping, vm-ping.sh, and vm-restart.sh work correctly for
Ubuntu profiles without modification.
Default is vsock (Alpine behaviour, backwards-compatible).
pelagos-guest is the vsock server that handles container commands (run, exec, ps, etc.). The Ubuntu build VM has no containers — its sole purpose is native aarch64 Linux compilation. systemd-networkd + openssh-server is the entire control plane needed. vsock drivers are present in the kernel but nothing listens on them.
scripts/test-devcontainer-e2e.sh runs 27 tests across suites A–F.
Some suites stop and restart the daemon to reset mount configuration.
After the test suite completes the daemon is stopped. Run pelagos ping
or any other command to bring it back up.
virtiofs shares (-v /host/path:/container/path) are passed at daemon
launch and cannot change while the daemon is running. Changing mounts
requires stopping the daemon first:
pelagos vm stop
pelagos -v /new/path:/data run alpine ls /data