[GUIDE] Framework 16 Hibernate (w/ swapfile) Setup on Fedora 40

There isn’t a single place for all the adjustments that are needed to get this to work so I am putting it all here in one place:

1. Create the btrfs subvolume

sudo btrfs subvolume create /var/swap

2. Calculate the needed size of your swapfile

Use swapon to get the size of your current zram swap. The size you need for the swapfile (to be safe) is:

(ram_size - zram_size) + (zram_size * 2)

Or equivalently:

ram_size + zram_size

3. Create the swapfile

sudo btrfs filesystem mkswapfile --size 40g --uuid clear /var/swap/swapfile

I have 32G or RAM and 8G of zram, so I’m creating a 40 G(i)B swapfile in this case.

4. Find the UUID of the swapfile

sudo findmnt -no UUID -T /var/swap/swapfile

Looks something like ffe8a473-6525-4a46-a7e1-e7fea5bdf20e

5. Find the offset on the disk

Btrfs has a native command for this too now, and it doesn’t require any math to convert it.

sudo btrfs inspect-internal map-swapfile -r /var/swap/swapfile

Looks something like 6148378

6. Add the kernel parameters for the swapfile

sudo grubby --args="resume=UUID=ffe8a473-6525-4a46-a7e1-e7fea5bdf20e resume_offset=6148378" --update-kernel=ALL

Replace the ffe8a473-6525-4a46-a7e1-e7fea5bdf20e and 6148378 with the values you found in the prior steps

7. Add the swapfile to your fstab with low priority

Add a line like the following to the end of your /etc/fstab. This sets the priority of the swapfile as low as it can possibly be so it won’t get used unless it has to:

# add swapfile, but set priority as low as possible so it only gets used if zram (pri=100) can't be
/var/swap/swapfile                        none                    swap    defaults,pri=0 0 0

8. Enable swapfile

sudo swapon /var/swap/swapfile

9. Add SELinux labeling

Add the permanent rule for the label, and apply the rule to the files.

sudo semanage fcontext -a -t swapfile_t '/var/swap(/.*)?'
sudo restorecon -RF /var/swap

10. Reboot

You want to have a clean audit.log for the next step, and the best way to do that is to reboot and do absolutely nothing else except the steps that follow.

11. Try to Hibernate (it won’t work)

After you login, try to hibernate from the command-line. It won’t work, but it generates audit events we can use for the next steps.

sudo systemctl hibernate
# it won't work, but that's expected

12. Generate SELinux policy

Check to make sure you don’t have other random things in your policy.

sudo audit2allow -b

You should only get back:

#============= systemd_logind_t ==============
allow systemd_logind_t swapfile_t:dir search;

If you get back anything else, you’ll need to manually edit the generated policy, and recompile it by hand.

Generate the policy from the audit2allow rules, which gives you both a *.te file and a compiled *.pp file. If you need to do manual changes, you’ll use the .te file and overwrite the .pp file from this.

cd /tmp
sudo audit2allow -b -M systemd_hibernate

13. (Optional) Manually edit and re-compile the policy

If you had extraneous results in your audit2allow, those are now in the policy it generated for you. Luckily it provides you the source file (.te) as well as the compiled policy file (.pp), so you can edit and recompile.

Edit the policy file and fix it up. Editing SELinux policy files is beyond the scope of this, but in simple cases might not be too hard. Make sure to remove unnecessary requires as well as the polcies.

sudo nano systemd_hibernate.te

Then re-compile it into a .pp file.

sudo checkmodule -M -m -o systemd_hibernate.mod systemd_hibernate.te
sudo semodule_package -o systemd_hibernate.pp -m systemd_hibernate.mod

14. Load the new SELinux policy

Load the new policy into the permanent database.

sudo semodule -i systemd_hibernate.pp

15. Repeat 10-14 for this SELinux policy:

#============= systemd_sleep_t ==============
allow systemd_sleep_t self:capability sys_admin;

16. Create script to disable/enable wifi with hibernate

Save this script to: /usr/lib/systemd/system-sleep/hibernate-pre-post.sh

#!/bin/bash
WiFiModule=mt7921e

case "$1 $2" in
  "pre hibernate" | "pre suspend-then-hibernate")
    modprobe -r $WiFiModule
    ;;
  "post hibernate" | "post suspend-then-hibernate")
    modprobe $WiFiModule
    ;;
  *)
    :
    ;;
esac

Make sure it is executable -
sudo chmod +x hibernate-pre-post.sh

reference - [Guide] Solution for WiFi problems after hibernate (non-systemd)

17. Try to Hibernate (again)

This time it should actually work. It’s possible you have other problems though. One common case is the screen only going black for a second and then coming back to the login screen, which can be caused by a few different things.

Troubleshooting

Adding an override to the systemd-logind.service so it includes more debug data in the journalctl should almost always be your first step.

  1. Add the override folder and file

The normal systemctl edit method doesn’t seem to work for me for some reason.

sudo mkdir -p /etc/systemd/system/systemd-logind.service.d/
sudo nano /etc/systemd/system/systemd-logind.service.d/override.conf

You can undo this change later by just removing the file and folder that were created, and rebooting.

  1. Populate the override file

Add this to the file and save it:

[Service]
Environment=SYSTEMD_LOG_LEVEL=debug
  1. Reboot your system.

Restarting the service logs you out and causes weird bugs in the service, so just reboot.

  1. View the logs for the service
sudo journalctl -u systemd-logind.service
# scroll to the bottom with 'GG' to see the most recent logs

references: Setup hibernation on Silverblue / Kinoite? - #8 - Fedora Discussion

P.S.
You can use this script to diagnose sleep issues on your device: scripts/amd_s2idle.py · master · drm / amd · GitLab

9 Likes

Awesome guide which can be used for a lot of distros with slight modifications as well. My question would be, can you detail what you are doing with the swap file that is included most of the times by default (usually 1 to 8GB in size. Used to be called swapfile, but is now swap.img)? This is an important step, because if not handled correctly it can be the source of instability.

1 Like

Sure I will read up on this. I didn’t run into this being discussed as I was figuring out how to get this working because Fedora uses zram and doesn’t have disk based swap by default (swap partitions or a swapfile).

I plan to add some more context to some of the steps (like step 15 and 16) later this week. The content is mainly taken from the referenced post in the Fedora forums.

I’m on the Framework 13 since a year and Hibernation is the one feature I’ve been missing the most.
Any clue if this guide could work on an encrypted disk or what possible changes would have to be made?

Yes this should work on a 13. I used it on a 12th gen running Bluefin OS, as well as Ubuntu 24.04. However 24.04 is still very buggy with hibernation after about 4 hibernation and resume cycles. Not sure why either. I don’t believe Fedora is effected in the same way.

It does not work on software encrypted disks w/ secure boot enabled. I am working on gathering the info to do that. It’s one of the things I am planning to do today actually.

Any progress so far?

In order for hibernation to start working for me (Framework 13/Fedora 40/AMD Ryzen) I needed to do extra steps:

  • turn off secure boot
  • create one more config file and execute command:
cat <<EOF >/etc/dracut.conf.d/resume.conf
add_dracutmodules+=" resume "
EOF
dracut -f

and that worked for me, maybe it will help for someone else :slight_smile:

2 Likes

Currently using framework 16 with fedora 40 kde plasma. When trying to hibernate after rebooting and setting up the swap file, I get “Call to Hibernate failed: Invalid argument” and running “sudo audit2allow -b” returns nothing. I have double checked my uuid and offset are correct.

TBH I’ve got the same error message and blank output of audit2allow first and disabled selinux completely :man_facepalming: so I could check if hibernation really works.

So it worked perfectly well and I changed from disabled to permissive in /etc/sysconfig/selinux, rebooted and once again changed mode to enforcing.
I read somewhere in RH documentation so it is advised to toggle to permissive before enforcing so that you don’t have problems booting system up.

After that combination of steps above I tried sudo systemctl hibernate and sudo audit2allow -b and got the output finally. And then retried steps from this guide, but unfortunelly it weirdly kicked me out to the login screen and without hibernation.

After all from gist attached in this post I tried:
cd /tmp
sudo audit2allow -b -M systemd_sleep
sudo semodule -i systemd_sleep.pp
And it worked for me without having to disable selinux

BTW I’m plasma user too :smiley:

1 Like

I also have Framework 13/Fedora 40/AMD Ryzen, with gnome

I followed this guide but had some more/different steps.

First, It seems that with systemd 255, there is no more need to set resume and resume_offset in grub.

So from Tarian’s guide, I follow step 1 to 3 then 7 to 11.

At this step, I had the Call to Hibernate failed: Invalid argument message when trying to hibernate.
In journalctl, I had Failed to find location to hibernate to: Invalid argument message.
This is due to /sys/power/resume file containing 0:0 instead of ID of the partition hosting the swapfile.
Mine is on /dev/nvme0n1p3:

root@arcadia:~# ls -l /dev/nvme0n1p3
brw-rw----. 1 root disk 259, 3 11 août  10:11 /dev/nvme0n1p3

So I need to use 259:3

Next, I follow what @tail_Head said:

  • create /etc/dracut.conf.d/resume.conf but with some modifications to make /sys/power/resume modifications consistent:
cat <<EOF >/etc/dracut.conf.d/resume.conf
add_dracutmodules+=" resume "
install_items+=" /usr/lib/systemd/system/systemd-hibernate-resume.service "
EOF
dracut -f
  • set selinux to permissive to use audit2allow
cd /tmp
sudo audit2allow -b -M systemd_hibernate
sudo semodule -i systemd_hibernate.pp
sudo audit2allow -b -M systemd_sleep
sudo semodule -i systemd_sleep.pp

Then, I finished with step 17 from Tarian’s guide

And for now, all seems to work

1 Like

Sad to say that this works, but it breaks wifi after resuming from hiberation for me.
It just gives a wifi activation error and nothing resolves it other than restarting the computer

This part of the guide should fix your wifi -

:person_facepalming: not sure how I missed that. Thanks, seems to work now :crossed_fingers:

I’ve been able to follow most of the steps here without issue, except that I’m still not able to see any output from audit2allow -b. I updated my /sys/power/resume with the offset value for my /dev/nvme0n1p3 and I added the extra install_items line that underscoreDje mentioned. Finally, I also changed /etc/sysconfig/systemd to SELINUX=permissive and rebooted but still no dice.

The output of journalctl -k contains this message about lockdown:

Lockdown: systemd-logind: hibernation is restricted; see man kernel_lockdown.7

I do have secure boot enabled, but I’d like to keep it that way since this is a work machine. I know that’s a problem for hibernate after reading through the suggested kernel_lockdown.7 man page, but there’s an old comment in the gist linked in the post which says “there’s an effort to produce signed and verifiable hibernation images”. Since that was about Fedora 37, I was hoping there was some improvement on this situation. However, though I haven’t seen anyone outright say it, I am slowly putting it together that I may not be able to use hibernate at all because of secure boot.

Does that seem to be the case and should stop wasting my time on this?

You have this thread which is saying you would need to modify your kernel to support hibernating with secureboot enabled.

I would imagine that still applies, based on your results

Hi there
Thanks for the excellent guide. Newbie here (came from Ubuntu) trying to set it up. I am completely lost on the policy, when i try the audit2allow i get no output and when i try $sudo audit2allow -b -M systemd_hibernate
then i get
compilation failed:
systemd_hibernate.te:6:ERROR ‘syntax error’ at token ‘’ on line 6:

any ideas why?

thanks

Why do you have a $ in front of sudo? Did you manually edit your policy? It seems like you have a typo in your .te file.

thanks for your quick response, sorry the “$” was to show that it was code.
So, let me explain, and sorry for not being very clear. I started by trying to generate the SELinux policy, so i typed

sudo audit2allow -b

the weird thing is the above comes back empty, it returns absolutely nothing.
so i went to /tmp and then i tried

but then what i got was

compilation failed:
systemd_hibernate.te:6:ERROR ‘syntax error’ at token ‘’ on line 6:
/usr/bin/checkmodule: error(s) encountered while parsing configuration

so now i m a bit on lost on how to proceed…

Your systemd_hibernate.te probably doesn’t have anything in it. Did trying to hibernate error out?

yeap, thats correct

sudo audit2allow -b -M systemd_hibernate

produces the systemd_hibernate.te

and then

less systemd_hibernate.te

shows that there is only one line in the file:

module systemd_hibernate 1.0;

when attempting

sudo systemctl hibernate

I get
Call to Hibernate failed: Invalid argument

1 Like