Systemd-machined
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 containersmachinectl list-images
- list offline containersmachinectl start NAME
- start an imagemachinectl login NAME
- log into a running container, like a serial loginmachinectl shell NAME
- directly start a shell in the containermachinectl 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
- TODO: integrate systemd-sysupdate
- TODO: checksum validation https://github.com/openSUSE/open-build-service/issues/10407
- XXX: need to figure out why the container is read-only by default and fix that
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