FAQ

Short answers to the questions that come up most.

What is nspawn.org?

A hub for systemd-nspawn images and the tool that uses them. The team builds images of common Linux distributions with mkosi, publishes them on an OCI registry at hub.nspawn.org, and maintains nspawn, the command line tool documented on this site. The mkosi definitions of the images are public.

Do I need systemd?

Yes, version 255 or newer. nspawn drives systemd-nspawn through systemd-machined and the systemd service manager, so the host needs both, with cgroup v2. The images on the hub contain systemd as well; images without an init system run as apps.

Is this docker?

No. The commands and flags look alike on purpose (-p, -e, -v, --entrypoint, create, exec, logs), but the machines are systemd-nspawn containers managed by systemd: they are systemd-nspawn@NAME.service units, appear in machinectl list, log to journald and boot a full init when the image has one. nspawn’s own service holds none of them open, there is no compose file and no orchestration.

Can I run images from Docker Hub?

Yes. sudo nspawn search nginx finds them, and sudo nspawn pull docker.io/library/nginx:latest --name web fetches one like any other registry image. Since it has no init system, it is installed as an app image: its entrypoint runs under nspawn’s stub init, on the bridge, with -p for its ports. Docker Hub limits anonymous pulls per address; sudo nspawn login docker.io -u USER lifts that. See Getting started.

Do I need root?

Not necessarily. Every command goes through the service on the system bus, and the service asks polkit about the caller: root is never asked, an administrator is asked for a password (a desktop session prompts; in a plain terminal, start pkttyagent first), and a rule of your own can hand the actions to a group so that nobody is asked at all. The work does need privileges, since the machines live below /var/lib/machines and the bridge is the host’s, which is why the service is the one holding them.

On a host without polkit the service answers root alone. See The service for the two actions and the rule.

What is the org.nspawn service?

Where the work happens. The command line is its client, the way machinectl and systemctl are clients of machined and systemd: every command is a method call, and pulls, pushes, builds, creates, removals and copies come back as job objects that report their output. The bus starts the service when a command arrives and it exits after a minute without work, so nothing of nspawn’s runs in the background otherwise. A package installs it; for a binary you built yourself, sudo nspawn daemon --install. Its journal is journalctl -u nspawn.service, and the interface is described in docs/DBUS.md of the repository. After an upgrade the service keeps running the binary it started with until it goes idle or is restarted; a command of another version says so and asks for sudo systemctl restart nspawn.service (the rpm and the deb restart it themselves).

Are the images signed?

Yes. The workflow that builds the images of the hub, in nspawn/mkosi-definitions, signs each one twice with cosign after pushing it: keyless, with the identity of that workflow on master (a short-lived certificate from Fulcio, recorded in the Rekor transparency log), and with the project’s key, whose public half is cosign.pub in that repository. The signatures are stored on the hub next to the image, as OCI referrers of its digest, so they cover every tag that points to it, and the hub verifies the key one itself and shows the image as signed.

nspawn pull verifies them too, since 1.5.0: before a single layer is downloaded, one of the two signatures has to verify offline against the project’s key and the workflow’s identity, both built into nspawn, and an image without a valid signature is refused (--no-verify skips the check for one command; see Signed images). Other registries get a policy in the configuration. To verify an image yourself, with cosign:

cosign verify \
  --certificate-identity https://github.com/nspawn/mkosi-definitions/.github/workflows/mkosi.yml@refs/heads/master \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  hub.nspawn.org/fedora:44

or, with the key from the repository, cosign verify --key cosign.pub hub.nspawn.org/fedora:44. Every blob is also checked against the sha256 digest in the manifest while it downloads, and registries are reached over HTTPS only.

What happened to the wrapper script and the tar images?

The first generation of nspawn was a shell wrapper around machinectl that downloaded tar.xz and raw.xz images from hub.nspawn.org/storage, signed with the nspawn.org master key and verified by systemd-importd. Its last release was 0.6; version 1.0 replaced it with the OCI based client described here: images are OCI images on a registry, layers are shared, and machinectl is no longer involved. The history of the old script is still in the nspawn repository.

Does the bridge work with NetworkManager, docker or firewalld?

Yes. nspawn creates the bridge, its addresses and its nftables rules itself, and hands each machine its address through a generated file or a prepared network namespace. Neither systemd-networkd nor NetworkManager on the host is involved; only --network veth depends on systemd-networkd. With firewalld the bridge is put in the trusted zone, and on hosts where docker or ufw set the forward policy to drop, nspawn adds the exception the bridge needs. See Firewalls.

What is the difference between exec and shell?

exec enters the machine’s namespaces, like docker exec: nothing is needed inside, the exit code comes back and the program is found on the machine’s PATH. shell opens an interactive shell: machined’s login session for a booted machine, which needs D-Bus inside, or /bin/sh in the namespaces for an app.

How do I keep data across restarts and rebuilds?

With volumes, as in docker: -v /srv/data:/data mounts a host directory, -v pgdata:/var/lib/postgresql a named volume that nspawn keeps under /var/lib/nspawn/volumes/pgdata. Named volumes survive rm and images rm. See Volumes.

Can I run several machines from one image?

Yes: sudo nspawn create fedora-44 db makes another machine that shares the layers of fedora-44 and has a writable layer, an address, ports and settings of its own. See More machines from one image.

Can a machine start at boot?

Yes. sudo nspawn start NAME --restart always (or unless-stopped) enables the unit and also restarts the machine when it ends; systemctl enable systemd-nspawn@NAME.service (or machinectl enable NAME) works too. Either way the drop-in nspawn installs on the unit prepares the network and publishes the ports whoever starts the machine.

How do I get a machine’s address from the host?

sudo nspawn ps shows it, and sudo nspawn network inspect bridge (or the name of another network) lists the machines of a network with their addresses. Inside the machines, the other machines are reachable by name and the host as host.nspawn.internal; on hosts with systemd 258 or newer, machined resolves the machine names on the host as well.

How do I free disk space?

sudo nspawn rm NAME (or images rm) removes a machine or image, and afterwards every layer and blob that no remaining image references. Overlay machines keep their writes in a private directory under /var/lib/nspawn, which goes away with the image; named volumes stay until sudo nspawn volume rm NAME or sudo nspawn volume prune.

Where do I ask or report a problem?

For questions, #nspawn-org on Matrix or on Libera.Chat. For bugs, the issues of github.com/nspawn/nspawn for the tool, mkosi-definitions for the images, and nspawn.org for this site.