guides
Networking and ports (SLIRP, publish, hostfwd)
SLIRP, publish, live forwards, and limits.
grain VMs use QEMU user networking (SLIRP). Each VM gets a private guest network; the host reaches guest services only through hostfwd port mappings bound to 127.0.0.1.
This page describes the QEMU path. The experimental Firecracker backend does not configure SLIRP or hostfwd (agent via vsock only) — see Firecracker on Linux.
Built-in SSH forward
On every start, grain allocates a free host TCP port and maps it to guest port 22:
hostfwd=tcp:127.0.0.1:<sshPort>-:22grain sh / grain x --ssh / grain cp --ssh use that port and the key under ~/.grain/ssh/.
(Default x / cp prefer the guest agent on the forwarded agent port when healthy.)
List SSH forwards with:
grain fwd ls
# NAME PROTO HOST GUEST NOTE
# sbox-1 tcp :52341 22 sshSSH ports are re-allocated each time the VM starts (they are not fixed across restarts).
Publish extra ports (--publish / -P)
At create time, publish host→guest ports:
# fixed host port → guest port
grain new -P 8080:80
# auto host port (omit host, or use 0)
grain new -P 80
grain new -P 0:443
# multiple
grain new -P 8080:80 -P 4430:443
# optional proto prefix (default tcp)
grain new -P tcp/8080:80
grain new -P udp/5353:53Accepted forms for each -P value:
| Form | Meaning |
|---|---|
HOST:GUEST | map host HOST → guest GUEST |
GUEST or :GUEST or 0:GUEST | allocate a free host port → guest GUEST |
tcp/HOST:GUEST, udp/HOST:GUEST | same with explicit protocol |
Forwards are stored in the VM metadata and re-applied on grain start. Host ports that were auto-allocated at create stay in meta; explicit host ports are reused as stored.
Limits
- Host ports < 1024 (privileged) are rejected. Use a port ≥ 1024, or omit the host side so grain picks a free high port.
- Guest ports must be in
1–65535. - Protocols:
tcporudponly. - All hostfwds bind to loopback only (
127.0.0.1), not0.0.0.0. - Create-time SLIRP hostfwds are fixed for the life of the process; change them by recreating the VM.
grain startre-applies stored SLIRP forwards. - Live forwards can be added while a VM is running via
grain fwd add(SSH local tunnels).
Live forwards (running VM)
Hot-add a host→guest mapping without recreating the VM:
grain fwd add sbox-1 8080:80
grain fwd rm sbox-1 8080API: POST /vms/{name}/forwards, DELETE /vms/{name}/forwards/{hostPort}.
Live forwards are cleared on stop/delete.
Inspect forwards
grain fwd ls # all VMs
grain fwd ls sbox-1 # one VMShows the built-in SSH row plus any --publish entries.
What SLIRP does not do
- No bridged/TAP networking and no guest-visible LAN IP on the host interface.
- No inbound connections from other machines on your network (loopback hostfwd only).
- Guest outbound internet works through SLIRP (typical QEMU user-net behavior).
- No guest↔guest connectivity between VMs (each SLIRP net is private). For a shared L2 lab fabric, see Overlay network — and read its security note (peers can reach each other’s unauthenticated guest agent).
Egress proxy (optional)
From the guest, the host is 10.0.2.2. Run grain proxy up on the host
(default listen 0.0.0.0:3128) and point HTTPS_PROXY at
http://[email protected]:3128 for default-deny allowlisted HTTP(S) and optional
secret injection. Details: Egress proxy.
Related
- Overlay network — guest↔guest L2 (isolation tradeoffs)
- Firecracker — experimental backend without SLIRP/hostfwd
- Mounts — share host directories into the guest
- Egress proxy — allowlist + secret injection
- Security model — agent trust, hostfwd loopback, remote API
- Troubleshooting — SSH wait, serial logs, resource caps