Buried inside every systemd installation sits a container runtime that most administrators never notice, a tool that boots a complete Linux system inside a directory using nothing more than the init system already running on the host. Systemd-nspawn is that tool, and its niche is exactly the working-day corner this article's series lives in: spinning up a throwaway Linux environment for testing a package, reproducing a bug on an older distribution release, or isolating a debugging session, all without installing a single new service. This article builds the practical skill set: where the tool fits relative to the runtimes covered earlier, creating containers through debootstrap and through cloud images, the machinectl management interface, networking in its two modes, resource limits through the same systemd properties from the cgroups article, and the testing and debugging patterns that make nspawn a quiet daily habit on any systemd host.

The runtime that ships with the init system

Nspawn's identity comes from what it is not. It is not a standalone runtime with its own command suite, it is part of systemd, present on the host from the moment the distribution installed the init, and its containers are machine containers in the LXC sense, complete Linux systems with their own init, rather than application containers in the Podman sense. The contrast with the rest of this series is therefore complementary, not competitive: the app-container articles cover services in production, and nspawn covers the sandbox on the same host where an engineer needs a full second system for an hour, an evening or a quarter.

The two properties that define the daily experience are integration and weight. Integration, because every nspawn container is a systemd unit, Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в браузере должен быть включен Javascript., startable, stoppable and restartable with the systemctl vocabulary the whole series has used, and listed alongside every other unit in the host's normal monitoring. Weight, because a booted nspawn container is a directory tree and a process tree, no separate block device, no second kernel, and the memory cost is the booted guest's userspace alone, tens of megabytes for a minimal image.

Creating containers, the debootstrap and image routes

The first route builds a fresh Debian-family system straight into the standard machines directory, using the bootstrap tool of the distribution family:

debootstrap --arch=amd64 bookworm /var/lib/machines/bookworm http://deb.debian.org/debian

which downloads and unpacks a complete minimal root filesystem in minutes, ready to boot without further ceremony. The RHEL-family equivalent uses dnf with the installroot flag against the release repositories, and the result is the same artifact in the same place, a directory that is a bootable machine.

The second route reaches for a ready-made image and saves the bootstrap entirely. Download a cloud image of the distribution, unpack it, and point nspawn at the resulting directory, or use machinectl pull-tar against a published tarball, the native path for images from the systemd project's own registry and for any local tarball of a prepared root filesystem:

machinectl pull-tar https://example.com/images/testbookworm.tar testbox

Both routes land in the same place, /var/lib/machines/<name>, the directory that the host treats as the container's entire disk, and the btrfs or ZFS hosts gain the snapshot property from the previous article for free, the container as a subvolume snapshots and clones in seconds.

Booting, entering and the two modes of use

Starting a container is one command, and the flag that matters decides whether the guest boots its own init:

systemd-nspawn -bD /var/lib/machines/bookworm

where -b boots systemd inside, presenting a login prompt at the container's console, and the interactive session ends with the usual logout, the container shutting down cleanly. The lighter form omits -b and boots straight to a shell in the container, the scratch-pad mode for quick package tests where no services need to run.

The management interface is machinectl, and its verbs cover the full lifecycle:

machinectl list # machinectl start bookworm # machinectl shell bookworm # machinectl login bookworm # machinectl poweroff bookworm

machinectl shell is the working command for scripting, opening a shell or running a single command inside a running container without an interactive login, while machinectl login attaches a real login session to the console. The start and poweroff verbs speak to the service-mapped side of the design, identical in effect to systemctl start Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в браузере должен быть включен Javascript., and machinectl list is the one-screen inventory of running machines with their addresses and timestamps.

Networking, the private and bridged models

Nspawn's default network mode is deliberately simple: the container gets a private veth pair and shares the host's connectivity through the same virtual bridge machinery that the LXC article described, with a NAT'd address that reaches the outside and no inbound exposure. The explicit flag for the private mode, --network-veth, appears in the per-container configuration when the default needs overriding, and the bridged production mode arrives through the same bridge the LXC article built:

systemd-nspawn --network-bridge=br0 -bD /var/lib/machines/bookworm

placing the container on the physical network with an address of its own, the pattern for a test box that must be reachable by other machines on the LAN. The per-container file makes the settings persistent, /etc/systemd/nspawn/bookworm.nspawn:

[Network]
Bridge=br0

with the nspawn file the nspawn analogue of LXC's config file, every runtime declaration in one small unit-adjacent file, versioned alongside the machine it configures.

Resource limits through the systemd front door

Because every nspawn container is a systemd unit, the resource limits from the cgroups article apply through the systemd interface unchanged:

systemctl set-property Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в браузере должен быть включен Javascript. MemoryMax=2G # systemctl set-property Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в браузере должен быть включен Javascript. CPUQuota=100%

and the properties persist, bind, and monitor exactly as they did for the service containers there. The caps compose with the host's hardening stack naturally, the auditd rules from earlier watch the container's rootfs as host files, and the outbound iptables policy from this series governs the container's traffic through the host stack, one security architecture wrapping the test environments instead of a separate one.

The testing and debugging scenarios that pay the bills

Three patterns cover most of the real nspawn hours in a working week. The package rehearsal: a new major version of a critical package lands in the repository, and the question is what it does to the service stack. The answer is a throwaway container built from the current release image, the package installed inside, the service stack exercised, the results noted, and the machine powered off and deleted, twenty minutes of rehearsal that converts a risky upgrade into a scheduled non-event.

The reproduction lab: a bug report that reads environment-specific, the listener that binds differently or the cron that behaves oddly, becomes a controlled experiment in a container built to match the reporter's distribution release, where the variables are enumerable and the snapshot before the experiment is one btrfs command away. The isolation debugging session: a dependency chain that must be poked without contaminating the host, foreign repositories, conflicting library versions, the software whose vendor demands a specific platform, all live inside the machine directory and vanish with it, leaving the host's package state exactly as the session found it.

The closing checklist is the article in working order. Confirm nspawn is installed, it ships with systemd, so it usually is. Bootstrap or pull one image into /var/lib/machines. Boot it with -b, enter it through machinectl shell, and confirm the network mode suits the task. Apply the resource limits through systemctl set-property. Use the machines for the rehearsal and reproduction patterns above, and clean them up with machinectl poweroff and a removal of the directory, which is the full lifecycle of a tool whose entire administrative surface is two commands and a directory tree.
## Overlay mode and the throwaway pattern

The overlay flag is nspawn's built-in answer to the disposable experiment, layering a writable copy-on-write layer over a pristine base image so that every change inside the container vanishes with the session. The invocation adds one option:

systemd-nspawn --overlay -bD /var/lib/machines/bookworm

and the semantics are the container equivalent of a live-booted DVD: the base directory stays untouched, all writes land in the ephemeral upper layer, and the next boot starts from the same pristine state again. The testing patterns from the scenario section become cleaner with overlay in the pipeline, the package rehearsal runs its experiment, the results are noted, and the machine is discarded with a poweroff because there was never anything to clean up.

The clone workflow serves the same goal with a persistent shape. On btrfs and ZFS hosts, machinectl clone bookworm rehearsaltwo produces a snapshot-backed copy in seconds, a full sibling of the original with its own directory and its own identity, and the experiment runs there with write persistence for the cases that need it, the multi-day soak test, the reproduction that requires a specific package state to survive a reboot. The pair, overlay for the ephemeral hour and clones for the persistent week, covers the disposable-machine spectrum entirely within the machine directory, no image registries, no build files, just a filesystem and a flag.

What lives inside, services and the container's own systemd

A booted nspawn container runs the guest's own systemd, and the difference from the app-container world is worth dwelling on for a paragraph because it changes what the machine is good for. Inside the container, journald collects the guest's logs into the guest's journal, readable with journalctl -M bookworm from the host without entering the machine, one command that reads another system's log from the outside. The guest's services start, restart and crash exactly as they would on real hardware, which is what makes the container a faithful rehearsal environment: the unit file that behaves differently under the guest's systemd is a unit file that will behave differently on the next real deployment.

Host-visible management follows from the service mapping. A container whose guest service wedges gets its whole cage restarted with systemctl restart Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в браузере должен быть включен Javascript., the guest reboots inside, its services come up in its declared order, and the host's journal keeps a clean record of the entire cycle. The watchdog pattern from the spot instances article applies unchanged, the unit's Restart=always keeping the test machine alive through the guest's worst behavior, and the monitoring side reads the machine like any other unit, the nspawn service's memory and CPU feeding the same dashboards the production services feed.

The closing verdict on the niche

Nspawn will never replace the production runtimes, and it never tries to. What it replaces is the virtual machine that stood in for a quick test, the laptop dual-boot that reproduced the old release, and the excuse that testing on production-adjacent hardware was too much trouble to arrange. The tool is on every systemd host already, the containers cost minutes to create and megabytes to run, and the administrative surface is the same systemctl vocabulary the whole working day already speaks, which is the rare combination that turns a hidden feature into a daily habit.