Systemd-machined

Jump to: navigation, search

Introduction

systemd-machined is a lightweight container manager, primarily designed to manage systemd-nspawn containers.

Most importantly the containers manged by machined actually boot a full system with systemd inside the container rather than just running a single service. That makes it ideal for using containers like virtual machines, just without an extra kernel and VM. A container can be simply a file system tree (preferably in a btrfs subvolume) or a disk image.

systemd-machined comes from systemd directly and is therefore tightly integrated. Using such containers feels very natural when familiar with running service units. Even the journal output of the containers is visible via journalctl on the host.

Installation

systemd-machined is contained in the systemd-container package and can be installed using zypper.

Usage

  • machinectl list - list running containers
  • machinectl list-images - list offline containers
  • machinectl start NAME - start an image
  • machinectl login NAME - log into a running container, like a serial login
  • machinectl shell NAME - directly start a shell in the container
  • machinectl enable NAME - enable a container to run at boot

Getting Started

The quickest way to get something up and running is to simply download a ready-made TW appliance. It will be stored in /var/lib/machines in a btrfs subvolume.

   # machinectl pull-tar --verify=no http://download.opensuse.org/tumbleweed/appliances/opensuse-tumbleweed-image.x86_64-networkd.tar.xz tumbleweed
   # machinectl read-only tumbleweed false
   # machinectl start tumbleweed
   # machinectl shell tumbleweed

Network

For DHCP and DNS to work automatically in the container it's easiest to have systemd-networkd installed on the host. systemd-networkd can be run in parallel to eg NetworkManager just fine as systemd-networkd only picks up interfaces created by systemd-machined by default.

   # zypper in systemd-network
   # systemctl enable systemd-networkd

By default the DNS servers from /etc/resolv.conf of the host are also used in the container. If resolv.conf has no DNS server, eg because a local dnsmasq is used, one needs to manually configure the host's networkd to emit a specific DNS server address to containers.

   # mkdir -p /etc/systemd/network/80-container-ve.network.d
   # echo -e "[DHCPServer]\nDNS=1.1.1.1" > /etc/systemd/network/80-container-ve.network.d/dhcp-dns-cloudflare.conf

Firewalld integration

Make sure connections have zones properly assigned. Interfaces without explicit zone assigned are normally configured to use the 'public' zone. You may want to eg assign your wifi connection to the 'home' zone and your company wifi to 'work'.

Example:

/etc/NetworkManager/system-connections/ACME-vpn

   [connection]
   zone=work

Create new zone for machined containers

   firewall-cmd --permanent --new-zone machined
   firewall-cmd --permanent --zone machined --add-service dhcp
   firewall-cmd --permanent --zone machined --add-service dhcpv6-client

Enable masquerading on the outgoing interfaces

   firewall-cmd --permanent --zone=public --add-masquerade
   firewall-cmd --permanent --zone=home --add-masquerade
   firewall-cmd --permanent --zone=work --add-masquerade

Create a policy that allows forwarding

   firewall-cmd --permanent --new-policy=machined-policy
   firewall-cmd --permanent --policy=machined-policy --add-egress-zone=public
   firewall-cmd --permanent --policy=machined-policy --add-egress-zone=home
   firewall-cmd --permanent --policy=machined-policy --add-egress-zone=work
   firewall-cmd --permanent --policy=machined-policy --set-target=ACCEPT

Add your machined interfaces to machined zone (ip l l to list interfaces, it's ve-*)

   firewall-cmd --permanent --zone machined --add-interface=ve-tumbleweed

Reload firewall

   firewall-cmd --reload

Mapping Users

Mapping users is a very convenient feature to use your your host user inside the container. For this feature to work, private user groups must be used. Check whether the id command reports identical uid and gid. If not create a group with same name and gid as your user and make it primary group of your user.

If your user has a private group, configure the container to use it. In /etc/systemd/nspawn/name.nspawn add

   [Files]
   BindUser=alan

Inside the container nss-systemd must be active:

   # zypper in nss-systemd
   # grep -v '^#\|^$' /usr/etc/nsswitch.conf  > /etc/nsswitch.conf
   # vi /etc/nsswitch.conf
   # grep systemd /etc/nsswitch.conf
   passwd:         compat systemd
   group:          compat [SUCCESS=merge] systemd
   shadow:         compat systemd
   ## or with one sed command:
   # sed -e '/^#\|^$/d;s/^\(group:\s*compat\)$/\1 [SUCCESS=merge] systemd/;s/^\(\(passwd\|shadow\):\s*compat\)/\1  systemd/' /usr/etc/nsswitch.conf > /etc/nsswitch.conf

Using containers as user

It's possible to start, stop and login into containers as user without root privileges. Root is only needed to set it up. You can install the polkit policy from home:lnussel:systemd/systemd-machined-userpolicy

Containers following the schema user-$USERNAME-SOMETHING can be manged by $USERNAME without authentication then. So rename the container created above:

   machinectl rename tumbleweed user-alan-tumbleweed

Mapping directories

It's also possible to mount certain host directories into the container. That's convenient if you e.g. keep your source code somewhere outside your home or want to store data of some daemon on the host.

/etc/systemd/nspawn/name.nspawn:

   [Files]
   Bind=/work/git