<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>systemd &amp;mdash; Sebastian Wiesner</title>
    <link>https://swsnr.writeas.com/tag:systemd</link>
    <description>System engineer for satellite mission planning. Gnome. Rust. Arch.  </description>
    <pubDate>Sat, 09 May 2026 12:25:34 +0000</pubDate>
    <image>
      <url>https://i.snap.as/9knB2j11.jpg</url>
      <title>systemd &amp;mdash; Sebastian Wiesner</title>
      <link>https://swsnr.writeas.com/tag:systemd</link>
    </image>
    <item>
      <title>logcontrol – an underappreciated systemd feature</title>
      <link>https://swsnr.writeas.com/logcontrol-an-underappreciated-systemd-feature?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[#systemd #rust&#xA;&#xA;Systemd has this feature which lets you change the log level of a service on the fly.  You can actually do this:&#xA;&#xA;$ sudo systemctl service-log-level systemd-resolved.service debug&#xA;$ resolvectl query some-funky-domain.example.com&#xA;$ sudo systemctl service-log-level systemd-resolved.service info&#xA;&#xA;to get a debug log of systemd-resolved trying to resolve a specific domain.&#xA;&#xA;This is backed by dbus: If a service listens on dbus and has its bus name defined in its unit file then it can expose the log control interface on its bus connection to let systemctl change its log level and log target.&#xA;&#xA;All of systemd&#39;s own services support this interface, but unfortunately it hasn&#39;t seen wide-spread adoption outside systemd yet.  Which is kinda sad, because it&#39;s really a great feature for debugging.&#xA;&#xA;I certainly plan to use it more, so I put up logcontrol.rs on crates.io.&#xA;&#xA;a href=&#34;https://remark.as/p/swsnr/logcontrol-an-underappreciated-systemd-feature&#34;Discuss.../a]]&gt;</description>
      <content:encoded><![CDATA[<p><a href="https://swsnr.writeas.com/tag:systemd" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">systemd</span></a> <a href="https://swsnr.writeas.com/tag:rust" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">rust</span></a></p>

<p>Systemd has this feature which lets you change the log level of a service on the fly.  You can actually do this:</p>

<pre><code class="language-console">$ sudo systemctl service-log-level systemd-resolved.service debug
$ resolvectl query some-funky-domain.example.com
$ sudo systemctl service-log-level systemd-resolved.service info
</code></pre>

<p>to get a debug log of systemd-resolved trying to resolve a specific domain.</p>

<p>This is backed by dbus: If a service listens on dbus and has its bus name defined in its unit file then it can expose the <a href="https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.LogControl1.html" rel="nofollow">log control interface</a> on its bus connection to let systemctl change its log level and log target.</p>

<p>All of systemd&#39;s own services support this interface, but unfortunately it hasn&#39;t seen wide-spread adoption outside systemd yet.  Which is kinda sad, because it&#39;s really a great feature for debugging.</p>

<p>I certainly plan to use it more, so I put up <a href="https://github.com/swsnr/logcontrol.rs" rel="nofollow">logcontrol.rs</a> on crates.io.</p>

<p><a href="https://remark.as/p/swsnr/logcontrol-an-underappreciated-systemd-feature" rel="nofollow">Discuss...</a></p>
]]></content:encoded>
      <guid>https://swsnr.writeas.com/logcontrol-an-underappreciated-systemd-feature</guid>
      <pubDate>Wed, 25 Oct 2023 19:00:18 +0000</pubDate>
    </item>
    <item>
      <title>Install Arch with Secure boot, TPM2-based LUKS encryption, and systemd-homed</title>
      <link>https://swsnr.writeas.com/install-arch-with-secure-boot-tpm2-based-luks-encryption-and-systemd-homed?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[#archlinux #systemd #secureboot #dracut #sbctl&#xA;&#xA;a href=&#34;https://remark.as/p/swsnr/install-arch-with-secure-boot-tpm2-based-luks-encryption-and-systemd-homed&#34;Discuss.../a &#xA;&#xA;Update: I no longer use dracut, and the corresponding part of this blog&#xA;post no longer reflects my setup.&#xA;&#xA;This article describes my Arch Linux setup which combines Secure Boot with custom keys, TPM2-based full disk encryption and systemd-homed into a fully encrypted and authenticated, yet convenient Linux system.&#xA;&#xA;This setup draws inspiration from Authenticated Boot and Disk Encryption on Linux and Unlocking LUKS2 volumes with TPM2, FIDO2, PKCS#11 Security Hardware on systemd 248 by Lennart Poettering, and combines my previous posts on these topics.&#xA;&#xA;!--more--&#xA;&#xA;What this setup does&#xA;&#xA;Authenticate the boot loader, kernel, initramfs, microcode with Secure Boot, using my own custom keys.  Nothing can boot which wasn’t signed by my keys.&#xA;Everything is either authenticated with my keys (kernel, initramfs, microcode) or encrypted (system partition).&#xA;Encrypt the system partition, and unlock it automatically if the boot process was authenticated, by means of a TPM2 key bound to the secure boot state.&#xA;Give every user their own dedicated encrypted home directory, which gets unlocked at login and locked again at logout.&#xA;&#xA;What it doesn’t&#xA;&#xA;Show an ugly LUKS password prompt at boot (even with Plymouth it’s not really pretty).&#xA;Leave some parts unencrypted and unauthenticated (conventional installations often fail to consider the initramfs).&#xA;Ask me twice for my password, once at boot to unlock the disk and then again at login.&#xA;Encrypt data of all users with a shared key.&#xA;&#xA;Tools used&#xA;&#xA;Archlinux&#xA;systemd   = 250&#xA;systemd-boot as bootloader&#xA;systemd in initramfs to automatically discover and mount the root filesystem&#xA;dracut to generate the initramfs and build signed UEFI binaries&#xA;sbctl to create and enroll Secure Boot keys, and sign binaries&#xA;systemd-homed to manage user accounts with per-user encrypted home directories&#xA;systemd-cryptenroll to add TPM2 and recovery keys tokens to a LUKS partition&#xA;&#xA;The setup&#xA;&#xA;Install the system&#xA;&#xA;We follow the Installation Guide up to and including section “Update the system clock”. Then we partition the disk (/dev/nvme0n1 in our case); we need an EFI system partition of about 500MB and a root partition spanning the rest of the disk. The EFI partition must be unencrypted and have a FAT filesystem; for the root file system we choose btrfs on top of an encrypted partition.&#xA;&#xA;First we partition the disk and reload the partition table; we take care to specify proper partition types (-t option) so that systemd can automatically discover and mount our filesystems without further configuration in /etc/crypttab or /etc/fstab (see Discoverable Partitions Specification (DPS)):&#xA;&#xA;$ targetdevice=/dev/nvme0n1&#xA;$ sgdisk -Z &#34;$targetdevice&#34;&#xA;$ sgdisk -n1:0:+550M -t1:ef00 -c1:EFISYSTEM -N2 -t2:8304 -c2:linux &#34;$targetdevice&#34;&#xA;$ sleep 3&#xA;$ partprobe -s &#34;$targetdevice&#34;&#xA;$ sleep 3&#xA;&#xA;Then we setup the encrypted partition for the root file system. We get asked for an encryption password where we pick a very simple encryption password (even “password” is good enough for now, really) to save some typing during installation, as we’ll later replace the password with TPM2 key and a random recovery key:&#xA;&#xA;$ cryptsetup luksFormat --type luks2 /dev/disk/by-partlabel/linux&#xA;$ cryptsetup luksOpen /dev/disk/by-partlabel/linux root&#xA;$ rootdevice=/dev/mapper/root&#xA;&#xA;Now we create the filesystems:&#xA;&#xA;$ mkfs.fat -F32 -n EFISYSTEM /dev/disk/by-partlabel/EFISYSTEM&#xA;$ mkfs.btrfs -f -L linux &#34;$rootdevice&#34;&#xA;&#xA;Now we can mount the filesystems and create some basic btrfs subvolumes:&#xA;&#xA;$ mount &#34;$rootdevice&#34; /mnt&#xA;$ mkdir /mnt/efi&#xA;$ mount /dev/disk/by-partlabel/EFISYSTEM /mnt/efi&#xA;$ for subvol in var var/log var/cache var/tmp srv home; do btrfs subvolume create &#34;/mnt/$subvol&#34;; done&#xA;&#xA;Now we’re ready to bootstrap Arch Linux: We generate a mirrorlist and install essential packages:&#xA;&#xA;$ reflector --save /etc/pacman.d/mirrorlist --protocol https --latest 5 --sort age&#xA;$ pacstrap /mnt base linux linux-firmware intel-ucode btrfs-progs dracut neovim&#xA;&#xA;This takes a while to download and installation all packages; afterwards we configure some essential settings. Choose locale settings and the $newhostname according to your personal preferences.&#xA;&#xA;$ ln -sf /usr/share/zoneinfo/Europe/Berlin /mnt/etc/localtime&#xA;$ sed -i -e &#39;/^#enGB.UTF-8/s/^#//&#39; /mnt/etc/locale.gen&#xA;$ echo &#39;LANG=enGB.UTF-8&#39;   /mnt/etc/locale.conf&#xA;$ echo &#39;KEYMAP=us&#39;   /mnt/etc/vconsole.conf&#xA;$ echo &#34;$newhostname&#34;   /mnt/etc/hostname&#xA;&#xA;Now we enter the new system and finish configuration by generating locales, enabling a few essential services and setting a root password:&#xA;&#xA;$ arch-chroot /mnt&#xA;$ locale-gen&#xA;$ systemctl enable systemd-homed&#xA;$ systemctl enable systemd-timesyncd&#xA;$ passwd root&#xA;&#xA;Still in chroot we now build unified EFI kernel images (including initrd and kernel) for booting and install the systemd-boot boot loader:&#xA;&#xA;$ pacman -S --noconfirm --asdeps binutils elfutils&#xA;$ dracut -f --uefi --regenerate-all&#xA;$ bootctl install&#xA;&#xA;We do not need to create /etc/fstab or /etc/crypttab; as we assigned the appropriate types to each partition and installed systemd-boot a systemd-based initramfs can automatically determine the disk the system was booted from, and discover all relevant partitions.  It can then use superblock information to automatically open encrypted LUKS devices and mount file systems.&#xA;&#xA;At this point we also need to take care to install everything we need for network configuration after reboot.  For desktop systems I prefer network manager because it integrates well into Gnome:&#xA;&#xA;$ pacman -S networkmanager&#xA;&#xA;We have finished the basic setup from the live disk now; let’s leave chroot and reboot:&#xA;&#xA;$ exit&#xA;$ reboot&#xA;&#xA;After reboot we can complete the system installation, by adding a desktop environment, applications, command line tools, etc.&#xA;&#xA;I like to automate this, and have two bash scripts in my dotfiles, one for boostrapping a new system from a live disk (arch/bootstrap-from-iso.bash) and another one for installing everything after the initial bootstrapping (arch/install.bash).&#xA;&#xA;Create homed user&#xA;&#xA;With the installation finished we create our user account with homectl; let’s name it foo for the purpose of this article. First we should disable copy on write for /home, because this file system feature doesn’t work well with large files frequently updated in place, such as disk images of virtual machines or loopback files as created by systemd-homed:&#xA;&#xA;$ chattr +C /home/&#xA;&#xA;We now create the foo user with an encrypted home directory backed by LUKS and btrfs:&#xA;&#xA;$ homectl create foo --storage luks --fs-type btrfs&#xA;&#xA;By default systemd assigns 85% of the available disk space to the user account, and will balance available space among all user accounts (based on a weight we can configure with —rebalance-weight). On a single user system we may prefer to set an explicit quota for the user account:&#xA;&#xA;$ homectl resize foo 50G&#xA;&#xA;We can also add some additional metadata to the user account:&#xA;&#xA;homectl update foo --real-name &#39;Foo&#39; --email-address foo@example.org --language enGB.UTF-8 --member-of wheel&#xA;&#xA;man homectl provides a complete list of flags; in particular it also offers support for various kinds of security tokens (e.g. FIDO2) for user authentication, provides plenty of means for resource accounting (e.g. memory consumption) for the user account, and supports different kinds of password policies.&#xA;&#xA;Finally we may run into systemd issues with home areas on btrfs (see below); if login fails with a “Operation on home failed: Not enough disk space for home” message we need to enable LUKS discard:&#xA;&#xA;homectl update foo --luks-discard=true&#xA;&#xA;This flag is not safe (heed the warning in man homectl), but until systemd improves its behaviour on btrfs we have no choice unfortunately.&#xA;&#xA;Setup secure boot&#xA;&#xA;First let’s check the secure boot state. We must be in Setup Mode in order to enroll our own keys:&#xA;&#xA;$ sbctl status&#xA;Installed:&#x9;✓ sbctl is installed&#xA;Owner GUID:&#x9;REDACTED&#xA;Setup Mode:&#x9;✗ Enabled&#xA;Secure Boot:&#x9;✗ Disabled&#xA;&#xA;To enable secure boot we need some keys which we generate with sbctl.  For historical reasons sbctl creates these keys in /usr/share/secureboot but plans exists to change this to a more appropriate place (see Github issue 57).&#xA;&#xA;$ sbctl create-keys&#xA;&#xA;Now we tell dracut how to sign the UEFI binaries it builds and rebuild our kernel images to get them signed:&#xA;&#xA;$ cat   /etc/dracut.conf.d/50-secure-boot.conf &lt;&lt;EOF&#xA;uefisecurebootcert=&#34;/usr/share/secureboot/keys/db/db.pem&#34;&#xA;uefisecurebootkey=&#34;/usr/share/secureboot/keys/db/db.key&#34;&#xA;EOF&#xA;$ dracut -f --uefi --regenerate-all&#xA;&#xA;Next we need to sign the bootloader.  With -s we ask sbctl to remember this file in its database which later lets us check signatures with sbctl verify and automatically update all signatures with sbctl sign-all. The sbctl package includes a pacman hook which automatically updates signatures when an EFI binary on /efi or in /usr/lib changed. Note that we do not sign the boot loader on /efi but instead place a signed copy in /usr/lib.  Starting with systemd 250 bootctl will pick up the signed copy when updating the boot loader.  Hence we reinstall the bootloader afterwards to put the signed copy on /efi.&#xA;&#xA;$ sbctl sign -s -o /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed /usr/lib/systemd/boot/efi/systemd-bootx64.efi&#xA;$ bootctl install&#xA;&#xA;We should also do the same for the firmware update to enable seamless firmware updates under secure boot.  Again we use -s to remember this file in the sbtctl database:&#xA;&#xA;$ sbctl sign -s -o /usr/lib/fwupd/efi/fwupdx64.efi.signed /usr/lib/fwupd/efi/fwupdx64.efi&#xA;&#xA;Now let’s verify that we have all signatures in place and enroll keys if everything’s properly signed:&#xA;&#xA;$ sbctl verify&#xA;Verifying file database and EFI images in /efi...&#xA;✓ /usr/lib/fwupd/efi/fwupdx64.efi.signed is signed&#xA;✓ /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed is signed&#xA;✓ /efi/EFI/BOOT/BOOTX64.EFI is signed&#xA;✓ /efi/EFI/Linux/linux-5.15.12-arch1-1-19ea0ebee1ea4de086128ce1a8e2197b-rolling.efi is signed&#xA;✓ /efi/EFI/systemd/systemd-bootx64.efi is signed&#xA;$ sbctl enroll-keys&#xA;&#xA;After a reboot we can check the secure boot state again; we’ll see that setup mode is now disabled, secure boot is on, and everything was properly enrolled:&#xA;&#xA;$ reboot&#xA;$ sbctl status&#xA;Installed:&#x9;✓ sbctl is installed&#xA;Owner GUID:&#x9;REDACTED&#xA;Setup Mode:&#x9;✓ Disabled&#xA;Secure Boot:&#x9;✓ Enabled&#xA;&#xA;Enroll TPM2 keys&#xA;&#xA;With the boot process secured we can now configure automatic unlocking of the root filesystem, by binding a LUKS key to the TPM.&#xA;&#xA;We enable the tpm2-tss module in the Dracut configuration, install the dependencies of this dracut module, and regenerate our UEFI kernel images (which will again be signed for secure boot):&#xA;&#xA;$ cat   /etc/dracut.conf.d/50-tpm2.conf &lt;&lt;EOF&#xA;adddracutmodules+=&#34; tpm2-tss &#34;&#xA;EOF&#xA;$ pacman -S tpm2-tools&#xA;$ dracut -f --uefi --regenerate-all&#xA;&#xA;Now we can enroll a TPM2 token (bound to the secure boot measurement in PCR 7) and a recovery key to our root filesystem. This prompts for an existing passphrase each time.  Store the recovery key at a safe place outside of this disk, to have it at hand if TPM2 unlocking ever breaks.&#xA;&#xA;$ systemd-cryptenroll /dev/gpt-auto-root-luks --recovery-key&#xA;$ systemd-cryptenroll /dev/gpt-auto-root-luks --tpm2-device=auto&#xA;&#xA;Now reboot and enjoy: The boot process goes straight all the way to the login manager and never shows a LUKS password prompt.  The root filesystem is still reasonably secure: The TPM2 key becomes invalid if the secure boot state changes (e.g. new keys are enrolled, or secure boot is disabled), and cannot be recovered if the disk is removed from the system. Consequently only a kernel signed and authenticated with your own secure boot keys can unlock the root disk automatically.&#xA;&#xA;Finally we can wipe the password slots if you like (make sure to have a recovery key at this point):&#xA;&#xA;$ systemd-cryptenroll /dev/gpt-auto-root-luks --wipe-slot=password&#xA;&#xA;If you cannot use secure boot for some reason you can alternatively bind the TPM2 token to a combination of firmware state and configuration and the exact boot chain (up to and including the specific kernel that was started), by specifing the PCR registers 0-5:&#xA;&#xA;$ systemd-cryptenroll /dev/gpt-auto-root-luks --tpm2-device=auto --tpm2-pcrs 0+1+2+3+4+5&#xA;&#xA;This only permits the current kernel and its specific boot chain (e.g bootloader used) to unlock the root filesystem automatically.  However this means that we need to reboot and then wipe and re-enroll the TPM2 token after every rebuild of the kernel image… which happens quite often in fact: Dracut updates or configuration changes, kernel updates, systemd updates (due to the EFI shim provided by systemd), bootloader updates, bootloader configuration changes, etc.&#xA;&#xA;Hence I generally recommend to use secure boot if possible in any way.&#xA;&#xA;Issues with this setup&#xA;&#xA;While I am happy with this setup it still has a few drawbacks and issues.&#xA;&#xA;Double encryption&#xA;&#xA;In this setup home directories get encrypted twice, once by homed and then again by the underlying LUKS device.  This wastes a bunch of CPU cycles and likely impacts performance a lot, though I haven’t measured the impact and it’s not so bad as to be noticeable in my day-to-day work.&#xA;&#xA;We could optimize this by putting /home/ on a separate partition backed by dm-integrity to authenticate the filesystem (omitting dm-integrity and using a plain file system leaves an attack vector, because linux cannot securely mount untrusted file systems).  This setup requires at least systemd 250 or newer, because earlier versions do not support dm-integrity well.  With systemd 250 we can setup a HMAC-based integrity device, put the HMAC key on the rootfs (e.g. /etc/keys/home.key) and register the home partition in /etc/integritytab with that key, and then mount it via /etc/fstab.&#xA;&#xA;However, this has a few issues on its own, because dm-integrity has a few design issues and is and nowhere near LUKS/dm-crypt:&#xA;&#xA;There’s no key management like LUKS for dm-crypt, meaning we can’t use passphrases or TPM2 keys for dm-integrity devices; instead we need a key file somewhere on disk.&#xA;Unlike LUKS/dm-crypt devices dm-integrity devices aren’t self-describing, because the superblock for dm-integrity doesn’t even contain the algorithm used (see &lt;https://github.com/systemd/systemd/pull/20902). We cannot mount a dm-integrity device without some extra configuration, and worse, getting the configuration wrong can silently corrupt the device.&#xA;For these reasons, DPS cannot and does not support dm-integrity partitions, so we need to configure the whole home partition mount, from dm-integrity up to /etc/fstab.&#xA;&#xA;Tooling issues&#xA;&#xA;There are also multiple issues with current tooling that require some more or less safe workarounds:&#xA;&#xA;At the time of writing systemd-home has issues with resizing LUKS home areas on btrfs filesystems, apparently due to fallocate() idiosyncrasies in btrfs. This issue prevents users from logging in, see systemd issues 19398 and 20960, an Arch forums post, and a mail on the systemd-devel list. A workaround is to enable online discard for the user, but this flag is unsafe because it allows overcommitting disk space, which results in IO errors that the kernel and application are not well prepared to handle (which comes down to potential data loss).  Keep frequent backups if you need this.&#xA;&#xA;a href=&#34;https://remark.as/p/swsnr/install-arch-with-secure-boot-tpm2-based-luks-encryption-and-systemd-homed&#34;Discuss.../a ]]&gt;</description>
      <content:encoded><![CDATA[<p><a href="https://swsnr.writeas.com/tag:archlinux" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">archlinux</span></a> <a href="https://swsnr.writeas.com/tag:systemd" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">systemd</span></a> <a href="https://swsnr.writeas.com/tag:secureboot" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">secureboot</span></a> <a href="https://swsnr.writeas.com/tag:dracut" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">dracut</span></a> <a href="https://swsnr.writeas.com/tag:sbctl" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">sbctl</span></a></p>

<p><a href="https://remark.as/p/swsnr/install-arch-with-secure-boot-tpm2-based-luks-encryption-and-systemd-homed" rel="nofollow">Discuss...</a></p>

<p><strong>Update:</strong> I no longer use <code>dracut</code>, and the corresponding part of this blog
post no longer reflects my setup.</p>

<p>This article describes my Arch Linux setup which combines Secure Boot with custom keys, TPM2-based full disk encryption and systemd-homed into a fully encrypted and authenticated, yet convenient Linux system.</p>

<p>This setup draws inspiration from <a href="https://0pointer.net/blog/authenticated-boot-and-disk-encryption-on-linux.html" rel="nofollow">Authenticated Boot and Disk Encryption on Linux</a> and <a href="https://0pointer.net/blog/unlocking-luks2-volumes-with-tpm2-fido2-pkcs11-security-hardware-on-systemd-248.html" rel="nofollow">Unlocking LUKS2 volumes with TPM2, FIDO2, PKCS#11 Security Hardware on systemd 248</a> by Lennart Poettering, and combines my previous posts on these topics.</p>



<h2 id="what-this-setup-does" id="what-this-setup-does">What this setup does</h2>
<ul><li>Authenticate the boot loader, kernel, initramfs, microcode with Secure Boot, using my own custom keys.  Nothing can boot which wasn’t signed by my keys.</li>
<li>Everything is either authenticated with my keys (kernel, initramfs, microcode) or encrypted (system partition).</li>
<li>Encrypt the system partition, and unlock it automatically if the boot process was authenticated, by means of a TPM2 key bound to the secure boot state.</li>
<li>Give every user their own dedicated encrypted home directory, which gets unlocked at login and locked again at logout.</li></ul>

<h2 id="what-it-doesn-t" id="what-it-doesn-t">What it doesn’t</h2>
<ul><li>Show an ugly LUKS password prompt at boot (even with Plymouth it’s not really pretty).</li>
<li>Leave some parts unencrypted and unauthenticated (conventional installations often fail to consider the initramfs).</li>
<li>Ask me twice for my password, once at boot to unlock the disk and then again at login.</li>
<li>Encrypt data of all users with a shared key.</li></ul>

<h2 id="tools-used" id="tools-used">Tools used</h2>
<ul><li><strong>Archlinux</strong></li>
<li><strong>systemd</strong> &gt;= 250</li>
<li><strong>systemd-boot</strong> as bootloader</li>
<li><strong>systemd</strong> in initramfs to automatically discover and mount the root filesystem</li>
<li><strong>dracut</strong> to generate the initramfs and build signed UEFI binaries</li>
<li><strong>sbctl</strong> to create and enroll Secure Boot keys, and sign binaries</li>
<li><strong>systemd-homed</strong> to manage user accounts with per-user encrypted home directories</li>
<li><strong>systemd-cryptenroll</strong> to add TPM2 and recovery keys tokens to a LUKS partition</li></ul>

<h2 id="the-setup" id="the-setup">The setup</h2>

<h3 id="install-the-system" id="install-the-system">Install the system</h3>

<p>We follow the <a href="https://wiki.archlinux.org/title/installation_guide" rel="nofollow">Installation Guide</a> up to and including section <a href="https://wiki.archlinux.org/title/installation_guide#Update_the_system_clock" rel="nofollow">“Update the system clock”</a>. Then we partition the disk (<code>/dev/nvme0n1</code> in our case); we need an EFI system partition of about 500MB and a root partition spanning the rest of the disk. The EFI partition must be unencrypted and have a FAT filesystem; for the root file system we choose btrfs on top of an encrypted partition.</p>

<p>First we partition the disk and reload the partition table; we take care to specify proper partition types (-t option) so that systemd can automatically discover and mount our filesystems without further configuration in <code>/etc/crypttab</code> or <code>/etc/fstab</code> (see <a href="https://systemd.io/DISCOVERABLE_PARTITIONS/" rel="nofollow">Discoverable Partitions Specification (DPS)</a>):</p>

<pre><code class="language-console">$ target_device=/dev/nvme0n1
$ sgdisk -Z &#34;$target_device&#34;
$ sgdisk -n1:0:+550M -t1:ef00 -c1:EFISYSTEM -N2 -t2:8304 -c2:linux &#34;$target_device&#34;
$ sleep 3
$ partprobe -s &#34;$target_device&#34;
$ sleep 3
</code></pre>

<p>Then we setup the encrypted partition for the root file system. We get asked for an encryption password where we pick a very simple encryption password (even “password” is good enough for now, really) to save some typing during installation, as we’ll later replace the password with TPM2 key and a random recovery key:</p>

<pre><code class="language-console">$ cryptsetup luksFormat --type luks2 /dev/disk/by-partlabel/linux
$ cryptsetup luksOpen /dev/disk/by-partlabel/linux root
$ root_device=/dev/mapper/root
</code></pre>

<p>Now we create the filesystems:</p>

<pre><code class="language-console">$ mkfs.fat -F32 -n EFISYSTEM /dev/disk/by-partlabel/EFISYSTEM
$ mkfs.btrfs -f -L linux &#34;$root_device&#34;
</code></pre>

<p>Now we can mount the filesystems and create some basic btrfs subvolumes:</p>

<pre><code class="language-console">$ mount &#34;$root_device&#34; /mnt
$ mkdir /mnt/efi
$ mount /dev/disk/by-partlabel/EFISYSTEM /mnt/efi
$ for subvol in var var/log var/cache var/tmp srv home; do btrfs subvolume create &#34;/mnt/$subvol&#34;; done
</code></pre>

<p>Now we’re ready to bootstrap Arch Linux: We generate a mirrorlist and install essential packages:</p>

<pre><code class="language-console">$ reflector --save /etc/pacman.d/mirrorlist --protocol https --latest 5 --sort age
$ pacstrap /mnt base linux linux-firmware intel-ucode btrfs-progs dracut neovim
</code></pre>

<p>This takes a while to download and installation all packages; afterwards we configure some essential settings. Choose locale settings and the <code>$new_hostname</code> according to your personal preferences.</p>

<pre><code class="language-console">$ ln -sf /usr/share/zoneinfo/Europe/Berlin /mnt/etc/localtime
$ sed -i -e &#39;/^#en_GB.UTF-8/s/^#//&#39; /mnt/etc/locale.gen
$ echo &#39;LANG=en_GB.UTF-8&#39; &gt;/mnt/etc/locale.conf
$ echo &#39;KEYMAP=us&#39; &gt;/mnt/etc/vconsole.conf
$ echo &#34;$new_hostname&#34; &gt;/mnt/etc/hostname
</code></pre>

<p>Now we enter the new system and finish configuration by generating locales, enabling a few essential services and setting a root password:</p>

<pre><code class="language-console">$ arch-chroot /mnt
$ locale-gen
$ systemctl enable systemd-homed
$ systemctl enable systemd-timesyncd
$ passwd root
</code></pre>

<p>Still in chroot we now build unified EFI kernel images (including initrd and kernel) for booting and install the systemd-boot boot loader:</p>

<pre><code class="language-console">$ pacman -S --noconfirm --asdeps binutils elfutils
$ dracut -f --uefi --regenerate-all
$ bootctl install
</code></pre>

<p>We do <em>not</em> need to create <code>/etc/fstab</code> or <code>/etc/crypttab</code>; as we assigned the appropriate types to each partition and installed systemd-boot a systemd-based initramfs can automatically determine the disk the system was booted from, and discover all relevant partitions.  It can then use superblock information to automatically open encrypted LUKS devices and mount file systems.</p>

<p>At this point we also need to take care to install everything we need for network configuration after reboot.  For desktop systems I prefer network manager because it integrates well into Gnome:</p>

<pre><code class="language-console">$ pacman -S networkmanager
</code></pre>

<p>We have finished the basic setup from the live disk now; let’s leave chroot and reboot:</p>

<pre><code class="language-console">$ exit
$ reboot
</code></pre>

<p>After reboot we can complete the system installation, by adding a desktop environment, applications, command line tools, etc.</p>

<p>I like to automate this, and have two bash scripts in my <a href="https://github.com/swsnr/dotfiles" rel="nofollow">dotfiles</a>, one for boostrapping a new system from a live disk (<a href="https://github.com/swsnr/dotfiles/blob/6a25c4e0620068ecc6360fcbe1587eb14b622ac2/arch/bootstrap-from-iso.bash" rel="nofollow"><code>arch/bootstrap-from-iso.bash</code></a>) and another one for installing everything after the initial bootstrapping (<a href="https://github.com/swsnr/dotfiles/blob/6a25c4e0620068ecc6360fcbe1587eb14b622ac2/arch/install.bash" rel="nofollow"><code>arch/install.bash</code></a>).</p>

<h3 id="create-homed-user" id="create-homed-user">Create homed user</h3>

<p>With the installation finished we create our user account with <code>homectl</code>; let’s name it <code>foo</code> for the purpose of this article. First we should disable copy on write for <code>/home</code>, because this file system feature doesn’t work well with large files frequently updated in place, such as disk images of virtual machines or loopback files as created by systemd-homed:</p>

<pre><code class="language-console">$ chattr +C /home/
</code></pre>

<p>We now create the <code>foo</code> user with an encrypted home directory backed by LUKS and btrfs:</p>

<pre><code class="language-console">$ homectl create foo --storage luks --fs-type btrfs
</code></pre>

<p>By default systemd assigns 85% of the available disk space to the user account, and will balance available space among all user accounts (based on a weight we can configure with <code>—rebalance-weight</code>). On a single user system we may prefer to set an explicit quota for the user account:</p>

<pre><code class="language-console">$ homectl resize foo 50G
</code></pre>

<p>We can also add some additional metadata to the user account:</p>

<pre><code class="language-console">homectl update foo --real-name &#39;Foo&#39; --email-address foo@example.org --language en_GB.UTF-8 --member-of wheel
</code></pre>

<p><code>man homectl</code> provides a complete list of flags; in particular it also offers support for various kinds of security tokens (e.g. FIDO2) for user authentication, provides plenty of means for resource accounting (e.g. memory consumption) for the user account, and supports different kinds of password policies.</p>

<p>Finally we may run into systemd issues with home areas on btrfs (see below); if login fails with a “Operation on home failed: Not enough disk space for home” message we need to enable LUKS discard:</p>

<pre><code class="language-console">homectl update foo --luks-discard=true
</code></pre>

<p>This flag is not safe (heed the warning in <code>man homectl</code>), but until systemd improves its behaviour on btrfs we have no choice unfortunately.</p>

<h3 id="setup-secure-boot" id="setup-secure-boot">Setup secure boot</h3>

<p>First let’s check the secure boot state. We must be in Setup Mode in order to enroll our own keys:</p>

<pre><code class="language-console">$ sbctl status
Installed:	✓ sbctl is installed
Owner GUID:	REDACTED
Setup Mode:	✗ Enabled
Secure Boot:	✗ Disabled
</code></pre>

<p>To enable secure boot we need some keys which we generate with <code>sbctl</code>.  For historical reasons sbctl creates these keys in <code>/usr/share/secureboot</code> but plans exists to change this to a more appropriate place (see <a href="https://github.com/Foxboron/sbctl/issues/57" rel="nofollow">Github issue 57</a>).</p>

<pre><code class="language-console">$ sbctl create-keys
</code></pre>

<p>Now we tell dracut how to sign the UEFI binaries it builds and rebuild our kernel images to get them signed:</p>

<pre><code class="language-console">$ cat &gt; /etc/dracut.conf.d/50-secure-boot.conf &lt;&lt;EOF
uefi_secureboot_cert=&#34;/usr/share/secureboot/keys/db/db.pem&#34;
uefi_secureboot_key=&#34;/usr/share/secureboot/keys/db/db.key&#34;
EOF
$ dracut -f --uefi --regenerate-all
</code></pre>

<p>Next we need to sign the bootloader.  With <code>-s</code> we ask <code>sbctl</code> to remember this file in its database which later lets us check signatures with <code>sbctl verify</code> and automatically update all signatures with <code>sbctl sign-all</code>. The <code>sbctl</code> package includes a pacman hook which automatically updates signatures when an EFI binary on <code>/efi</code> or in <code>/usr/lib</code> changed. Note that we do not sign the boot loader on <code>/efi</code> but instead place a signed copy in <code>/usr/lib</code>.  Starting with systemd 250 <code>bootctl</code> will pick up the signed copy when updating the boot loader.  Hence we reinstall the bootloader afterwards to put the signed copy on <code>/efi</code>.</p>

<pre><code class="language-console">$ sbctl sign -s -o /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed /usr/lib/systemd/boot/efi/systemd-bootx64.efi
$ bootctl install
</code></pre>

<p>We should also do the same for the firmware update to enable seamless firmware updates under secure boot.  Again we use <code>-s</code> to remember this file in the <code>sbtctl</code> database:</p>

<pre><code class="language-console">$ sbctl sign -s -o /usr/lib/fwupd/efi/fwupdx64.efi.signed /usr/lib/fwupd/efi/fwupdx64.efi
</code></pre>

<p>Now let’s verify that we have all signatures in place and enroll keys if everything’s properly signed:</p>

<pre><code class="language-console">$ sbctl verify
Verifying file database and EFI images in /efi...
✓ /usr/lib/fwupd/efi/fwupdx64.efi.signed is signed
✓ /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed is signed
✓ /efi/EFI/BOOT/BOOTX64.EFI is signed
✓ /efi/EFI/Linux/linux-5.15.12-arch1-1-19ea0ebee1ea4de086128ce1a8e2197b-rolling.efi is signed
✓ /efi/EFI/systemd/systemd-bootx64.efi is signed
$ sbctl enroll-keys
</code></pre>

<p>After a reboot we can check the secure boot state again; we’ll see that setup mode is now disabled, secure boot is on, and everything was properly enrolled:</p>

<pre><code class="language-console">$ reboot
$ sbctl status
Installed:	✓ sbctl is installed
Owner GUID:	REDACTED
Setup Mode:	✓ Disabled
Secure Boot:	✓ Enabled
</code></pre>

<h3 id="enroll-tpm2-keys" id="enroll-tpm2-keys">Enroll TPM2 keys</h3>

<p>With the boot process secured we can now configure automatic unlocking of the root filesystem, by binding a LUKS key to the TPM.</p>

<p>We enable the tpm2-tss module in the Dracut configuration, install the dependencies of this dracut module, and regenerate our UEFI kernel images (which will again be signed for secure boot):</p>

<pre><code class="language-console">$ cat &gt; /etc/dracut.conf.d/50-tpm2.conf &lt;&lt;EOF
add_dracutmodules+=&#34; tpm2-tss &#34;
EOF
$ pacman -S tpm2-tools
$ dracut -f --uefi --regenerate-all
</code></pre>

<p>Now we can enroll a TPM2 token (bound to the secure boot measurement in PCR 7) and a recovery key to our root filesystem. This prompts for an existing passphrase each time.  Store the recovery key at a safe place <em>outside</em> of this disk, to have it at hand if TPM2 unlocking ever breaks.</p>

<pre><code class="language-console">$ systemd-cryptenroll /dev/gpt-auto-root-luks --recovery-key
$ systemd-cryptenroll /dev/gpt-auto-root-luks --tpm2-device=auto
</code></pre>

<p>Now reboot and enjoy: The boot process goes straight all the way to the login manager and never shows a LUKS password prompt.  The root filesystem is still reasonably secure: The TPM2 key becomes invalid if the secure boot state changes (e.g. new keys are enrolled, or secure boot is disabled), and cannot be recovered if the disk is removed from the system. Consequently only a kernel signed and authenticated with your own secure boot keys can unlock the root disk automatically.</p>

<p>Finally we can wipe the password slots if you like (<strong>make sure to have a recovery key at this point</strong>):</p>

<pre><code class="language-console">$ systemd-cryptenroll /dev/gpt-auto-root-luks --wipe-slot=password
</code></pre>

<p>If you cannot use secure boot for some reason you can alternatively bind the TPM2 token to a combination of firmware state and configuration and the exact boot chain (up to and including the specific kernel that was started), by specifing the PCR registers 0-5:</p>

<pre><code class="language-console">$ systemd-cryptenroll /dev/gpt-auto-root-luks --tpm2-device=auto --tpm2-pcrs 0+1+2+3+4+5
</code></pre>

<p>This only permits the current kernel and its specific boot chain (e.g bootloader used) to unlock the root filesystem automatically.  However this means that we need to reboot and then wipe and re-enroll the TPM2 token after every rebuild of the kernel image… which happens quite often in fact: Dracut updates or configuration changes, kernel updates, systemd updates (due to the EFI shim provided by systemd), bootloader updates, bootloader configuration changes, etc.</p>

<p>Hence I generally recommend to use secure boot if possible in any way.</p>

<h2 id="issues-with-this-setup" id="issues-with-this-setup">Issues with this setup</h2>

<p>While I am happy with this setup it still has a few drawbacks and issues.</p>

<h3 id="double-encryption" id="double-encryption">Double encryption</h3>

<p>In this setup home directories get encrypted twice, once by homed and then again by the underlying LUKS device.  This wastes a bunch of CPU cycles and likely impacts performance a lot, though I haven’t measured the impact and it’s not so bad as to be noticeable in my day-to-day work.</p>

<p>We could optimize this by putting <code>/home/</code> on a separate partition backed by dm-integrity to authenticate the filesystem (omitting dm-integrity and using a plain file system leaves an attack vector, because linux cannot securely mount untrusted file systems).  This setup requires at least systemd 250 or newer, because earlier versions do not support dm-integrity well.  With systemd 250 we can setup a HMAC-based integrity device, put the HMAC key on the rootfs (e.g. <code>/etc/keys/home.key</code>) and register the home partition in <code>/etc/integritytab</code> with that key, and then mount it via <code>/etc/fstab</code>.</p>

<p>However, this has a few issues on its own, because dm-integrity has a few design issues and is and nowhere near LUKS/dm-crypt:</p>
<ul><li>There’s no key management like LUKS for dm-crypt, meaning we can’t use passphrases or TPM2 keys for dm-integrity devices; instead we need a key file somewhere on disk.</li>
<li>Unlike LUKS/dm-crypt devices dm-integrity devices aren’t self-describing, because the superblock for dm-integrity doesn’t even contain the algorithm used (see &lt;<a href="https://github.com/systemd/systemd/pull/20902" rel="nofollow">https://github.com/systemd/systemd/pull/20902</a>). We cannot mount a dm-integrity device without some extra configuration, and worse, getting the configuration wrong can silently corrupt the device.</li>
<li>For these reasons, <a href="https://systemd.io/DISCOVERABLE_PARTITIONS/" rel="nofollow">DPS</a> cannot and does not support dm-integrity partitions, so we need to configure the whole home partition mount, from dm-integrity up to <code>/etc/fstab</code>.</li></ul>

<h2 id="tooling-issues" id="tooling-issues">Tooling issues</h2>

<p>There are also multiple issues with current tooling that require some more or less safe workarounds:</p>
<ul><li>At the time of writing systemd-home has issues with resizing LUKS home areas on btrfs filesystems, apparently due to <code>fallocate()</code> idiosyncrasies in btrfs. This issue prevents users from logging in, see systemd issues <a href="https://github.com/systemd/systemd/issues/19398" rel="nofollow">19398</a> and <a href="https://github.com/systemd/systemd/issues/20960" rel="nofollow">20960</a>, an <a href="https://bbs.archlinux.org/viewtopic.php?id=258382" rel="nofollow">Arch forums post</a>, and a <a href="https://lists.freedesktop.org/archives/systemd-devel/2020-August/045092.html" rel="nofollow">mail on the systemd-devel list</a>. A workaround is to enable online discard for the user, but this flag is unsafe because it allows overcommitting disk space, which results in IO errors that the kernel and application are not well prepared to handle (which comes down to potential data loss).  Keep frequent backups if you need this.</li></ul>

<p><a href="https://remark.as/p/swsnr/install-arch-with-secure-boot-tpm2-based-luks-encryption-and-systemd-homed" rel="nofollow">Discuss...</a></p>
]]></content:encoded>
      <guid>https://swsnr.writeas.com/install-arch-with-secure-boot-tpm2-based-luks-encryption-and-systemd-homed</guid>
      <pubDate>Wed, 05 Jan 2022 23:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Unlock LUKS rootfs with TPM2 key</title>
      <link>https://swsnr.writeas.com/unlock-luks-rootfs-with-tpm2-key?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[#dracut #luks #sbctl #archlinux #systemd #secureboot&#xA;&#xA;a href=&#34;https://remark.as/p/swsnr/unlock-luks-rootfs-with-tpm2-key&#34;Discuss.../a &#xA;&#xA;Historically cryptsetup and LUKS only supported good old passwords; however recent systemd versions extend cryptsetup with additional key types such as FIDO tokens and TPM devices.&#xA;&#xA;I like the idea of encrypting the rootfs with a TPM2 key; it allows booting without ugly LUKS password prompts but still it keeps data encrypted at rest, and when combined with secure boot also still protects the running system against unauthorized access.&#xA;&#xA;Secure boot will prevent others from placing custom kernels on the unencrypted EFI system partition and booting these, or changing the kernel cmdline, in order to obtain root access to the unlocked rootfs.  LUKS encryption with a TPM-based key bound to secure boot state protects the data if someone removes the hard disk and attempts to access it offline, or tries to disable secure boot in order to boot a custom kernel.&#xA;&#xA;I’ve covered secure boot setup in a past article; this article talks about the TPM2-based encryption.&#xA;&#xA;!--more--&#xA;&#xA;Enroll TPM key&#xA;&#xA;Check that the system supports TPM2:&#xA;&#xA;$ systemd-cryptenroll --tpm2-device=list&#xA;PATH        DEVICE      DRIVER &#xA;/dev/tpmrm0 MSFT0101:00 tpmcrb&#xA;&#xA;Then enroll a new TPM2 key (use the appropriate block device path of course):&#xA;&#xA;$ systemd-cryptenroll --tpm2-device=auto /dev/disk/by-partlabel/linux &#xA;New TPM2 token enrolled as key slot 1.&#xA;&#xA;Then add recovery key:&#xA;&#xA;$ systemd-cryptenroll --recovery-key  /dev/disk/by-partlabel/linux&#xA;🔐 Please enter current passphrase for disk /dev/disk/by-partlabel/linux: &#xA;A secret recovery key has been generated for this volume:&#xA;&#xA;    🔐 efcfbdlt-rhkdjjul-inbhbvhi-nfkvbbbv-didjbjel-butkrrig-ugbrivdd-evnkkkgn&#xA;&#xA;Please save this secret recovery key at a secure location. It may be used to&#xA;regain access to the volume if the other configured access credentials have&#xA;been lost or forgotten. The recovery key may be entered in place of a password&#xA;whenever authentication is requested.&#xA;New recovery key enrolled as key slot 2.&#xA;&#xA;As suggested save this key in a secure location outside of the system. If TPM2 unlocking fails systemd will prompt for a password where you can enter this key.  This lets us access the data even if the TPM2 key became invalid (e.g. when the secure boot configuration changes).&#xA;&#xA;Configure dracut&#xA;&#xA;Force dracut to include the TPM2 software stack, by adding /etc/dracut.conf.d/tpm.conf:&#xA;&#xA;adddracutmodules+=&#34; tpm2-tss &#34;&#xA;And add files dracut currently fails to add, see&#xA;https://github.com/dracutdevs/dracut/issues/1676&#xA;install_items+=&#34; /usr/lib/cryptsetup/libcryptsetup-token-systemd-tpm2.so &#34;&#xA;&#xA;The last line adds necessary cryptsetup plugins which dracut doesn’t yet add (see https://github.com/dracutdevs/dracut/issues/1676).&#xA;&#xA;Make sure to use dracut newer than 055-106-g813577e2; dracut 55 has a typo in the tpm2-tss module dependencies which breaks the module (see https://github.com/dracutdevs/dracut/pull/1526), and another issue with systemd-sysusers which interferes with TPM2 support in early boot (see https://github.com/dracutdevs/dracut/pull/1658).  As of Dec 2021 you’ll need to install dracut-git from AUR.&#xA;&#xA;Reboot and cleanup&#xA;&#xA;Reboot to verify that the system now boots without a LUKS prompt.  Afterwards remove the password key from the rootfs:&#xA;&#xA;$ systemd-cryptenroll --wipe-slot=password /dev/disk/by-partlabel/linux&#xA;&#xA;Now the system only unlocks with the TPM2 key or the recovery key.&#xA;&#xA;Tighten security&#xA;&#xA;Check that&#xA;&#xA;secure boot is enabled (bootctl status or sbctl status),&#xA;secure boot uses custom keys,&#xA;all kernels are signed (sbctl verify; also check the firmware updater and other relevant EFI binaries), and&#xA;no unsigned initramfs or microcode image is used (at best use bundled UEFI executables).&#xA;&#xA;For users consider to use systemd-homed which offers per-user encrypted home “areas”, backed by LUKS encrypted loopback files.&#xA;&#xA;a href=&#34;https://remark.as/p/swsnr/unlock-luks-rootfs-with-tpm2-key&#34;Discuss.../a ]]&gt;</description>
      <content:encoded><![CDATA[<p><a href="https://swsnr.writeas.com/tag:dracut" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">dracut</span></a> <a href="https://swsnr.writeas.com/tag:luks" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">luks</span></a> <a href="https://swsnr.writeas.com/tag:sbctl" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">sbctl</span></a> <a href="https://swsnr.writeas.com/tag:archlinux" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">archlinux</span></a> <a href="https://swsnr.writeas.com/tag:systemd" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">systemd</span></a> <a href="https://swsnr.writeas.com/tag:secureboot" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">secureboot</span></a></p>

<p><a href="https://remark.as/p/swsnr/unlock-luks-rootfs-with-tpm2-key" rel="nofollow">Discuss...</a></p>

<p>Historically cryptsetup and LUKS only supported good old passwords; however recent systemd versions extend cryptsetup with <a href="https://0pointer.net/blog/unlocking-luks2-volumes-with-tpm2-fido2-pkcs11-security-hardware-on-systemd-248.html" rel="nofollow">additional key types</a> such as FIDO tokens and TPM devices.</p>

<p>I like the idea of encrypting the rootfs with a TPM2 key; it allows booting without ugly LUKS password prompts but still it keeps data encrypted at rest, and when combined with secure boot also still protects the running system against unauthorized access.</p>

<p>Secure boot will prevent others from placing custom kernels on the unencrypted EFI system partition and booting these, or changing the kernel cmdline, in order to obtain root access to the unlocked rootfs.  LUKS encryption with a TPM-based key bound to secure boot state protects the data if someone removes the hard disk and attempts to access it offline, or tries to disable secure boot in order to boot a custom kernel.</p>

<p>I’ve covered <a href="2021-04-01-secure-boot-on-arch-linux-with-sbctl-and-dracut.md" rel="nofollow">secure boot setup in a past article</a>; this article talks about the TPM2-based encryption.</p>



<h2 id="enroll-tpm-key" id="enroll-tpm-key">Enroll TPM key</h2>

<p>Check that the system supports TPM2:</p>

<pre><code class="language-console">$ systemd-cryptenroll --tpm2-device=list
PATH        DEVICE      DRIVER 
/dev/tpmrm0 MSFT0101:00 tpm_crb
</code></pre>

<p>Then enroll a new TPM2 key (use the appropriate block device path of course):</p>

<pre><code class="language-console">$ systemd-cryptenroll --tpm2-device=auto /dev/disk/by-partlabel/linux 
New TPM2 token enrolled as key slot 1.
</code></pre>

<p>Then add recovery key:</p>

<pre><code class="language-console">$ systemd-cryptenroll --recovery-key  /dev/disk/by-partlabel/linux
🔐 Please enter current passphrase for disk /dev/disk/by-partlabel/linux: 
A secret recovery key has been generated for this volume:

    🔐 efcfbdlt-rhkdjjul-inbhbvhi-nfkvbbbv-didjbjel-butkrrig-ugbrivdd-evnkkkgn

Please save this secret recovery key at a secure location. It may be used to
regain access to the volume if the other configured access credentials have
been lost or forgotten. The recovery key may be entered in place of a password
whenever authentication is requested.
New recovery key enrolled as key slot 2.
</code></pre>

<p>As suggested save this key in a secure location outside of the system. If TPM2 unlocking fails systemd will prompt for a password where you can enter this key.  This lets us access the data even if the TPM2 key became invalid (e.g. when the secure boot configuration changes).</p>

<h2 id="configure-dracut" id="configure-dracut">Configure dracut</h2>

<p>Force dracut to include the TPM2 software stack, by adding /etc/dracut.conf.d/tpm.conf:</p>

<pre><code class="language-console">add_dracutmodules+=&#34; tpm2-tss &#34;
# And add files dracut currently fails to add, see
# https://github.com/dracutdevs/dracut/issues/1676
install_items+=&#34; /usr/lib/cryptsetup/libcryptsetup-token-systemd-tpm2.so &#34;
</code></pre>

<p>The last line adds necessary cryptsetup plugins which dracut doesn’t yet add (see <a href="https://github.com/dracutdevs/dracut/issues/1676" rel="nofollow">https://github.com/dracutdevs/dracut/issues/1676</a>).</p>

<p>Make sure to use dracut newer than 055-106-g813577e2; dracut 55 has a typo in the tpm2-tss module dependencies which breaks the module (see <a href="https://github.com/dracutdevs/dracut/pull/1526" rel="nofollow">https://github.com/dracutdevs/dracut/pull/1526</a>), and another issue with systemd-sysusers which interferes with TPM2 support in early boot (see <a href="https://github.com/dracutdevs/dracut/pull/1658" rel="nofollow">https://github.com/dracutdevs/dracut/pull/1658</a>).  As of Dec 2021 you’ll need to install <a href="https://aur.archlinux.org/packages/dracut-git" rel="nofollow">dracut-git from AUR</a>.</p>

<h3 id="reboot-and-cleanup" id="reboot-and-cleanup">Reboot and cleanup</h3>

<p>Reboot to verify that the system now boots without a LUKS prompt.  Afterwards remove the password key from the rootfs:</p>

<pre><code class="language-console">$ systemd-cryptenroll --wipe-slot=password /dev/disk/by-partlabel/linux
</code></pre>

<p>Now the system only unlocks with the TPM2 key or the recovery key.</p>

<h3 id="tighten-security" id="tighten-security">Tighten security</h3>

<p>Check that</p>
<ul><li>secure boot is enabled (<code>bootctl status</code> or <code>sbctl status</code>),</li>
<li>secure boot uses custom keys,</li>
<li>all kernels are signed (<code>sbctl verify</code>; also check the firmware updater and other relevant EFI binaries), and</li>
<li>no unsigned initramfs or microcode image is used (at best use bundled UEFI executables).</li></ul>

<p>For users consider to use systemd-homed which offers per-user encrypted home “areas”, backed by LUKS encrypted loopback files.</p>

<p><a href="https://remark.as/p/swsnr/unlock-luks-rootfs-with-tpm2-key" rel="nofollow">Discuss...</a></p>
]]></content:encoded>
      <guid>https://swsnr.writeas.com/unlock-luks-rootfs-with-tpm2-key</guid>
      <pubDate>Sun, 26 Dec 2021 23:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Discoverable GPT partitions</title>
      <link>https://swsnr.writeas.com/discoverable-gpt-partitions?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[#archlinux #systemd&#xA;&#xA;LWN recently covered a comprehensive guide about discoverable GPT disk images by Lennart Poettering.&#xA;&#xA;!--more--&#xA;&#xA;I like this feature a lot; in my experience it makes standard setups much simpler and less error prone.&#xA;&#xA;The article illustrates that almost all systemd commands also work on discoverable disk images, which perhaps makes Archlinux installations simpler as well: One can prepare a generic Arch disk image offline, then write it to the block device, run systemd-firstboot on it for the necessary customisation, and finally a custom installation script via systemd-nspawn.&#xA;&#xA;I&#39;ll have to try this next time I install Arch.&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p><a href="https://swsnr.writeas.com/tag:archlinux" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">archlinux</span></a> <a href="https://swsnr.writeas.com/tag:systemd" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">systemd</span></a></p>

<p>LWN <a href="https://lwn.net/Articles/859240/" rel="nofollow">recently covered</a> a comprehensive guide about <a href="https://0pointer.net/blog/the-wondrous-world-of-discoverable-gpt-disk-images.html" rel="nofollow">discoverable GPT disk images</a> by Lennart Poettering.</p>



<p>I like this feature a lot; in my experience it makes standard setups much simpler and less error prone.</p>

<p>The article illustrates that almost all systemd commands also work on discoverable disk images, which perhaps makes Archlinux installations simpler as well: One can prepare a generic Arch disk image offline, then write it to the block device, run <code>systemd-firstboot</code> on it for the necessary customisation, and finally a custom installation script via <code>systemd-nspawn</code>.</p>

<p>I&#39;ll have to try this next time I install Arch.</p>
]]></content:encoded>
      <guid>https://swsnr.writeas.com/discoverable-gpt-partitions</guid>
      <pubDate>Mon, 26 Jul 2021 22:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Arch Linux with LUKS and (almost) no configuration</title>
      <link>https://swsnr.writeas.com/arch-linux-with-luks-and-almost-no-configuration?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[#systemd #luks #dracut #archlinux&#xA;&#xA;a href=&#34;https://remark.as/p/swsnr/arch-linux-with-luks-and-almost-no-configuration&#34;Discuss.../a &#xA;&#xA;Installing Arch on a LUKS-encrypted dsik traditionally required a few careful configuration steps to configure the proper root device for booting; if any of these steps was omitted or done wrongly the system would fail to boot. With systemd and dracut however a LUKS-encrypted Arch system can boot safely and reliably without any configuration:&#xA;&#xA;Dracut builds a unified EFI kernel image including microcode and a generic initrd with systemd and cryptsetup.&#xA;systemd-boot automatically discovers unified kernel images installed by dracut and automatically adds them to the boot menu without explicit boot loader configuration.&#xA;At boot systemd automatically discovers and mounts the root file system following its DISCOVERABLE PARTITIONS specification.&#xA;&#xA;The following commands demonstrate a fresh Arch installation from the Arch installation media into a libvirt VM. Installing to a pristine physical machine or a different virtual machine provider should require only minimal changes; adapting an existing system may be more difficult and require more work.&#xA;&#xA;!--more--&#xA;&#xA;Prepare the disk&#xA;&#xA;$ sgdisk &#xA;    -n1:0:+500M  -t1:ef00 -c1:EFISYSTEM &#xA;    -n2:0:+1000M -t2:ea00 -c2:XBOOTLDR &#xA;    -N3          -t3:8304 -c3:linux &#xA;    /dev/vda&#xA;$ mkfs.fat -F32 -n EFISYSTEM /dev/disk/by-partlabel/EFISYSTEM&#xA;$ mkfs.fat -F32 -n XBOOTLDR /dev/disk/by-partlabel/XBOOTLDR&#xA;$ cryptsetup luksFormat /dev/disk/by-partlabel/linux&#xA;$ cryptsetup luksOpen /dev/disk/by-partlabel/linux root&#xA;$ mkfs.btrfs -L linux /dev/mapper/root&#xA;&#xA;This creates a 500M EFI system partition for the boot loader and the kernel, a 1000M extended boot loader partition for systemd-boot (entirely optional, but helpful for rescue systems or Windows dual-boot), and fills the rest of the partition with a LUKS parition holding a btrfs filesystem. Each partition gets the proper type code (-t) corresponding to the discoverable partition GUID (e.g. 8304 refers to the “Linux x86-64 root (/)” partition); this enables systemd to automatically mount the partition. For convenience each partition also gets a GPT partition label (-c) which we can use to refer to the partition by name under /dev/disk/by-partlabel instead of remembering the numeric order of partitions as in /dev/vda1.&#xA;&#xA;Install and configure the base system&#xA;&#xA;We now install a base Arch system on top of the new file system:&#xA;&#xA;$ mount /dev/mapper/root/ /mnt&#xA;$ mkdir /mnt/{boot,efi}&#xA;$ btrfs subvolume create /mnt/var&#xA;$ btrfs subvolume create /mnt/home&#xA;$ mount /dev/disk/by-partlabel/EFISYSTEM /mnt/efi&#xA;$ mount /dev/disk/by-partlabel/XBOOTLDR /mnt/boot&#xA;$ reflector --save /etc/pacman.d/mirrorlist --protocol https --latest 5 --sort age&#xA;$ pacstrap /mnt base linux linux-lts linux-firmware intel-ucode btrfs-progs dracut neovim&#xA;$ arch-chroot /mnt&#xA;$ ln -sf /usr/share/zoneinfo/UTC /etc/localtime&#xA;$ nvim /etc/locale.gen /etc/locale.conf /etc/vconsole.conf /etc/hostname /etc/hosts&#xA;$ locale-gen&#xA;$ passwd&#xA;&#xA;Note that we explicitly do not create /etc/fstab.&#xA;&#xA;Generate unified kernel image&#xA;&#xA;While still in chroot we install the optional dependencies dracut requires to build unified kernel images and then run dracut for all kernels we installed above.&#xA;&#xA;$ pacman -S --asdeps binutils elfutils&#xA;$ for kver in /lib/modules/; do dracut -f --uefi --kver &#34;${kver##/}&#34;; done&#xA;&#xA;Install the boot loader&#xA;&#xA;Next we install the systemd-boot boot loader, again still from chroot; we need no further configuration as we mount the EFI and boot loader paritions at their standard paths /efi and /boot respectively.&#xA;&#xA;$ bootctl install&#xA;&#xA;Continue installation&#xA;&#xA;At this point we can install additional packages and enable services; for the purpose of this demonstration we’ll add a simple network configuration:&#xA;&#xA;$ cat   /etc/systemd/network/20-wired.network &lt;&lt;EOF&#xA;[Match]&#xA;Name=enp1s0&#xA;&#xA;[Network]&#xA;DHCP=yes&#xA;EOF&#xA;$ umount /etc/resolve.conf&#xA;$ ln -sf /run/systemd/resolve/stub-resolve.conf /etc/resolve.conf&#xA;$ systemctl enable systemd-network.service&#xA;$ systemctl enable systemd-timesyncd.service&#xA;$ systemctl enable systemd-resolved.service&#xA;&#xA;At the time of writing arch-chroot bind-mounts the live disk resolve.conf into the chroot; we need to unmount it explicitly before we can setup the systemd stub resolver for the new installation.&#xA;&#xA;For a real server or desktop installation we would likely install more packages and services and setup user accounts at this point to boot into a fully working system. I usually run my arch/install.bash script when installing a desktop system (for servers I tend to use other distributions, or one of the Arch Linux cloud images)&#xA;&#xA;Reboot into the new system&#xA;&#xA;$ exit&#xA;$ poweroff&#xA;&#xA;Now we can remove the installation media and start the system again; by holding the space key during boot we make the boot menu appear to verify that the generated unified kernel images are indeed recognized by systemd-boot:&#xA;&#xA;Boot menu with UKIs&#xA;&#xA;systemd-boot seems to pick the image with the highest version number automatically. Upon boot the image automatically discovers the LUKS root partition and offers to unlock it:&#xA;&#xA;Auto-discovered LUKS partition&#xA;&#xA;All this happens automatically; we did not have to configure /etc/fstab and /etc/crypttab.initramfs to specify the root filesystem, nor /etc/mkinitcpio.conf to include the right systemd and cryptsetup hooks.&#xA;&#xA;Configuring for more convenience&#xA;&#xA;At this point the system boots perfectly fine without any configuration, but nonetheless there are a few relevant configuration switches.&#xA;&#xA;Generate kernel images upon installation&#xA;&#xA;Currently the dract package includes no libalpm hooks to build new EFISTUB binaries on kernel updates. The Arch wiki documents the hooks necessary to make this happen; I use dracut-hook-uefi-systemd from AUR to automate this.&#xA;&#xA;Optimize the initrd&#xA;&#xA;By default dracut builds a generic initrd which works on any hardware and system; this mode is intended for distribution vendors which ship a prebuilt initrd as a package. Arch however builds the initrd on the system after installation; this allows us to enable host-only mode to reduce the size of the image and embed host-specific kernel flags. Dracuts reads configuration files from /etc/dracut.conf.d, e.g. /etc/dracut.conf.d/50-host-only.conf:&#xA;&#xA;Hide all systemd messages at startup&#xA;kernelcmdline=&#34;quiet&#34;&#xA;Use hostonly to exclude unnecessary modules, but do not include the hostonly&#xA;cmdline in the image, because at the time of writing it has a few issues with&#xA;discoverable partitions.&#xA;# See https://github.com/dracutdevs/dracut/issues/723#issuecomment-792248568&#xA;hostonly=&#34;yes&#34;&#xA;hostonlycmdline=&#34;no&#34;&#xA;&#xA;Configure the boot menu&#xA;&#xA;systemd-boot enables the kernel command line editor by default, to aid with fixing unbootable systems. With physical access to the machine we can gain root access by booting into /bin/sh with proper kernel parameters. In our system the impact of this security hole is limited since the attacker cannot unlock the encrypted root disk to do anything with the system, but nonetheless it’s recommended to disable the editor in /efi/loader/loader.conf. At this place we can also change the boot menu timeout, and set the default kernel.&#xA;&#xA;Disable the editor to improve security a bit.&#xA;editor no&#xA;Directly boot the default kernel; to make the boot menu appear&#xA;press any key during the firmware splash screen.&#xA;timeout 0&#xA;Boot the LTS kernel by default.&#xA;default linux--lts-&#xA;&#xA;The default stanza supports glob patterns; systemd boot then picks the matching image with the highest version. The pattern in the above example matches the linux LTS kernel.&#xA;&#xA;Conclusion&#xA;&#xA;This setup now boots seamlessly into the getty prompt:&#xA;&#xA;Auto-discovered boot&#xA;&#xA;a href=&#34;https://remark.as/p/swsnr/arch-linux-with-luks-and-almost-no-configuration&#34;Discuss.../a ]]&gt;</description>
      <content:encoded><![CDATA[<p><a href="https://swsnr.writeas.com/tag:systemd" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">systemd</span></a> <a href="https://swsnr.writeas.com/tag:luks" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">luks</span></a> <a href="https://swsnr.writeas.com/tag:dracut" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">dracut</span></a> <a href="https://swsnr.writeas.com/tag:archlinux" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">archlinux</span></a></p>

<p><a href="https://remark.as/p/swsnr/arch-linux-with-luks-and-almost-no-configuration" rel="nofollow">Discuss...</a></p>

<p>Installing Arch on a LUKS-encrypted dsik traditionally required a few careful configuration steps to configure the proper root device for booting; if any of these steps was omitted or done wrongly the system would fail to boot. With systemd and dracut however a LUKS-encrypted Arch system can boot safely and reliably without any configuration:</p>
<ul><li>Dracut builds a unified EFI kernel image including microcode and a generic initrd with systemd and cryptsetup.</li>
<li>systemd-boot automatically discovers unified kernel images installed by dracut and automatically adds them to the boot menu without explicit boot loader configuration.</li>
<li>At boot systemd automatically discovers and mounts the root file system following its <a href="https://systemd.io/DISCOVERABLE_PARTITIONS/" rel="nofollow">DISCOVERABLE PARTITIONS</a> specification.</li></ul>

<p>The following commands demonstrate a fresh Arch installation from the Arch installation media into a libvirt VM. Installing to a pristine physical machine or a different virtual machine provider should require only minimal changes; adapting an existing system may be more difficult and require more work.</p>



<h2 id="prepare-the-disk" id="prepare-the-disk">Prepare the disk</h2>

<pre><code class="language-console">$ sgdisk 
    -n1:0:+500M  -t1:ef00 -c1:EFISYSTEM 
    -n2:0:+1000M -t2:ea00 -c2:XBOOTLDR 
    -N3          -t3:8304 -c3:linux 
    /dev/vda
$ mkfs.fat -F32 -n EFISYSTEM /dev/disk/by-partlabel/EFISYSTEM
$ mkfs.fat -F32 -n XBOOTLDR /dev/disk/by-partlabel/XBOOTLDR
$ cryptsetup luksFormat /dev/disk/by-partlabel/linux
$ cryptsetup luksOpen /dev/disk/by-partlabel/linux root
$ mkfs.btrfs -L linux /dev/mapper/root
</code></pre>

<p>This creates a 500M EFI system partition for the boot loader and the kernel, a 1000M extended boot loader partition for systemd-boot (entirely optional, but helpful for rescue systems or Windows dual-boot), and fills the rest of the partition with a LUKS parition holding a btrfs filesystem. Each partition gets the proper type code (<code>-t</code>) corresponding to the <a href="https://systemd.io/DISCOVERABLE_PARTITIONS/" rel="nofollow">discoverable partition GUID</a> (e.g. <code>8304</code> refers to the “Linux x86-64 root (/)” partition); this enables systemd to automatically mount the partition. For convenience each partition also gets a GPT partition label (<code>-c</code>) which we can use to refer to the partition by name under <code>/dev/disk/by-partlabel</code> instead of remembering the numeric order of partitions as in <code>/dev/vda1</code>.</p>

<h2 id="install-and-configure-the-base-system" id="install-and-configure-the-base-system">Install and configure the base system</h2>

<p>We now install a base Arch system on top of the new file system:</p>

<pre><code class="language-console">$ mount /dev/mapper/root/ /mnt
$ mkdir /mnt/{boot,efi}
$ btrfs subvolume create /mnt/var
$ btrfs subvolume create /mnt/home
$ mount /dev/disk/by-partlabel/EFISYSTEM /mnt/efi
$ mount /dev/disk/by-partlabel/XBOOTLDR /mnt/boot
$ reflector --save /etc/pacman.d/mirrorlist --protocol https --latest 5 --sort age
$ pacstrap /mnt base linux linux-lts linux-firmware intel-ucode btrfs-progs dracut neovim
$ arch-chroot /mnt
$ ln -sf /usr/share/zoneinfo/UTC /etc/localtime
$ nvim /etc/locale.gen /etc/locale.conf /etc/vconsole.conf /etc/hostname /etc/hosts
$ locale-gen
$ passwd
</code></pre>

<p>Note that we explicitly do <em>not</em> create <code>/etc/fstab</code>.</p>

<h2 id="generate-unified-kernel-image" id="generate-unified-kernel-image">Generate unified kernel image</h2>

<p>While still in <code>chroot</code> we install the optional dependencies <code>dracut</code> requires to build unified kernel images and then run dracut for all kernels we installed above.</p>

<pre><code class="language-console">$ pacman -S --asdeps binutils elfutils
$ for kver in /lib/modules/*; do dracut -f --uefi --kver &#34;${kver##*/}&#34;; done
</code></pre>

<h2 id="install-the-boot-loader" id="install-the-boot-loader">Install the boot loader</h2>

<p>Next we install the <code>systemd-boot</code> boot loader, again still from <code>chroot</code>; we need no further configuration as we mount the EFI and boot loader paritions at their standard paths <code>/efi</code> and <code>/boot</code> respectively.</p>

<pre><code class="language-console">$ bootctl install
</code></pre>

<h2 id="continue-installation" id="continue-installation">Continue installation</h2>

<p>At this point we can install additional packages and enable services; for the purpose of this demonstration we’ll add a simple network configuration:</p>

<pre><code class="language-console">$ cat &gt; /etc/systemd/network/20-wired.network &lt;&lt;EOF
[Match]
Name=enp1s0

[Network]
DHCP=yes
EOF
$ umount /etc/resolve.conf
$ ln -sf /run/systemd/resolve/stub-resolve.conf /etc/resolve.conf
$ systemctl enable systemd-network.service
$ systemctl enable systemd-timesyncd.service
$ systemctl enable systemd-resolved.service
</code></pre>

<p>At the time of writing <code>arch-chroot</code> bind-mounts the live disk <code>resolve.conf</code> into the chroot; we need to unmount it explicitly before we can setup the systemd stub resolver for the new installation.</p>

<p>For a real server or desktop installation we would likely install more packages and services and setup user accounts at this point to boot into a fully working system. I usually run my <a href="https://github.com/lunaryorn/dotfiles/blob/f40ea05cd64dc90ba5ed1824eeca2ee4c657f11b/arch/install.bash" rel="nofollow"><code>arch/install.bash</code></a> script when installing a desktop system (for servers I tend to use other distributions, or one of the Arch Linux cloud images)</p>

<h2 id="reboot-into-the-new-system" id="reboot-into-the-new-system">Reboot into the new system</h2>

<pre><code class="language-console">$ exit
$ poweroff
</code></pre>

<p>Now we can remove the installation media and start the system again; by holding the space key during boot we make the boot menu appear to verify that the generated unified kernel images are indeed recognized by systemd-boot:</p>

<p><img src="https://i.snap.as/qvW71UXG.png" alt="Boot menu with UKIs"/></p>

<p>systemd-boot seems to pick the image with the highest version number automatically. Upon boot the image automatically discovers the LUKS root partition and offers to unlock it:</p>

<p><img src="https://i.snap.as/s6S40UCu.png" alt="Auto-discovered LUKS partition"/></p>

<p>All this happens automatically; we did not have to configure <code>/etc/fstab</code> and <code>/etc/crypttab.initramfs</code> to specify the root filesystem, nor <code>/etc/mkinitcpio.conf</code> to include the right systemd and cryptsetup hooks.</p>

<h2 id="configuring-for-more-convenience" id="configuring-for-more-convenience">Configuring for more convenience</h2>

<p>At this point the system boots perfectly fine without any configuration, but nonetheless there are a few relevant configuration switches.</p>

<h3 id="generate-kernel-images-upon-installation" id="generate-kernel-images-upon-installation">Generate kernel images upon installation</h3>

<p>Currently the dract package includes no libalpm hooks to build new EFISTUB binaries on kernel updates. The Arch wiki documents the <a href="https://wiki.archlinux.org/index.php/Dracut#Generate_a_new_initramfs_on_kernel_upgrade" rel="nofollow">hooks necessary to make this happen</a>; I use <code>dracut-hook-uefi-systemd</code> from AUR to automate this.</p>

<h3 id="optimize-the-initrd" id="optimize-the-initrd">Optimize the initrd</h3>

<p>By default dracut builds a generic initrd which works on any hardware and system; this mode is intended for distribution vendors which ship a prebuilt initrd as a package. Arch however builds the initrd on the system after installation; this allows us to enable host-only mode to reduce the size of the image and embed host-specific kernel flags. Dracuts reads configuration files from <code>/etc/dracut.conf.d</code>, e.g. <code>/etc/dracut.conf.d/50-host-only.conf</code>:</p>

<pre><code class="language-ini"># Hide all systemd messages at startup
kernel_cmdline=&#34;quiet&#34;
# Use hostonly to exclude unnecessary modules, but do not include the hostonly
# cmdline in the image, because at the time of writing it has a few issues with
# discoverable partitions.
# See &lt;https://github.com/dracutdevs/dracut/issues/723#issuecomment-792248568&gt;
hostonly=&#34;yes&#34;
hostonly_cmdline=&#34;no&#34;
</code></pre>

<h3 id="configure-the-boot-menu" id="configure-the-boot-menu">Configure the boot menu</h3>

<p>systemd-boot enables the kernel command line editor by default, to aid with fixing unbootable systems. With physical access to the machine we can gain root access by booting into <code>/bin/sh</code> with proper kernel parameters. In our system the impact of this security hole is limited since the attacker cannot unlock the encrypted root disk to do anything with the system, but nonetheless it’s recommended to disable the editor in <code>/efi/loader/loader.conf</code>. At this place we can also change the boot menu timeout, and set the default kernel.</p>

<pre><code class="language-ini"># Disable the editor to improve security a bit.
editor no
# Directly boot the default kernel; to make the boot menu appear
# press any key during the firmware splash screen.
timeout 0
# Boot the LTS kernel by default.
default linux-*-lts-*
</code></pre>

<p>The <code>default</code> stanza supports glob patterns; systemd boot then picks the matching image with the highest version. The pattern in the above example matches the linux LTS kernel.</p>

<h2 id="conclusion" id="conclusion">Conclusion</h2>

<p>This setup now boots seamlessly into the getty prompt:</p>

<p><img src="https://i.snap.as/DTUQ4QGe.webp" alt="Auto-discovered boot"/></p>

<p><a href="https://remark.as/p/swsnr/arch-linux-with-luks-and-almost-no-configuration" rel="nofollow">Discuss...</a></p>
]]></content:encoded>
      <guid>https://swsnr.writeas.com/arch-linux-with-luks-and-almost-no-configuration</guid>
      <pubDate>Fri, 26 Mar 2021 23:00:00 +0000</pubDate>
    </item>
    <item>
      <title>systemd-homed</title>
      <link>https://swsnr.writeas.com/systemd-homed?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[#archlinux #systemd #homed&#xA;&#xA;Observations from using systemd-homed for a couple of days:&#xA;&#xA;!--more--&#xA;&#xA;Overall systemd-homed works quite well; I like that my system now boots direct to GDM, no ugly LUKS password prompt anymore, and I like that every user now has an independent encryption password.&#xA;It doesn’t work well with btrfs though: It keeps complaining about having no space left on the device.&#xA;The Newbie Corner of the Arch Linux forums is not so newbie: I found the cause of this issue in a thread there.&#xA;Even in Arch Linux it can take a long time for simple bugs to get fixed, see FS#67685.&#xA;There are still some rough corners: For instance snapperd crashes when it tries to use user data of a homed user, see https://github.com/openSUSE/snapper/issues/589.&#xA;  Incidentially even well-intentioned ideas such as clearing a password from memory are hard to get right in C.&#xA;&#xA;All in all I’m quite happy and I really like the idea of homed; I think I’m going to stick with it. I think this and many other ideas from the systemd project are really steps in the right direction.]]&gt;</description>
      <content:encoded><![CDATA[<p><a href="https://swsnr.writeas.com/tag:archlinux" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">archlinux</span></a> <a href="https://swsnr.writeas.com/tag:systemd" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">systemd</span></a> <a href="https://swsnr.writeas.com/tag:homed" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">homed</span></a></p>

<p>Observations from using systemd-homed for a couple of days:</p>


<ul><li>Overall systemd-homed works quite well; I like that my system now boots direct to GDM, no ugly LUKS password prompt anymore, and I like that every user now has an independent encryption password.</li>
<li>It doesn’t work well with btrfs though: It keeps complaining about having no space left on the device.</li>
<li>The Newbie Corner of the Arch Linux forums is not so newbie: I found the cause of this issue in <a href="https://bbs.archlinux.org/viewtopic.php?pid=1922435#p1922435" rel="nofollow">a thread</a> there.</li>
<li>Even in Arch Linux it can take a long time for simple bugs to get fixed, see <a href="https://bugs.archlinux.org/task/67658" rel="nofollow">FS#67685</a>.</li>
<li>There are still some rough corners: For instance snapperd crashes when it tries to use user data of a homed user, see <a href="https://github.com/openSUSE/snapper/issues/589" rel="nofollow">https://github.com/openSUSE/snapper/issues/589</a>.
<ul><li>Incidentially even well-intentioned ideas such as clearing a password from memory are hard to get right in C.</li></ul></li></ul>

<p>All in all I’m quite happy and I really like the idea of homed; I think I’m going to stick with it. I think this and many other ideas from the systemd project are really steps in the right direction.</p>
]]></content:encoded>
      <guid>https://swsnr.writeas.com/systemd-homed</guid>
      <pubDate>Wed, 09 Dec 2020 23:00:00 +0000</pubDate>
    </item>
  </channel>
</rss>