This plugin can build and provision systemd-nspawn containers. It can import or clone an existing base image, or generate one from scratch using debootstrap.
sudo apt-get install --no-install-recommends \
debootstrap golang-go libglib2.0-bin packer systemd-container zstd
git clone https://git.sr.ht/~angdraug/packer-builder-nspawn
packer build -only='*.base' .
debootstrap to generate a minimal viable chroot image
golang-go to build this plugin from source
libglib2.0-bin to monitor container status with
packer (the Debian package recommends docker, you don't need that)
systemd-container systemd-nspawn and related tools
packer-provisioner-apt for installing deb packages
zstd for creating and importing .tar.zst images
In most cases, you'll want your container to be able to connect to the network to provision itself, for that you need to enable systemd-networkd and systemd-resolved:
systemctl enable systemd-networkd.service
systemctl start systemd-networkd.service
systemctl enable systemd-resolved.service
systemctl start systemd-resolved.service
The recommended way to install deb packages when provisioning images is packer-provisioner-apt. When installing that plugin from source, symlink it into your working directory so that Packer can find it:
git clone https://git.sr.ht/~angdraug/packer-provisioner-apt
ln -s $(pwd)/packer-provisioner-apt ../packer-builder-nspawn
The included example
nspawn.pkr.hcl uses zstd to compress the image tarball,
it is several times faster than gzip at the same or better compression ratio.
You don't need zstd if you use a different method for archiving and delivering
For compatibility with the Debian package of Packer that is built with a newer
version of ugorji-go-codec than the one pinned
in Packer source, this plugin's
go.mod includes a replace line to import a
similarly patched version of Packer source. To use this plugin with Packer
built from unpatched upstream source, comment out that replace line.
In Debian, unprivileged user namespaces are disabled by default and have to be
enabled for nspawn's
-U option to have any effect:
echo kernel.unprivileged_userns_clone=1 > /etc/sysctl.d/nspawn.conf
systemctl restart systemd-sysctl.service
This builder will work with and without private user namespaces. If you want an image built on a system with userns enabled to be usable on systems with userns disabled, use the method offered in systemd-nspawn(1) to reset chroot file ownership before archiving the image:
systemd-nspawn ... --private-users=0 --private-users-chown
All configuration options for this plugin are optional.
name - Standard Packer build name parameter. The default is the builder
nspawn. This will be used as container name and will be configured as
the hostname within the container.
import - Import container image from a URL, file, or a directory tree, in a
format recognized by
pull-* commands of
clone - Name of a local container to clone. When neither
clone options are set, a new image will be created with
suite - Distribution release code name as recognized by
The default is
mirror - URL for the distribution mirror. The default is
variant - The bootstrap script variant as recognized by
The default is to not pass
--variant to debootstrap, which will install
required and important packages. The
minbase variant will only install
required packages, the plugin explicitly adds several small important
packages to make sure that even a
minbase image has the CLI tools likely to
be used in most provisioning scripts.
cache_dir - Absolute path to a directory where .deb files will be cached.
The default is the host's APT cache at
machines_dir - Absolute path to the directory where systemd-nspawn expects
to find the container chroots. Unless you know what you're doing, keep the
timeout - The timeout in seconds to wait for container startup and
shutdown. The default is 20 seconds.
See nspawn.pkr.hcl for an example of how to build a minimal base container, archive it into a tarball, clone it a new container, and import a container image from the archived tarball.
Copyright (c) 2020 Dmitry Borodaenko email@example.com
This program is free software. You can distribute/modify this program under the terms of the GNU General Public License version 3 or later, or under the terms of the Mozilla Public License, v. 2.0, at your discretion.
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This Source Code Form is not "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0.