After a lot of trial and error, lots of guides and documentation, I finally managed to get hibernation working on Framework with i7-1280p (12th gen) running Pop!_OS 22.04 LTS.
Main guide was made by Dylan Awalt-Conley and can be found here.
I felt a more detailed explanation of the steps was needed, as well as modifications I did in order to get it working.
This setup was made on a Pop!_OS 22.04 LTS installation without an encrypted disk.
I selected my own partition layout and defined a swap partition as big as my RAM. Various guides mention that hibernation either always writes 100% of RAM (so every time you hibernate, you write 16 GB or how much you have to SSD) or it compresses the RAM so only the actual RAM used is sent to storage (so if you get 25% usage from 16 GB of RAM when you hibernate you will write ~4 GB to SSD).
After you get the hang of the steps, I’m pretty sure you can adapt the guide to work on a fully encrypted disk.
Step 1 - Set some environment variables:
SWAP_DEVICE=$(sudo cryptsetup status cryptswap | grep 'device:' | awk '{print $2}')
This represents the partition that currently holds the swap.
CRYPT_DEVICE=/dev/mapper/cryptswap
This is the default on Pop!_OS. The current mapping used by crypttab.
SWAP_KEY=/.swap-key
This is the location of your swap encryption key. This will be used to decrypt the swap partition instead of a random key assigned each boot (which is the main culprit that breaks hibernation on Pop!_OS). I used /.swap-key
instead of /root/.swap-key
as the latter didn’t make crypttab unlock my LUKS partition and swap was not working on boot.
Step 2 - Turn off swap
sudo swapoff $SWAP_DEVICE
Step 3 - Lock the LUKS partition that holds the swap
sudo cryptsetup luksClose $CRYPT_DEVICE
Step 4 - Comment out the old swap mapping from crypttab
Basically crypttab holds mapping information for encrypted partitions and how to handle them. By default, Pop!_OS makes the swap partition encrypted with a key that is randomly generated at every boot. This breaks hibernation. We want to re-create this swap partition with a key that doesn’t change.
sudo sed -i 's!^cryptswap!# &!' /etc/crypttab
Step 5 - Create encryption key file
sudo dd if=/dev/urandom of=$SWAP_KEY bs=1024 count=4
Step 6 - Format the old swap partition and map it to the encryption key
sudo cryptsetup luksFormat -d $SWAP_KEY $SWAP_DEVICE
Step 7 - Open the new partition and mount it
sudo cryptsetup open -d $SWAP_KEY $SWAP_DEVICE cryptswap
Step 8 - Format the partition for swap
sudo mkswap $CRYPT_DEVICE
By this point, if you open Disks you should have a LUKS partition available and a swap partition underneath:
Now comes the complex stuff. Take note of the files we edit and remember them in case the system won’t boot anymore. You can make backups of them or comment out the old entries.
Step 9 - Set some new environment variables
Here I find the names confusing, but to keep it the same as the source Gist, I will leave them as is.
SWAP_UUID=$(sudo blkid -s UUID -o value $SWAP_DEVICE)
This holds the UUID of the LUKS partition that contains the swap.
CRYPT_UUID=$(sudo blkid -s UUID -o value $CRYPT_DEVICE)
This holds the UUID of the swap partition inside the luks partition.
ROOT_UUID=$(sudo findmnt -no UUID -T $SWAP_KEY)
This holds the UUID of the partition that holds the encryption key (mounted at /
in our case, mounted at /root
in the original guide)
Step 10 - Add our new cryptswap entry to crypttab
echo "cryptswap UUID=$SWAP_UUID /dev/disk/by-uuid/$ROOT_UUID:$SWAP_KEY luks,discard,keyscript=/lib/cryptsetup/scripts/passdev,noauto" | sudo tee -a /etc/crypttab
Step 11 - Checkpoint - Reboot and test
By this point, what you did was to make a new swap partition that uses a fixed encryption key instead of a random key.
run sudo update-initramfs -u
and check for any errors.
You shouldn’t get any.
Reboot your system and test to see if swap is used or not.
sudo swapon -s
should show output if swap is working.
You can also check Disks to see if the LUKS partition is automatically unlocked and if the swap partition is used by the system.
Step 12 - add RESUME flags to initramfs
echo "resume=UUID=$CRYPT_UUID" | sudo tee -a /etc/initramfs-tools/conf.d/resume
This will tell your system that for every kernel update from now on, also apply the changes in our resume
file. So we don’t have to manually update each systemd entry whenever a change happens.
Step 13 - add RESUME flags to kernelstub
This step is (as far as I know) Pop!_OS specific.
They use a tool called kernelstub
to update the systemd kernel parameters. Makes it easier to maintain extras (like nvme.noacpi=1
for example)
sudo kernelstub -a "resume=UUID=$CRYPT_UUID"
Step 14 - update initramfs again
sudo update-initramfs -u
Reboot, then open some programs and try hibernating with
sudo systemctl hibernate
.
After a few seconds, your laptop should shutdown and when you turn it back on, you should get a grey screen with a message resuming from /dev/disk/by-uuid/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
and everything should be just the way you left it.
References: