How to Use systemd-nspawn for Containerized Applications in Debian 12 Bookworm

This article provides a step-by-step guide on how to use systemd-nspawn for containerized applications on Debian 12 Bookworm.

Containerization has become an essential part of modern system administration and application deployment. While Docker and Podman are popular container tools, Linux also offers powerful native options like systemd-nspawn. Unlike Docker, which uses its own daemon and runtime, systemd-nspawn is part of the systemd suite and uses native Linux capabilities for container management. It’s ideal for lightweight system containers, testing environments, or even running full Linux distributions in a sandboxed manner.

In this article, we’ll explore how to use systemd-nspawn for containerized applications on Debian 12 (Bookworm), including how it works, installation, setup, and best practices.


What is systemd-nspawn?

systemd-nspawn is a container manager that comes with the systemd init system. It allows you to boot up and manage lightweight containers, which are essentially chroot environments with additional isolation provided by namespaces and cgroups.

Unlike Docker, which abstracts much of the Linux system’s complexity, systemd-nspawn operates closer to the metal, making it a great tool for system administrators and developers who want full control over container environments.

Key features:

  • Root file system isolation
  • Separate PID, UTS, IPC, and network namespaces
  • Integration with systemd services
  • Lightweight and doesn’t require a separate daemon
  • Ideal for running full distributions

Why Use systemd-nspawn on Debian 12?

Debian 12 (Bookworm) ships with systemd version 252, which includes improved support for containers. Using systemd-nspawn in Debian offers:

  • Tight integration with systemd services and journald logging
  • A minimal and clean alternative to Docker or Podman
  • Full control over container networking and permissions
  • Easier debugging and access to the underlying Linux subsystems

Prerequisites

Before you begin, ensure your system meets the following requirements:

  • A Debian 12 (Bookworm) host system
  • systemd-container package installed
  • Root or sudo privileges

You can install the necessary tools using:

sudo apt update
sudo apt install systemd-container debootstrap
  • systemd-container: Provides the systemd-nspawn binary
  • debootstrap: Useful for creating Debian container images

Step-by-Step Guide to Using systemd-nspawn

1. Create a Base Container Image

You can create a container environment using debootstrap, which installs a minimal Debian filesystem into a directory.

sudo debootstrap --arch=amd64 bookworm /var/lib/machines/mycontainer http://deb.debian.org/debian
  • bookworm: The release name
  • /var/lib/machines/mycontainer: Default location for systemd-nspawn containers
  • URL: Debian mirror to fetch packages

2. Booting the Container with systemd-nspawn

Now that the container root filesystem is in place, you can boot it:

sudo systemd-nspawn -D /var/lib/machines/mycontainer

The -D flag specifies the container root directory.

You’ll be dropped into a shell inside the container, similar to a chroot, but with better isolation. You can now run commands as if you were inside a separate Debian system.

3. Networking Setup

By default, systemd-nspawn uses a private veth pair and connects the container to the host using a bridge. To enable external networking, use the --network-veth option.

sudo systemd-nspawn -D /var/lib/machines/mycontainer --network-veth

For persistent bridge networking, install and configure systemd-networkd.

Create a bridge on the host:

sudo apt install bridge-utils
sudo brctl addbr br0
sudo ip addr add 192.168.100.1/24 dev br0
sudo ip link set br0 up

Then launch the container with:

sudo systemd-nspawn -D /var/lib/machines/mycontainer --network-bridge=br0

Inside the container, configure a static IP or use DHCP by enabling systemd-networkd and creating appropriate network files.


4. Running Containers as Services

To start containers automatically and integrate with systemctl, use machinectl and systemd-nspawn unit files.

First, move the container into /var/lib/machines/:

sudo mv /path/to/mycontainer /var/lib/machines/

Then start the container using:

sudo machinectl start mycontainer

To enable the container to boot at system startup:

sudo systemctl enable systemd-nspawn@mycontainer

This uses a systemd template unit file located at /lib/systemd/system/systemd-nspawn@.service.


5. Accessing Containers with machinectl

machinectl allows you to manage running containers:

  • List containers:
machinectl list
  • Login to a container:
machinectl shell mycontainer
  • Stop a container:
machinectl poweroff mycontainer

6. Container Customization

Once inside the container, you can install software using apt, configure users, set hostnames, and more.

Here’s a sample of how to configure the container post-boot:

apt update
apt install nginx

To set the hostname:

echo "webapp01" > /etc/hostname

To add a user:

adduser alice

7. Advanced Options

Read-Only Containers

If you want to ensure that the container cannot write to the filesystem:

sudo systemd-nspawn -D /var/lib/machines/mycontainer --read-only

Bind Mounts

To expose host directories inside the container:

sudo systemd-nspawn -D /var/lib/machines/mycontainer --bind=/home/hostuser/data:/data

CPU and Memory Limits

You can control resource usage using systemd unit options. For example, edit the override for systemd-nspawn@mycontainer:

sudo systemctl edit systemd-nspawn@mycontainer

Add:

[Service]
CPUQuota=50%
MemoryMax=512M

8. Security Considerations

While systemd-nspawn provides good isolation, it is not a complete sandbox. Some key practices include:

  • Use non-root users inside containers
  • Apply SELinux or AppArmor profiles where possible
  • Restrict capabilities using --capability= or --drop-capability=
  • Consider using --private-users=pick for user namespace isolation

9. Troubleshooting Tips

  • DNS issues inside containers: Ensure /etc/resolv.conf is configured correctly or bind mount from host.
  • Permission denied on bind mounts: Use --bind-ro for read-only access or check host permissions.
  • Service doesn’t start at boot: Ensure systemd-nspawn@containername is enabled and that container has its own systemd enabled.

Conclusion

systemd-nspawn is a powerful and elegant tool for containerization on Debian 12 Bookworm. It offers a lightweight and transparent alternative to Docker, especially for system-level containers and development environments. With native integration into systemd and Linux namespaces, it gives users precise control over their container environments while leveraging the full power of the underlying system.

Whether you’re a system administrator looking to isolate services or a developer testing full system environments, systemd-nspawn is a valuable addition to your Linux toolkit.