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:

text
hostfwd=tcp:127.0.0.1:<sshPort>-:22

grain 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:

bash
grain fwd ls
# NAME         PROTO  HOST       GUEST      NOTE
# sbox-1       tcp    :52341     22         ssh

SSH 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:

bash
# 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:53

Accepted forms for each -P value:

FormMeaning
HOST:GUESTmap host HOST → guest GUEST
GUEST or :GUEST or 0:GUESTallocate a free host port → guest GUEST
tcp/HOST:GUEST, udp/HOST:GUESTsame 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: tcp or udp only.
  • All hostfwds bind to loopback only (127.0.0.1), not 0.0.0.0.
  • Create-time SLIRP hostfwds are fixed for the life of the process; change them by recreating the VM. grain start re-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:

bash
grain fwd add sbox-1 8080:80
grain fwd rm  sbox-1 8080

API: POST /vms/{name}/forwards, DELETE /vms/{name}/forwards/{hostPort}. Live forwards are cleared on stop/delete.

Inspect forwards

bash
grain fwd ls           # all VMs
grain fwd ls sbox-1    # one VM

Shows 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.