Skip to content

12. Post-Boot Configuration

12.1. systemd Configuration

Some configuration needs to be done after Gentoo's systemd has been started. In the previous chapter, systemd was running, but only the instance belonging to SystemRescue.

Setup localisation (copy&paste one command after the other):

# set your language settings
export my_lang="de_DE.UTF-8"
export my_lc_messages="en_US.UTF-8" # I prefer English messages for easier googling around.

/bin/bash -c '
localectl set-locale LANG="${my_lang}" LC_COLLATE="C.UTF-8" LC_MESSAGES="${my_lc_messages}" && \
localectl status && \
env-update && source /etc/profile && \
echo -e "\e[1;32mSUCCESS\e[0m"

Setup systemd-timesyncd (copy&paste one command after the other):

# set your timezone
export my_timezone="Europe/Berlin"

# list of ntp servers:
# set your (fallback) ntp servers
export my_ntp_servers=""
export my_fallback_ntp_servers=""

/bin/bash -c '
timedatectl set-timezone ${my_timezone} && \
if grep -q -w "hypervisor" <(grep "^flags[[:space:]]*:[[:space:]]*" /proc/cpuinfo); then
    systemctl disable systemd-timesyncd.service && \
    echo -e "\e[1;32mSUCCESS\e[0m"
    rsync -av /etc/systemd/timesyncd.conf /etc/systemd/._cfg0000_timesyncd.conf && \
    sed -i -e "s/#NTP=/NTP=${my_ntp_servers}/" -e "s/#FallbackNTP=.*/FallbackNTP=${my_fallback_ntp_servers}/" /etc/systemd/._cfg0000_timesyncd.conf && \
    timedatectl set-ntp true && \
    echo -e "\e[1;32mSUCCESS\e[0m"
fi && \
timedatectl && \
echo -e "\e[1;32mSUCCESS\e[0m"

Setup nftables with certain firewall rules:

emerge net-firewall/nftables && \
/usr/local/sbin/firewall.nft && \
nft list ruleset > /var/lib/nftables/rules-save && \
systemctl enable nftables-restore && \
echo -e "\e[1;32mSUCCESS\e[0m"

(Optional) Disable saving firewall configuration upon shutdown:

mkdir /etc/systemd/system/nftables-restore.service.d && \
echo -e "[Service]\nExecStop=" > /etc/systemd/system/nftables-restore.service.d/override.conf && \
systemctl daemon-reload && \
echo -e "\e[1;32mSUCCESS\e[0m"

12.2. Measured Boot

Make sure that secure boot is enabled:

 sbctl status
Installed:   sbctl is installed
Owner GUID: 4cdeb60c-d2ce-4ed9-af89-2b659c21f6e4
Setup Mode:  Disabled
Secure Boot:     Enabled
Vendor Keys:    none

(Optional) To list the installed secure boot keys/certs:

emerge app-crypt/efitools && \
efi-readvar && \
echo -e "\e[1;32mSUCCESS\e[0m"

You have two reasonable options for measured boot on systemd:

  • systemd-cryptenroll: I prefer this on local systems (e.g. laptops, desktop PCs) where I have access to TTY and can take care of (optional) pin prompts which are supported with systemd ≥251. With pins, you don't have the problem of your laptop, for example, getting stolen and auto-unlocking upon boot. Furthermore, I experienced faster boot with systemd-cryptenroll than with clevis due to the use of PBKDF2 which is safe to use with the secure keys generated by systemd-cryptenroll. And, you don't have to use the "app-crypt/clevis" package from (unofficial) guru overlay.
  • clevis: I prefer this on remote systems, e.g. a server in colocation, where I can take care of unlock via Shamir Secret Sharing which combines TPM 2.0 and Tang pin (Tang project).

Use either systemd-cryptenroll or clevis in the following.

12.2.1.a) systemd-cryptenroll

TPM 2.0 dictionary lockout

If you typed in the wrong TPM 2.0 pin a certain amount of time, you need to use your fallback password and execute tpm2_dictionarylockout --clear-lockout after bootup to lift the lockout. You can execute the command as non-root, if your non-root user is a member of group "tss".

Install "app-crypt/tpm2-tools":

emerge -av tpm2-tools

Add your non-root user to "tss" group:

gpasswd -a david tss

Add support for TPM 2.0 to dracut and systemd:

rsync -a /etc/portage/package.use/main /etc/portage/package.use/._cfg0000_main && \
sed -i 's/^\(sys-apps\/systemd.*\)$/\1 tpm/' /etc/portage/package.use/._cfg0000_main && \
echo 'add_dracutmodules+=" tpm2-tss "' >> /etc/dracut.conf && \
echo -e "\e[1;32mSUCCESS\e[0m"

Update and make sure "sys-apps/systemd" is listed among the packages:

emerge -atuDN @world

Make sure that TPM 2.0 devices (should only be one) are recognised:

systemd-cryptenroll --tpm2-device=list

Make sure that the PCRs you are going to use have a valid hash and don't consist of zeroes only:

tpm2_pcrread sha256

Create new LUKS keyslots on all swap and system partitions.

# I only use PCR7 as recommended in the first sentence after following table:
# "--tpm2-with-pin=yes" is optional:
systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7 --tpm2-with-pin=yes /dev/sda3
systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7 --tpm2-with-pin=yes /dev/sda4
systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7 --tpm2-with-pin=yes /dev/sdb3
systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7 --tpm2-with-pin=yes /dev/sdb4
# etc.

Reboot your system and use your fallback passphrase for LUKS unlock again this time!

12.2.1.b) clevis

System Requirement: Tang Server

This section requires a tang server to preexist and be reachable from this system. A simple tang server setup is shown by RedHat on YouTube. I personally use AlmaLinux as tang server, but any supported system can do.


The packages app-crypt/clevis, dev-libs/jose and dev-libs/luksmeta originate from project GURU. The packages there may be more up-to-date. Update the overlay in /var/db/repos/duxsco as you see fit. I keep a local copy, because I want to double check packages before I make them available for installation.

No DNS resolution!

As of now (April 1st 2023), DNS resolution is not possible upon boot. Thus, you need to provide a static IP instead of "tang.local" as used in below codeblock.

Further info:

Install "app-crypt/clevis":

echo "app-crypt/clevis ~amd64
dev-libs/jose ~amd64
dev-libs/luksmeta ~amd64
app-crypt/tpm2-tools ~amd64" >> /etc/portage/package.accept_keywords/main && \
emerge -at app-crypt/clevis

Make sure that the PCRs you are going to use have a valid hash and don't consist of zeroes only:

tpm2_pcrread sha256

Bind all swap and system LUKS volumes.

# I only use PCR7 as recommended in the first sentence after following table:
clevis luks bind -d /dev/sda3 sss '{"t": 2, "pins": {"tpm2": {"pcr_bank":"sha256","pcr_ids":"7"}, "tang": {"url": "http://tang.local"}}}'
clevis luks bind -d /dev/sda4 sss '{"t": 2, "pins": {"tpm2": {"pcr_bank":"sha256","pcr_ids":"7"}, "tang": {"url": "http://tang.local"}}}'
clevis luks bind -d /dev/sdb3 sss '{"t": 2, "pins": {"tpm2": {"pcr_bank":"sha256","pcr_ids":"7"}, "tang": {"url": "http://tang.local"}}}'
clevis luks bind -d /dev/sdb4 sss '{"t": 2, "pins": {"tpm2": {"pcr_bank":"sha256","pcr_ids":"7"}, "tang": {"url": "http://tang.local"}}}'
# etc.

Show results:

clevis luks list -d /dev/sda3
clevis luks list -d /dev/sda4
clevis luks list -d /dev/sdb3
clevis luks list -d /dev/sdb4
# etc.

12.2.2. Kernel Rebuild

Rebuild the unified kernel image to integrate the changes for measured boot:

emerge -at --oneshot \
$(qlist -eI sys-kernel/gentoo-kernel-bin >/dev/null && echo sys-kernel/gentoo-kernel-bin) \
$(qlist -eI sys-kernel/gentoo-kernel >/dev/null && echo sys-kernel/gentoo-kernel)


If you decided in favor of systemd-cryptenroll, you can use the TPM 2.0 pin upon boot from this point onwards.

12.3. Package Cleanup

Update packages and remove extraneous ones (copy&paste one command after the other):

emerge -atuDN @world
emerge --depclean -a