Build in a systemd-nspawn container
For general information about systemd-nspawn, see:
systemd-nspawn(1)andsystemd.nspawn(5)manpages- Archlinux wiki
The container is a directory under /var/lib/machines that systemd boots. One
file controls it: the nspawn config (/etc/systemd/nspawn/<name>.nspawn).
Why build in a systemd-nspawn container?
This guide is for cross-building (e.g. Yocto) against an old distribution without touching the host. systemd-nspawn gives you:
- an old distribution, in a chroot that systemd manages for you
- fine control over resources such as CPUs and memory
- easy access to the journal from the host
- nothing more than systemd to install
Creation
Install debootstrap, and one or both of debian-archive-keyring and ubuntu-keyring,
depending on which distribution you want.
# cd /var/lib/machines
# debootstrap --include=dbus,libpam-systemd,libnss-systemd,systemd-resolved --components=main,universe <codename> <container-name>
For Debian, use the rolling names ("stable", "testing") or release names ("stretch",
"sid"); for Ubuntu, use the code name ("xenial", "zesty"). Code names are listed in
/usr/share/debootstrap/scripts, and a table of code names to version numbers is on the
Debian releases page.
In my case, I use Debian stable and call the container builder:
# debootstrap --include=dbus,libpam-systemd,libnss-systemd,systemd-resolved stable builder
The container now exists in /var/lib/machines/builder.
Users
Before using the container, set a password for root and create a normal user.
Create the user with the same uid/gid as the host account (use $ id -u ). Mine is
1337:
# cd /var/lib/machines
# systemd-nspawn -D ./builder
# passwd
# useradd -m build -u 1337 -U -s /bin/bash
# passwd build
# logout
Configure the mount point
Edit /etc/systemd/nspawn/builder.nspawn (the file name must match the container name
in /var/lib/machines/).
[Files]
# mount a host directory, mapping uid/gid so the mount is owned by the
# container's user instead of nobody
Bind=/home/louson/projects/yocto:/home/builder/yocto:idmap
Without the idmap option, the mount point is owned by the user nobody.
Network
If the host runs systemd-networkd and systemd-resolved, the network is automatic. Enable and start them:
# systemctl enable --now systemd-networkd.service
# systemctl enable --now systemd-resolved.service
Otherwise, either configure the NAT or disable virtual networking:
[Network]
# no virtual ethernet: the container shares the host network
VirtualEthernet=no
Now start and login to the container:
# machinectl start builder
# machinectl login builder
Check the network is up, and update the system.
Further configuration
Start the container at boot
You can start the container at boot:
# machinectl enable builder
Control the resources
A build can easily take your PC down, so limit its usage:
# systemctl set-property systemd-nspawn@builder.service MemoryMax=4G
# systemctl set-property systemd-nspawn@builder.service CPUQuota=400%
Those limitations may also be given in the nspawn configuration file.