Difference between revisions of "Systemd-nspawn"

From ArchWiki
Jump to: navigation, search
(Fix style. Add category. See Help:Style.)
(Configure networking: textedit)
 
(205 intermediate revisions by 43 users not shown)
Line 1: Line 1:
[[Category:Security]]
+
{{Lowercase title}}
Quick guide on how to create a lightweight systemd container for Arch Linux, using systemd-nspawn and pacstrap, in under 1 minute!
+
[[Category:Virtualization]]
 +
[[ja:Systemd-nspawn]]
 +
[[ru:Systemd-nspawn]]
 +
{{Related articles start}}
 +
{{Related|systemd}}
 +
{{Related|Linux Containers}}
 +
{{Related|systemd-networkd}}
 +
{{Related|Docker}}
 +
{{Related|Lxc-systemd}}
 +
{{Related articles end}}
 +
 
 +
''systemd-nspawn'' is like the [[chroot]] command, but it is a ''chroot on steroids''.
 +
 
 +
''systemd-nspawn'' may be used to run a command or OS in a light-weight namespace container. It is more powerful than [[chroot]] since it fully virtualizes the file system hierarchy, as well as the process tree, the various IPC subsystems and the host and domain name.
 +
 
 +
''systemd-nspawn'' limits access to various kernel interfaces in the container to read-only, such as {{ic|/sys}}, {{ic|/proc/sys}} or {{ic|/sys/fs/selinux}}. Network interfaces and the system clock may not be changed from within the container. Device nodes may not be created. The host system cannot be rebooted and kernel modules may not be loaded from within the container.
 +
 
 +
This mechanism differs from [[Lxc-systemd]] or [[Libvirt]]-lxc, as it is a much simpler tool to configure.
  
 
== Installation ==
 
== Installation ==
  
pacman -S arch-install-scripts
+
''systemd-nspawn'' is part of and packaged with {{Pkg|systemd}}.
  mkdir /srv/subarch
+
 
pacstrap -c -d /srv/subarch base
+
== Examples ==
  systemd-nspawn -bD /srv/subarch
+
 
 +
=== Create and boot a minimal Arch Linux distribution in a container ===
 +
 
 +
First install {{Pkg|arch-install-scripts}}.
 +
 
 +
Next, create a directory to hold the container. In this example we will use {{ic|~/MyContainer}}.
 +
 
 +
Next, we use pacstrap to install a basic arch-system into the container. At minimum we need to install the {{Grp|base}} group.
 +
   
 +
# pacstrap -i -c -d ~/MyContainer base [additional pkgs/groups]
 +
 
 +
{{Tip|The {{ic|-i}} option will '''avoid''' auto-confirmation of package selection. As you do not need to install the Linux kernel in the container, you can remove it from the package list selection to save space. See [[Pacman#Usage]].}}
 +
 
 +
{{Note|The package {{Pkg|linux-firmware}} required by {{Pkg|linux}}, which is included in the {{Grp|base}} group and isn't necessary to run the container, causes some issues to {{ic|systemd-tmpfiles-setup.service}} during the booting process with {{ic|systemd-nspawn}}. It's possible to install the {{Grp|base}} group but excluding the {{Pkg|linux}} package and its dependencies when building the container with {{ic|# pacstrap -i -c -d ~/MyContainer base --ignore linux [additional pkgs/groups]}}. The {{ic|--ignore}} flag will be simply passed to {{Pkg|pacman}}. See {{Bug|46591}} for more information.}}
 +
 
 +
Once your installation is finished, boot into the container:
 +
 
 +
# systemd-nspawn -b -D ~/MyContainer -n
 +
 
 +
The {{ic|-b}} option will boot the container (i.e. run {{ic|systemd}} as PID=1), instead of just running a shell. {{ic|-D}} specifies the directory that becomes the container's root directory and {{ic|-n}} will set up a private network between host and container.
 +
 
 +
After the container starts, log in as "root" with no password.
 +
 
 +
The container can be powered off by running {{ic|poweroff}} from within the container. From the host, containers can be controlled by the [[#machinectl|machinectl]] tool.
 +
 
 +
{{Note|To terminate the ''session'' from within the container, hold {{ic|Ctrl}} and rapidly press {{ic|]}} three times. Non US keyboard will use {{ic|%}} instead of {{ic|]}}}}
 +
 
 +
==== Bootstrap Arch Linux i686 inside x86_64 host ====
 +
 
 +
It is possible to install a minimal i686 Arch Linux inside a subdirectory and use it as systemd-nspawn container instead of [[chroot]] or [[virtualization]]. This is useful for testing {{ic|PKGBUILD}} compilation for i686 and other tasks. Make sure you use a {{ic|pacman.conf}} '''without''' {{ic|multilib}} repository.
 +
 
 +
  # pacman_conf=/tmp/pacman.conf # this is pacman.conf without multilib
 +
  # mkdir /mnt/i686-archlinux
 +
  # linux32 pacstrap -C "$pacman_conf" -di /mnt/i686-archlinux base base-devel
 +
 
 +
You may deselect {{ic|linux}} from {{ic|base}} group, since the resulting bootstrap directory is not meant to be booted on real or virtualized hardware.
 +
 
 +
To start the resulting i686 Arch Linux systemd-nspawn instance, just issue the following command.
 +
 
 +
  # linux32 systemd-nspawn -D /mnt/i686-archlinux
 +
 
 +
=== Create a Debian or Ubuntu environment ===
 +
 
 +
Install {{Pkg|debootstrap}}, {{Aur|gnupg1}}, and one or both of {{Aur|debian-archive-keyring}} and {{Aur|ubuntu-keyring}} (obviously install the keyrings for the distros you want).
 +
 
 +
{{Note|systemd-nspawn requires that the os in the container has systemd running as PID 1, this means Ubuntu before 15.04 will not work out of the box and requires additional configuration to switch from upstart to systemd.}}
 +
 
 +
From there it's rather easy to setup Debian or Ubuntu environments:
 +
 
 +
# cd /var/lib/machines
 +
# debootstrap <codename> myContainer <repository>
 +
 
 +
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 "wily" or "hardy" should be used. A complete list is in /usr/share/debootstrap/scripts
 +
 
 +
Unlike Arch, Debian and Ubuntu will not let you login without a password on first login. To set the root password login without the '-b' option and set a password:
 +
 
 +
  # systemd-nspawn -D myContainer
 +
# passwd
 +
# logout
 +
 
 +
=== Enable container on boot ===
 +
 
 +
When using a container frequently, you may want to start it on boot.
 +
 
 +
First [[enable]] the {{ic|machines.target}} target, then {{ic|systemd-nspawn@''myContainer''.service}}, where {{ic|myContainer}} is an nspawn container in {{ic|/var/lib/machines}}.
 +
 
 +
{{Tip|
 +
* Symbolic links to containers in {{ic|/var/lib/machines}} do not work as of {{Pkg|systemd}} v229, see [https://github.com/systemd/systemd/issues/2001].
 +
* To customize the startup of a container, [[edit]] the {{ic|systemd-nspawn@''myContainer''}} unit instance. See {{ic|systemd-nspawn(1)}} for all options.
 +
}}
 +
 
 +
=== Build and test packages ===
 +
 
 +
See [[Creating packages for other distributions]] for example uses.
 +
 
 +
== Management ==
 +
 
 +
=== machinectl ===
 +
 
 +
{{Note|The ''machinectl'' tool requires [[systemd]] and {{Pkg|dbus}} to be installed in the container. See [https://github.com/systemd/systemd/issues/685] for detailed discussion.}}
 +
 
 +
Managing your containers is essentially done with the {{ic|machinectl}} command. See {{ic|machinectl(1)}} for details.
 +
 
 +
Examples:
 +
 
 +
Spawn a new shell inside a running container:
 +
 
 +
$ machinectl login ''MyContainer''
 +
 
 +
Show detailed information about a container:
 +
 +
$ machinectl status ''MyContainer''
 +
 
 +
Reboot a container:
 +
 
 +
$ machinectl reboot ''MyContainer''
 +
 
 +
Poweroff a container:
 +
 +
$ machinectl poweroff ''MyContainer''
 +
 
 +
{{Tip|Poweroff and reboot operations can be performed from within a container session using the ''systemctl'' {{ic|poweroff}} or {{ic|reboot}} commands.}}
 +
 
 +
Download an image:
 +
 
 +
# machinectl pull-tar ''URL'' ''name''
 +
 
 +
=== systemd toolchain ===
 +
 
 +
Much of the core systemd toolchain has been updated to work with containers. Tools that do usually provide a {{ic|1=-M, --machine=}} option which will take a container name as argument.
 +
 
 +
Examples:
 +
 
 +
See journal logs for a particular machine:
 +
 
 +
$ journalctl -M ''MyContainer''
 +
 
 +
Show control group contents:
 +
 
 +
$ systemd-cgls -M ''MyContainer''
 +
 
 +
See startup time of container:
 +
 
 +
$ systemd-analyze -M ''MyContainer''
 +
 
 +
For an overview of resource usage:
 +
 
 +
$ systemd-cgtop
 +
 
 +
== Tips and tricks ==
 +
 
 +
=== Use an X environment ===
 +
 
 +
See [[Xhost]] and [[Change root#Run graphical applications from chroot]].
 +
 
 +
You will need to set the {{ic|DISPLAY}} environment variable inside your container session to connect to the external X server.
 +
 
 +
X stores some required files in the {{ic|/tmp}} directory. In order for your container to display anything, it needs access to those files. To do so, append the {{ic|--bind<nowiki>=</nowiki>/tmp/.X11-unix:/tmp/.X11-unix}} option when starting the container.
 +
 
 +
=== Run Firefox  ===
 +
 
 +
See [[Firefox tweaks#Run Firefox inside an nspawn container|Firefox tweaks]].
 +
 
 +
=== Access host filesystem ===
 +
 
 +
See {{ic|--bind}} and {{ic|--bind-ro}} in {{ic|man systemd-nspawn}}.
 +
 
 +
If both the host and the container are Arch Linux, then one could, for example, share the pacman cache:
 +
 
 +
# systemd-nspawn --bind=/var/cache/pacman/pkg
 +
 
 +
=== Configure networking ===
 +
 
 +
{{Style}}
 +
 
 +
Note the canonical [[systemd-networkd]] host and container .network files are from https://github.com/systemd/systemd/tree/master/network
 +
 
 +
You need to set up the container .network manually after pacstrapping and {{ic|# systemctl enable [[systemd-networkd]]}} (your dhcp client) with systemd-nspawn's -n switch to ensure a virtual Ethernet link is setup. Don't forget to set up DNS, e.g. by either 1) [[textedit|edit]] your container's {{ic|/etc/resolv.conf}} by adding your DNS server's IP address, or have 2) [[systemd-resolved]] manage {{ic|/etc/resolv.conf}} for you.
 +
 
 +
See [[systemd-networkd#Usage with containers]] for more complex examples.
 +
 
 +
==== nsswitch.conf ====
 +
 
 +
{{Merge|systemd-networkd}}
 +
 
 +
To make it easier to connect to a container from the host, you can enable local DNS resolution for container names. In {{ic|/etc/nsswitch.conf}}, add {{ic|mymachines}} to the {{ic|hosts:}} section, e.g.
 +
 
 +
hosts: files mymachines dns myhostname
 +
 
 +
Then, any DNS lookup for hostname {{ic|foo}} on the host will first consult {{ic|/etc/hosts}}, then the names of local containers, then upstream DNS etc.
 +
 
 +
==== Use host networking ====
 +
 
 +
To disable private networking used by containers started with {{ic|machinectl start MyContainer}}, [[edit]] the configuration of {{ic|systemd-nspawn@.service}} with {{ic|systemctl edit systemd-nspawn@.service}} and set the {{ic|1=ExecStart=}} option without the {{ic|--network-veth}} parameter unlike the original service:
 +
 
 +
{{hc|/etc/systemd/system/systemd-nspawn@.service.d/override.conf|<nowiki>
 +
[Service]
 +
ExecStart=
 +
ExecStart=/usr/bin/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --machine=%I
 +
</nowiki>}}
 +
 
 +
The newly started containers will use the hosts networking.
 +
 
 +
==== Virtual Ethernet interfaces ====
 +
 
 +
If a container is started with {{ic|systemd-nspawn ... -n}}, systemd will automatically create one virtual Ethernet interface on the host, and one in the container, connected by a virtual Ethernet cable.
 +
 
 +
If the name of the container is {{ic|foo}}, the name of the virtual Ethernet interface on the host is {{ic|ve-foo}}. The name of the virtual Ethernet interface in the container is always {{ic|host0}}.
 +
 
 +
When examining the interfaces with {{ic|ip link}}, interface names will be shown with a suffix, such as {{ic|ve-foo@if2}} and {{ic|host0@if9}}. The {{ic|@ifN}} is not actually part of the name of the interface; instead, {{ic|ip link}} appends this information to indicate which "slot" the virtual Ethernet cable connects to on the other end.
 +
 
 +
For example, a host virtual Ethernet interface shown as {{ic|ve-foo@if2}} will connect to container {{ic|foo}}, and inside the container to the second network interface -- the one shown with index 2 when running {{ic|ip link}} inside the container. Similarly, in the container, the interface named {{ic|host0@if9}} will connect to the 9th slot on the host.
 +
 
 +
=== Run on a non-systemd system ===
 +
 
 +
See [[Init#systemd-nspawn]].
 +
 
 +
=== Specify per-container settings ===
 +
 
 +
To specify per-container settings and not overrides for all (e.g. bind a directory to only one container)[https://github.com/systemd/systemd/issues/3442#issuecomment-223837408], the ".nspawn" file definition can be used [https://www.freedesktop.org/software/systemd/man/systemd.nspawn.html#]
 +
 
 +
  man systemd.nspawn
 +
 
 +
=== Use Btrfs subvolume as container root ===
 +
 
 +
To use a btrfs subvolume as a template for the container's root, use the {{ic|--template}} flag. This takes a snapshot of the subvolume and populates the root directory for the container with it.
 +
 
 +
{{Note|If the template path specified is not the root of a subvolume, the '''entire''' tree is copied. This will be very time consuming.}}
 +
 
 +
For example, to use a snapshot located at {{ic|/.snapshots/403/snapshot}}:
 +
 
 +
# systemd-nspawn --template=/.snapshots/403/snapshots -b -D ''my-container''
 +
 
 +
where {{ic|''my-container''}} is the name of the directory that will be created for the container. After powering off, the newly created subvolume is retained.
 +
 
 +
=== Use temporary Btrfs snapshot of container ===
 +
 
 +
One can use the {{ic|--ephemeral}} or {{ic|-x}} flag to create a temporary btrfs snapshot of the container and use it as the container root. Any changes made while booted in the container will be lost. For example:
 +
 
 +
# systemd-nspawn -D ''my-container'' -xb
 +
 
 +
where ''my-container'' is the directory of an '''existing''' container or system. For example, if {{ic|/}} is a btrfs subvolume one could create an ephemeral container of the currently running host system by doing:
 +
 
 +
# systemd-nspawn -D / -xb
 +
 
 +
After powering off the container, the btrfs subvolume that was created is immediately removed.
 +
 
 +
== Troubleshooting ==
 +
 
 +
=== root login fails ===
 +
 
 +
If you get the following error when you try to login (i.e. using {{ic|machinectl login <name>}}):
 +
 
 +
arch-nspawn login: root
 +
Login incorrect
 +
 
 +
And {{ic|journalctl}} shows:
 +
 
 +
pam_securetty(login:auth): access denied: tty 'pts/0' is not secure !
 +
 
 +
Add {{ic|pts/0}} to the list of terminal names in {{ic|/etc/securetty}} on the '''container''' filesystem, see [http://unix.stackexchange.com/questions/41840/effect-of-entries-in-etc-securetty/41939#41939]. You can also opt to delete {{ic|/etc/securetty}} on the '''container''' to allow root to login to any tty, see [https://github.com/systemd/systemd/issues/852].
  
And that's it! Log in as "root" with no password.
+
=== Unable to upgrade some packages on the container ===
  
You can remove the kernel to save space within the container. DO NOT RUN THIS ON THE HOST!
+
It can sometimes be impossible to upgrade some packages on the container, {{Pkg|filesystem}} being a perfect example. The issue is due to {{ic|/sys}} being mounted as Read Only. The workaround is to remount the directory in Read Write when running {{ic|mount -o remount,rw -t sysfs sysfs /sys}}, do the upgrade then reboot the container.
  
pacman -Rsn linux
+
== See also ==
  
Once you're done with the container just shut it down with {{ic|poweroff}}.
+
* [http://www.freedesktop.org/software/systemd/man/machinectl.html machinectl man page]
 +
* [http://www.freedesktop.org/software/systemd/man/systemd-nspawn.html systemd-nspawn man page]
 +
* [http://lwn.net/Articles/572957/ Creating containers with systemd-nspawn]
 +
* [https://www.youtube.com/results?search_query=systemd-nspawn&aq=f Presentation by Lennart Pottering on systemd-nspawn]
 +
* [http://dabase.com/e/12009/ Running Firefox in a systemd-nspawn container]

Latest revision as of 14:51, 25 August 2016

systemd-nspawn is like the chroot command, but it is a chroot on steroids.

systemd-nspawn may be used to run a command or OS in a light-weight namespace container. It is more powerful than chroot since it fully virtualizes the file system hierarchy, as well as the process tree, the various IPC subsystems and the host and domain name.

systemd-nspawn limits access to various kernel interfaces in the container to read-only, such as /sys, /proc/sys or /sys/fs/selinux. Network interfaces and the system clock may not be changed from within the container. Device nodes may not be created. The host system cannot be rebooted and kernel modules may not be loaded from within the container.

This mechanism differs from Lxc-systemd or Libvirt-lxc, as it is a much simpler tool to configure.

Installation

systemd-nspawn is part of and packaged with systemd.

Examples

Create and boot a minimal Arch Linux distribution in a container

First install arch-install-scripts.

Next, create a directory to hold the container. In this example we will use ~/MyContainer.

Next, we use pacstrap to install a basic arch-system into the container. At minimum we need to install the base group.

# pacstrap -i -c -d ~/MyContainer base [additional pkgs/groups]
Tip: The -i option will avoid auto-confirmation of package selection. As you do not need to install the Linux kernel in the container, you can remove it from the package list selection to save space. See Pacman#Usage.
Note: The package linux-firmware required by linux, which is included in the base group and isn't necessary to run the container, causes some issues to systemd-tmpfiles-setup.service during the booting process with systemd-nspawn. It's possible to install the base group but excluding the linux package and its dependencies when building the container with # pacstrap -i -c -d ~/MyContainer base --ignore linux [additional pkgs/groups]. The --ignore flag will be simply passed to pacman. See FS#46591 for more information.

Once your installation is finished, boot into the container:

# systemd-nspawn -b -D ~/MyContainer -n

The -b option will boot the container (i.e. run systemd as PID=1), instead of just running a shell. -D specifies the directory that becomes the container's root directory and -n will set up a private network between host and container.

After the container starts, log in as "root" with no password.

The container can be powered off by running poweroff from within the container. From the host, containers can be controlled by the machinectl tool.

Note: To terminate the session from within the container, hold Ctrl and rapidly press ] three times. Non US keyboard will use % instead of ]

Bootstrap Arch Linux i686 inside x86_64 host

It is possible to install a minimal i686 Arch Linux inside a subdirectory and use it as systemd-nspawn container instead of chroot or virtualization. This is useful for testing PKGBUILD compilation for i686 and other tasks. Make sure you use a pacman.conf without multilib repository.

 # pacman_conf=/tmp/pacman.conf # this is pacman.conf without multilib
 # mkdir /mnt/i686-archlinux
 # linux32 pacstrap -C "$pacman_conf" -di /mnt/i686-archlinux base base-devel

You may deselect linux from base group, since the resulting bootstrap directory is not meant to be booted on real or virtualized hardware.

To start the resulting i686 Arch Linux systemd-nspawn instance, just issue the following command.

 # linux32 systemd-nspawn -D /mnt/i686-archlinux

Create a Debian or Ubuntu environment

Install debootstrap, gnupg1AUR, and one or both of debian-archive-keyringAUR and ubuntu-keyringAUR (obviously install the keyrings for the distros you want).

Note: systemd-nspawn requires that the os in the container has systemd running as PID 1, this means Ubuntu before 15.04 will not work out of the box and requires additional configuration to switch from upstart to systemd.

From there it's rather easy to setup Debian or Ubuntu environments:

# cd /var/lib/machines
# debootstrap <codename> myContainer <repository>

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 "wily" or "hardy" should be used. A complete list is in /usr/share/debootstrap/scripts

Unlike Arch, Debian and Ubuntu will not let you login without a password on first login. To set the root password login without the '-b' option and set a password:

# systemd-nspawn -D myContainer
# passwd
# logout

Enable container on boot

When using a container frequently, you may want to start it on boot.

First enable the machines.target target, then systemd-nspawn@myContainer.service, where myContainer is an nspawn container in /var/lib/machines.

Tip:
  • Symbolic links to containers in /var/lib/machines do not work as of systemd v229, see [1].
  • To customize the startup of a container, edit the systemd-nspawn@myContainer unit instance. See systemd-nspawn(1) for all options.

Build and test packages

See Creating packages for other distributions for example uses.

Management

machinectl

Note: The machinectl tool requires systemd and dbus to be installed in the container. See [2] for detailed discussion.

Managing your containers is essentially done with the machinectl command. See machinectl(1) for details.

Examples:

Spawn a new shell inside a running container:

$ machinectl login MyContainer

Show detailed information about a container:

$ machinectl status MyContainer

Reboot a container:

$ machinectl reboot MyContainer

Poweroff a container:

$ machinectl poweroff MyContainer
Tip: Poweroff and reboot operations can be performed from within a container session using the systemctl poweroff or reboot commands.

Download an image:

# machinectl pull-tar URL name

systemd toolchain

Much of the core systemd toolchain has been updated to work with containers. Tools that do usually provide a -M, --machine= option which will take a container name as argument.

Examples:

See journal logs for a particular machine:

$ journalctl -M MyContainer

Show control group contents:

$ systemd-cgls -M MyContainer

See startup time of container:

$ systemd-analyze -M MyContainer

For an overview of resource usage:

$ systemd-cgtop

Tips and tricks

Use an X environment

See Xhost and Change root#Run graphical applications from chroot.

You will need to set the DISPLAY environment variable inside your container session to connect to the external X server.

X stores some required files in the /tmp directory. In order for your container to display anything, it needs access to those files. To do so, append the --bind=/tmp/.X11-unix:/tmp/.X11-unix option when starting the container.

Run Firefox

See Firefox tweaks.

Access host filesystem

See --bind and --bind-ro in man systemd-nspawn.

If both the host and the container are Arch Linux, then one could, for example, share the pacman cache:

# systemd-nspawn --bind=/var/cache/pacman/pkg

Configure networking

Tango-edit-clear.pngThis article or section needs language, wiki syntax or style improvements.Tango-edit-clear.png

Reason: please use the first argument of the template to provide a brief explanation. (Discuss in Talk:Systemd-nspawn#)

Note the canonical systemd-networkd host and container .network files are from https://github.com/systemd/systemd/tree/master/network

You need to set up the container .network manually after pacstrapping and # systemctl enable systemd-networkd (your dhcp client) with systemd-nspawn's -n switch to ensure a virtual Ethernet link is setup. Don't forget to set up DNS, e.g. by either 1) edit your container's /etc/resolv.conf by adding your DNS server's IP address, or have 2) systemd-resolved manage /etc/resolv.conf for you.

See systemd-networkd#Usage with containers for more complex examples.

nsswitch.conf

Merge-arrows-2.pngThis article or section is a candidate for merging with systemd-networkd.Merge-arrows-2.png

Notes: please use the second argument of the template to provide more detailed indications. (Discuss in Talk:Systemd-nspawn#)

To make it easier to connect to a container from the host, you can enable local DNS resolution for container names. In /etc/nsswitch.conf, add mymachines to the hosts: section, e.g.

hosts: files mymachines dns myhostname

Then, any DNS lookup for hostname foo on the host will first consult /etc/hosts, then the names of local containers, then upstream DNS etc.

Use host networking

To disable private networking used by containers started with machinectl start MyContainer, edit the configuration of systemd-nspawn@.service with systemctl edit systemd-nspawn@.service and set the ExecStart= option without the --network-veth parameter unlike the original service:

/etc/systemd/system/systemd-nspawn@.service.d/override.conf
[Service]
ExecStart=
ExecStart=/usr/bin/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --machine=%I

The newly started containers will use the hosts networking.

Virtual Ethernet interfaces

If a container is started with systemd-nspawn ... -n, systemd will automatically create one virtual Ethernet interface on the host, and one in the container, connected by a virtual Ethernet cable.

If the name of the container is foo, the name of the virtual Ethernet interface on the host is ve-foo. The name of the virtual Ethernet interface in the container is always host0.

When examining the interfaces with ip link, interface names will be shown with a suffix, such as ve-foo@if2 and host0@if9. The @ifN is not actually part of the name of the interface; instead, ip link appends this information to indicate which "slot" the virtual Ethernet cable connects to on the other end.

For example, a host virtual Ethernet interface shown as ve-foo@if2 will connect to container foo, and inside the container to the second network interface -- the one shown with index 2 when running ip link inside the container. Similarly, in the container, the interface named host0@if9 will connect to the 9th slot on the host.

Run on a non-systemd system

See Init#systemd-nspawn.

Specify per-container settings

To specify per-container settings and not overrides for all (e.g. bind a directory to only one container)[3], the ".nspawn" file definition can be used [4]

 man systemd.nspawn

Use Btrfs subvolume as container root

To use a btrfs subvolume as a template for the container's root, use the --template flag. This takes a snapshot of the subvolume and populates the root directory for the container with it.

Note: If the template path specified is not the root of a subvolume, the entire tree is copied. This will be very time consuming.

For example, to use a snapshot located at /.snapshots/403/snapshot:

# systemd-nspawn --template=/.snapshots/403/snapshots -b -D my-container

where my-container is the name of the directory that will be created for the container. After powering off, the newly created subvolume is retained.

Use temporary Btrfs snapshot of container

One can use the --ephemeral or -x flag to create a temporary btrfs snapshot of the container and use it as the container root. Any changes made while booted in the container will be lost. For example:

# systemd-nspawn -D my-container -xb

where my-container is the directory of an existing container or system. For example, if / is a btrfs subvolume one could create an ephemeral container of the currently running host system by doing:

# systemd-nspawn -D / -xb 

After powering off the container, the btrfs subvolume that was created is immediately removed.

Troubleshooting

root login fails

If you get the following error when you try to login (i.e. using machinectl login <name>):

arch-nspawn login: root
Login incorrect

And journalctl shows:

pam_securetty(login:auth): access denied: tty 'pts/0' is not secure !

Add pts/0 to the list of terminal names in /etc/securetty on the container filesystem, see [5]. You can also opt to delete /etc/securetty on the container to allow root to login to any tty, see [6].

Unable to upgrade some packages on the container

It can sometimes be impossible to upgrade some packages on the container, filesystem being a perfect example. The issue is due to /sys being mounted as Read Only. The workaround is to remount the directory in Read Write when running mount -o remount,rw -t sysfs sysfs /sys, do the upgrade then reboot the container.

See also