This is a somehow personal step-by-step documentation, how I achieved hibernation and suspend-then-hibernate on a recent Fedora system with enabled secure boot. Basically you patch the kernel to allow hibernation with enabled secure boot and then configure hibernation. This can only be done securely, because we use a swap file stored on an encrypted disk. I used following documentation snippets on the internet:
- Enable decryption of luks devices with TPM2: Decrypt LUKS volumes with a TPM on Fedora 35+ Ā· GitHub
- Kernel patch to enable hibernate with secure-boot: Enable hibernate during lockdown Ā· GitHub
- How-to compile a fedora kernel: Building a Custom Kernel :: Fedora Docs
- Enable hibernation on Fedora: Hibernation in Fedora Workstation - Fedora Magazine
- Automatically hibernate after extended sleep: Automatically Hibernate After Extended Sleep | mitchellroe.dev
- Needed customizations for suspend-then-hibernate for this setup (swap file on luks encrypted hard disk): Fedora 35 hibernation with swap file, only for hibernation and resume Ā· GitHub
- My āminimizedā kernel configuration to save compilation time: momou! Paste
1. Enable automatic decryption of luks over tpm
I have a standard Fedora installation with full disk encryption. To enable automatic decryption over tpm2, you add necessary files to dracut and add the decryption key to the tpm module. You basically follow these instructions.
# Add decryption key to tpm.
systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+2+4+7 /dev/nvme0n1p3
# Wipe old keys and enroll new key. You have to execute this command again after a kernel upgrade.
systemd-cryptenroll /dev/nvme0n1p3 --wipe-slot=tpm2 --tpm2-device=auto --tpm2-pcrs=0,2,4,7
# Add tpm2 configuration option to /etc/crypttab
luks-$UUID UUID=disk-$UUID none tpm2-device=auto,discard
# Update initramfs (to get necessary tpm2 libraries and parameters for decryption into initramfs)
dracut -f
2. Patch and compile custom kernel
You follow basically this how-to. For a simplification I just wrote down the commands and variables I used for the most recent kernel on a Fedora 37 system.
### Set variables
export arch=x86_64
export ver=6.0
export minrel=15
export pkgrel=300
export subver=$minrel-$pkgrel
export fedver=fc37
export name=$(hostname)
### Custom Machine owner key for secure boot
# Allow kernel signing
sudo /usr/libexec/pesign/pesign-authorize
# Create key
openssl req -new -x509 -newkey rsa:2048 -keyout "key.pem" -outform DER -out "cert.der" -nodes -days 36500 -subj "$name"
# Import key to UEFI database.
mokutil --import "cert.der"
# You have to reboot the system after importing the key with "mokutil" to import the key via UEFI system
# After rebooting create PKCS #12 key file and import it into the nss database
openssl pkcs12 -export -out key.p12 -inkey key.pem -in cert.der
certutil -A -i cert.der -n "$name" -d /etc/pki/pesign/ -t "Pu,Pu,Pu"
pk12util -i key.p12 -d /etc/pki/pesign
### Setup build system
rpmdev-setuptree
koji download-build --arch=src kernel-$ver.$subver.$fedver
rpm -Uvh kernel-$ver.$subver.$fedver.src.rpm
cd ~/rpmbuild/SPECS
### Apply patches and customize kernel configuration
# Get patch to enable hibernate in lockdown mode (secure boot)
wget https://gist.githubusercontent.com/kelvie/917d456cb572325aae8e3bd94a9c1350/raw/74516829883c7ee7b2216938550d55ebcb7be609/0001-Add-a-lockdown_hibernate-parameter.patch -O ~/rpmbuild/SOURCES/0001-Add-a-lockdown_hibernate-parameter.patch
# Define patch in kernel.spec for building the rpms
# Patch2: 0001-Add-a-lockdown_hibernate-parameter.patch
sed -i '/^Patch999999/i Patch2: 0001-Add-a-lockdown_hibernate-parameter.patch' kernel.spec
# Add patch as ApplyOptionalPatch
sed -i '/^ApplyOptionalPatch linux-kernel-test.patch/i ApplyOptionalPatch 0001-Add-a-lockdown_hibernate-parameter.patch' kernel.spec
# Add custom kernel name
sed -i "s/# define buildid .local/%define buildid .$name/g" kernel.spec
# Add machine owner key
sed -i "s/.$name/.$name\n%define pe_signing_cert $name/g" kernel.spec
# Install necessary dependencies for compiling hte kernel
rpmbuild -bp kernel.spec
### Optional steps
# Create own configuration file from fedora config file
# You find my "minimized" configuration for a 6.0.11 kernel here.
cp ~/rpmbuild/SOURCES/kernel-$arch-fedora.config ~/rpmbuild/BUILD/kernel-$ver.$minrel/linux-$ver.$subver.$name.$fedver.$arch/.config
cd ~/rpmbuild/BUILD/kernel-$ver.$minrel/linux-$ver.$subver.$name.$fedver.$arch/
make menuconfig
# Copy custom menuconfig kernel configuration to kernel-local
cp ~/rpmbuild/BUILD/kernel-$ver.$minrel/linux-$ver.$subver.$name.$fedver.$arch/.config ~/rpmbuild/SOURCES/kernel-local
# ... or copy kernel config from running kernel to kernel-local
#cp /boot/config-$(uname -r) ~/rpmbuild/SOURCES/kernel-local
# Remove build infos from custom config
sed -i '0,/^#\ General\ setup$/d' ~/rpmbuild/SOURCES/kernel-local
sed -i '1i # x86_64' ~/rpmbuild/SOURCES/kernel-local
### End optional steps ###
# Compile kernel
cd ~/rpmbuild/SPECS
time rpmbuild -bb --with baseonly --without debuginfo --target=$arch kernel.spec | tee ~/build-kernel.log
# Install kernel
cd ~/rpmbuild/RPMS/$arch/
sudo dnf install *.rpm
After installing the new kernel and before rebooting, you have to add a kernel parameter to allow hibernation in kernel lockdown mode (actually allow hibernation with secure boot).
grubby --args="lockdown_hibernate=1" --update-kernel=ALL
Now reboot your system.
3. Enable hibernation
Follow this excellent article on fedoramagazine.org to enable hibernation: Hibernation in Fedora Workstation - Fedora Magazine. With this, you create a swap file on the encrypted hard disk which will be started and removed upon hibernation or waking up.
4. Preparation for suspend-then-hibernate
The suspend-then-hibernate doesnāt work out of the box with this setup (swap file for hibernation on luks encrypted hard disk). The system needs to prepare and remove the swap file before and after executing suspend-then-hibernate, check out this excellent gist: Fedora 35 hibernation with swap file, only for hibernation and resume Ā· GitHub
5. Enable suspend-the-hibernate
Normally, when you close the lid, the system will go to sleep (a.k.a. āsuspendā). You can configure your system that it will hibernate automatically after an extended sleep. Check this excellent guide here.
Final words
All in all it is quite complicated to get a āsecureā system with enabled secure boot and smoothly working hibernation, but in my case, it saves a lot of battery ā¦ As a plus you may enable encrypted RAM in the bios settings.