Date

This paper will not explain systemd-nspawn but only a guideline to create a builder.

For most of informations, check

Pros

  • can manage control groups, including the control of resources
  • easy access to the journal from host
  • already present on your PC if you have systemd
  • good and customizable integration
  • you only need man for documentation
  • does not need any weird script with unsuitable commands FROM, RUN, CMD
  • must have for trolls

Cons

  • Needs systemd on host
  • Needs systemd on target

Setup

Install debootsrap, and one or both of debian-archive-keyring and ubuntu-keyring depending on which distribution you want.

# cd /var/lib/machines
# debootstrap --include=systemd-container --components=main,universe codename container-name repository-url

For Debian valid code names are either the rolling names like “stable” and “testing” or release names like “stretch” and “sid”, for Ubuntu the code name like “xenial” or “zesty” should be used. A complete list of code names is in /usr/share/debootstrap/scripts and the official table of code names to version numbers can be found in [1]. In case of a Debian image the “repository-url” can be https://deb.debian.org/debian/. For an Ubuntu image, the “repository-url” can be http://archive.ubuntu.com/ubuntu/. “repository-url” should not contain a trailing slash.

For example, for the ubuntu LTS 20.04:

# debootstrap --include=systemd-container --components=main,universe focal ubuntu-focal http://archive.ubuntu.com/ubuntu/

Set a root and user

For an easy setup, create a user with the same id as the one running on the host (get it with $ id -u). To do so, chroot in the container:

# cd /var/lib/machines
# mkdir builder
# systemd-nspawn -D ./builder
# passwd
# useradd -m build -u <uid>
# logout

Set the mount points

Edit /etc/system/nspawn/builder.nspawn:

[Files]
Bind=<source>:<destination>:idmap

The idmap option will map the filesystem ids. If you omit it, the mount point will be owned by the user nobody.

Boot and login

The containers can be managed with the command machinectl which is part of systemd.

# machinectl start builder
# machinectl login builder

Network

Enable and start the network manager with # systemctl enable --now systemd-networkd.service.

Update your system, it’s up to you now.

Extra

Start the container at boot

It’s possible to start the container when the host has boot. But this requires to understand when your computer is ready.

In my case, I use a bind mount from a directory located in my home tree which is encrypted. Thus, I cannot run the container until my home is decrypted.

# machinectl enable container-name

Control the resources

Building OS can easily take your PC down. It’s possible to limit their usage:

# systemctl set-property systemd-nspawn@container-name.service MemoryMax=4G
# systemctl set-property systemd-nspawn@container-name.service CPUQuota=400%

The CPU quota is proportional to one core. Then if you have eight cores, you can go up to 800%.