User:Cmsigler/Nspawn Configuration Guide
My Personal Step-by-step Guide to systemd-nspawn Container Setup, Configuration and Operation
CMS, 2022/03/21
Note: This guide is a work-in-progress. Please use appropriately.
Note: These procedures have been developed and deployed on an Arch Linux installation. Other distributions and environments will require modifications to the steps below. YMMV
Create and set up Arch Linux container
$ sudo pacman -S --needed arch-install-scripts $ mkdir ~/containers $ cd ~/containers $ sudo mkdir ./container_name $ sudo pacstrap -c ./container_name base [addl. pkgs./groups] $ sudo systemd-nspawn -D ./container_name # passwd # useradd -m -G wheel regularuser # passwd regularuser # logout
Configure host for container operation
Configure host networking to support container
$ sudo cp -ip /usr/lib/systemd/network/80-container-vz.network /etc/systemd/network $ sudo vi /etc/systemd/network/80-container-vz.network
/etc/systemd/network/80-container-vz.network
[Match] Name=vz-* Driver=bridge [Network] # Default to using a /24 prefix, giving up to 253 addresses per virtual network. Address=10.10.0.1/24 Address=fd89:abc1:def2:10::1/64 IPMasquerade=both IPv6PrivacyExtensions=yes LinkLocalAddressing=yes LLDP=yes EmitLLDP=customer-bridge DHCPServer=no IPv6SendRA=yes
Note: Configuration of IP masquerading, along with sysctl IP forwarding kernel parameters, is configured by use of
IPMasquerade=both
in the [Network]
section of 80-container-vz.network
Add nftables rule to forward chain to allow forwarding
host_ruleset.nft
table inet inet-local-table { ... chain inet-local-forward { type filter hook forward priority filter policy drop ... # Accept IP forward for upstream established and related tracked connections iif $upstream-if ct state {established, related} accept # Accept all systemd-nspawn container traffic to be forwarded upstream iifname vz-* oif $upstream-if accept ... } }
$ sudo nft flush ruleset $ sudo nft -f host_ruleset.nft
Configure container for operation
Configure container networking
In container, edit /etc/systemd/network/80-container-host0.network:
/etc/systemd/network/80-container-host0.network
[Match] Virtualization=container Name=host0 [Network] DHCP=no Address=10.10.0.2/24 Gateway=10.10.0.1 Address=fd89:abc1:def2:10::2/64 Gateway=fd89:abc1:def2:10::1 IPv6PrivacyExtensions=yes LinkLocalAddressing=yes LLDP=yes EmitLLDP=customer-bridge [DHCP] UseTimezone=yes
Boot into and set up container
$ sudo systemd-nspawn -b -D ./container_name --network-zone=nspawn0
Log into container as root.
# systemctl enable systemd-networkd # systemctl start systemd-networkd # systemctl enable systemd-resolved # systemctl start systemd-resolved # systemctl enable sshd # systemctl start sshd # reboot ... [Continue setting up, install additional packages, configure, and/or run your container] ... # poweroff
Container operation
Set up container to run as a machine
Move container to /var/lib/machines, then create a .nspawn file for operation via machinectl, etc.:
$ sudo mv ./container_name /var/lib/machines $ sudo vi /etc/systemd/nspawn/container_name.nspawn
/etc/systemd/nspawn/container_name.nspawn
[Exec] Boot=on ;PrivateUsers=no [Network] Zone=nspawn0
Enable and start container
$ sudo machinectl enable container_name $ sudo machinectl start container_name $ sudo machinectl login container_name
Use container as base
Using a configured minimal container as the base image for a tailored, single-app container:
- Configure .nspawn file:
$ sudo vi /etc/systemd/nspawn/single-app_container_name.nspawn
/etc/systemd/nspawn/single-app_container_name.nspawn
[Exec] Boot=on ;PrivateUsers=no [Network] Zone=nspawn0
- First time only -- Create directories:
$ sudo mkdir /var/lib/machines/single-app_container_name
Note:
/var/lib/machines_overlay
is non-standard and unmanaged by the system.$ sudo mkdir /var/lib/machines_overlay $ sudo chmod 700 /var/lib/machines_overlay $ sudo mkdir /var/lib/machines_overlay/single-app_container_root $ sudo mkdir /var/lib/machines_overlay/single-app_container_tmp
- Each time before starting overlay container, perform overlay mount:
$ sudo mount -t overlay overlay -o lowerdir=/var/lib/machines/base_container_name,upperdir=/var/lib/machines_overlay/single-app_container_root,workdir=/var/lib/machines_overlay/single-app_container_tmp /var/lib/machines/single-app_container_name
- Start and login to overlay container:
$ sudo machinectl start single-app_container_name $ sudo machinectl login single-app_container_name
- Log into single-app container, then use pacman to install desired packages; configure container for operation.
- When finished, stop overlay container and unmount overlay:
$ sudo machinectl stop single-app_container_name $ sudo umount /var/lib/machines/single-app_container_name