Update on hibernation in Fedora Workstation

Photo by Ruiqi Kong on Unsplash (cropped)

Goals and rationale

Hibernation stores the state of the whole operating system — the contents of memory used by the kernel and all programs — on disk. The machine is then completely powered off. Upon next boot, this state is restored and the old kernel and all the programs that were running continue execution.

Hibernation is nowadays used less often, because “suspend” — the state where CPU is powered down, but the contents of memory are preserved, works fine on most laptops and other small devices. But if the suspend is implemented poorly and it drains the battery too quickly, or if the user needs to completely power off the device for some reasons, hibernation can still be useful.

We need a storage area for hibernation. The kernel allows two options:
– either a single large-enough swap device, usually a partition,
– or a single large-enough swap file on some file system.

Fedora Linux installations by default do not use a normal swap device or file. Instead, a zram device is created, which is an in-memory compressed swap area. It is not suitable for hibernation. This means that hibernation does not work out-of-the-box on Fedora Linux. This guide describes how to create a swap file to enable hibernation.

Limitations

This method only works on UEFI!

To check that the system uses UEFI:

bootctl

If this commands prints “Not booted with EFI”, then the method described below won’t work. Refer to the original Hibernation in Fedora Workstation (for Fedora Linux 36) instead.

Create and enable a swap file:

SWAPSIZE=$(free | awk '/Mem/ {x=$2/1024/1024; printf "%.0fG", (x<2 ? 2*x : x<8 ? 1.5*x : x) }')
sudo btrfs subvolume create /var/swap
sudo chattr +C /var/swap
sudo restorecon /var/swap
sudo mkswap --file -L SWAPFILE --size $SWAPSIZE /var/swap/swapfile
sudo bash -c 'echo /var/swap/swapfile none swap defaults 0 0 >>/etc/fstab'
sudo swapon -av
sudo bash -c 'echo add_dracutmodules+=\" resume \" > /etc/dracut.conf.d/resume.conf'
sudo dracut -f

This should print a message that swap was enabled on /var/swap/swapfile. The swap file is added to fstab, so it’ll be permanently active. This is a good thing, it should make the system more reliable in general.

Now we are ready to test hibernation:

systemctl hibernate

After the system has shut down, boot it again and let one of the kernels start. The machine should return to the previous state from before hibernation.

This method does not require further configuration because systemd automatically stores the location of the swap file before entering hibernation in an UEFI variable, and then after the reboot, reads that variable and instruct the kernel to resume from this location. This only works on UEFI systems, but is otherwise quite simple and robust.

Reverting the changes

sudo swapoff -v /var/swap/swapfile
sudo sed -r -i '/.var.swap.swapfile/d' /etc/fstab
sudo btrfs subvolume delete /var/swap
sudo rm /etc/dracut.conf.d/resume.conf

After that, reenable SecureBoot if appropriate.

Troubleshooting

This process mail fail in two ways:

  • either going into hibernation fails, i.e. the kernel does not save the state and the machine does not actually power off,
  • or loading of saved state fails, and we end up with a fresh boot.

In both cases, the first step is to look at journalctl -b, in particular any error lines.

FAQs and Guides For System Administrators

34 Comments

  1. Creating a swapfile on a BTRFS filesystem could increase IO operations a lot due to copy-on-write, couldn’t it?
    Or is COW somehow disabled for swap files?

    • Patrick O'Callaghan

      COW needs to be disabled for swapfiles. Not sure if this happens automatically. However you can certainly have a swapfile and zram, and give the zram higher priority so the swapfile is normally not used except for hibernation.

    • Pramod

      You need to put swapfile on a separate subvolume, [/var/swap could be the subvol, but better to create it outside the @ root subvolume and mount it], and create the swapfile with

      btrfs filesystem mkswapfile -s $SWAPSIZE /var/swap/swapfile

      after

      chattr -R +C /var/swap
  2. Tometzky

    Actually it seems that Fedora 41 after recent updates started to work also when Secure boot is enabled. At least on my new laptop with encrypted swap partition and zram disabled with “touch /etc/systemd/zram-generator.conf”:

    $ cat /proc/meminfo | grep -E ‘^(MemTotal|SwapTotal)’
    MemTotal: 32104280 kB
    SwapTotal: 41943036 kB

    $ cat /etc/fstab | grep swap | cut -d’ ‘ -f 1
    UUID=4ec0c9b4-de29-4828-8287-97252f489ab8

    $ readlink -f /dev/disk/by-uuid/4ec0c9b4-de29-4828-8287-97252f489ab8
    /dev/dm-1

    $ lsblk /dev/dm-1
    NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
    luks-fddfcbb6-24e8-4c20-8745-4e66bd335dda 253:1 0 40G 0 crypt [SWAP]

    $ sudo bootctl 2>/dev/null | grep -i ‘Secure Boot’
    Secure Boot: enabled (user)

    So you don’t need to risk disabling secure boot just to use hibernate. Just using sleep can drain the laptop battery and risk overheating a laptop is some event wakes it while closed or stored in a bag for commuting.

    Especially that some security conscious companies require Secure Boot.

    • Indeed, hibernation works with SecureBoot enabled. It turns out I had some unrelated selinux AVC which prevented from hibernation from being attempted, and didn’t actually verify this. I thought I understand the whole process…

      I asked the FedoraManagazine editors to make edits to drop the chunk about SecureBoot and modify the commands to include ‘chattr +C’.

      • msizanoen

        Hibernation working with secure boot enabled is a security bug and will be fixed eventually: https://bugzilla.redhat.com/show_bug.cgi?id=2333706

        • Ben

          Good point. Though I’d put it as: kernel lockdown precludes hibernation. If kernel lockdown is disabled then hibernation+Secure Boot work fine but is less secure due to the plaintext hibernated image being open to tampering.

          Hibernation currently requires unencrypted/plaintext swap. A system booted with kernel lockdown enabled (usually the default when Secure Boot is on), will refuse to use unencrypted swap, therefore will not be able to hibernate.

          As noted in the other comments, UEFI Secure Boot and Linux’s kernel lockdown are complementary and largely but not totally independent of each other. Per kernel_lockdown(7), “On an EFI-enabled x86 or arm64 machine, lockdown will be automatically enabled if the system boots in EFI Secure Boot mode.” However this isn’t actually happening for at least my system, presumably due to the RH bug referred to by @msizanoen. tbc, my system currently has kernel lockdown disabled (with or without hibernation set up/plaintext swap).

          The real reason why hibernation won’t work when kernel lockdown is enabled is that under lockdown “Unencrypted hibernation/suspend to swap are disallowed” (kernel_lockdown(7)).

          So: kernel lockdown refuses to use unencrypted swap, and hibernate requires unencrypted swap. Choose one.

          FTR: I have hibernation working with Secure Boot enabled, and lockdown is indeed disabled (kernel 6.12.9-200.fc41.x86_64). The ‘Linux swap: Invalid’ reflects the unencrypted swap; when I swapoff the swap file the warning goes away.

          % fwupdmgr security
          Host Security ID: HSI:4! (v1.9.27)

          HSI-1
          ...
          ✔ UEFI secure boot:              Enabled

          ...
          Runtime Suffix -!
          ✔ fwupd plugins:                 Untainted
          ✔ CET OS Support:                Supported
          ✔ Linux swap:                    Encrypted
          ✔ Linux kernel:                  Untainted
          ✘ Linux kernel lockdown:         Disabled
          ✘ Linux swap:                    Invalid
  3. Patrick O'Callaghan

    I used to have to jump through hoops to get hibernation to work on BTRFS, including calculating a physical disk offset and editing it into the boot command line. See for example https://btrfs.readthedocs.io/en/latest/Swapfile.html

    This is a welcome simplification.

    Is it still necessary to mark the swapfile as NODATACOW, or is this now automatic? Also, AFAIK the subvolume containing the swapfile cannot be snapshotted.

  4. darthVoid

    Hello,

    Nice article, however you can’t use a CoW file for swap :

    swapon -av
    swapon: /var/swap/swapfile: found signature [pagesize=4096, signature=swap]
    swapon: /var/swap/swapfile: pagesize=4096, swapsize=33285996544, devsize=33285996544
    swapon /var/swap/swapfile
    swapon: /var/swap/swapfile: swapon failed: Invalid argument

    [46666.195078] BTRFS warning (device nvme0n1p3): swapfile must not be copy-on-write

    Maybe chaning the attirube on the file with

    chattr +C /var/swap/swapfile

    could help…

    • Zbigniew Jędrzejewski-Szmek

      I didn’t see this issue on my system. I’ll need to figure out the details here and possibly update the article.

      • BR Web

        I had the exact same error on a fresh Fedora Workstation 41 installation

    • Easier to set chattr +C on /var/swap before creating /var/swap/swapfile

  5. darthVoid

    One more thing :

    This is wrong :

    btrfs subvolume rm /var/swap

    You have to do :

    btrfs subvolume delete /var/swap

    Delete subvolume 406 (no-commit): '/var/swap'
  6. Arvid

    Pandas do NOT hibernate ^^

  7. Kevin

    Does the zram swap have to be disabled somehow too?

    • Patrick O'Callaghan

      You can create hooks to disable zram when hibernating and turn it back on when waking. e.g.:

      $ cat /etc/systemd/system/hibernate-preparation.service
      [Unit]
      Description=Enable swap file and disable zram before hibernate
      Before=systemd-hibernate.service

      [Service]
      SyslogIdentifier=%N
      User=root
      Type=oneshot

      ExecStartPre=/bin/bash -c ‘ \
      swapon -a; \
      swapoff /dev/zram0; \
      exit 0; \

      ExecStart=/bin/true

      [Install]
      WantedBy=systemd-hibernate.service
      $ cat /etc/systemd/system/hibernate-preparation.service
      [Unit]
      Description=Enable swap file and disable zram before hibernate
      Before=systemd-hibernate.service

      [Service]
      SyslogIdentifier=%N
      User=root
      Type=oneshot

      ExecStartPre=/bin/bash -c ‘ \
      swapon -a; \
      swapoff /dev/zram0; \
      exit 0; \

      ExecStart=/bin/true

      [Install]
      WantedBy=systemd-hibernate.service

      $ cat /etc/systemd/system/hibernate-resume.service
      [Unit]
      Description=Enable zram swap after resuming from hibernation
      After=hibernate.target

      [Service]
      SyslogIdentifier=%N
      User=root
      Type=oneshot
      ExecStart=/bin/bash -c ‘ \
      if ! swapon –show=NAME –noheadings | grep -q /dev/zram0; then \
      swapon /dev/zram0; \
      fi; \
      exit 0; \

      [Install]
      WantedBy=hibernate.target

    • Zbigniew Jędrzejewski-Szmek

      No, zram swap is not a problem in any way. (When looking for a candidate device to use for hibernation, systemd will skip zram and zswap devices. And the in-memory compressed pages are just like any kind of memory. They’ll be written to the swap area and then restored.)

      • Patrick O'Callaghan

        I’m pretty sure that when I tried this (back in the F36 days) it definitely was a problem. I got error messages about zram not being permanent storage, i.e. it was trying to use zram for hibernation even when a disk-based swapfile was enabled. That’s why I added hooks to disable it when hibernating and enable it again when resuming. However it’s possible that this is no longer necessary.

  8. BR Web

    Is there an equivalent guide to enable hibernation in Fedora Silverblue?

  9. BR Web

    I tried with Fedora Workstation and got an error after the last command:

    swapon: /var/swap/swapfile: swapon failed: Invalid argument

  10. BR Web

    Due to the previous error I mentioned, I tried using a SWAP partition instead, the system will hibernate once, then if I try to hibernate again, it will not, it will try but automatically come back on, I don’t think this is related to having used a SWAP partition?

  11. Rich

    Any reason why

    mkswap

    is used instead of

    btrfs filesystem mkswapfile

    ?

  12. hpt

    [ 3641.479274] BTRFS warning (device dm-1): swapfile must be on one device

    I hit this issue. What shall I do, please? Thanks!

  13. Hugh

    It would be great to have a sleep mode that switches to hibernate after a certain amount of time or battery use.

    I often “sleep” a notebook and then leave it for longer than I intended.

  14. BR Web

    I was able to execute all steps successfully using the chattr +C /var/swap as well, then when I tried to execute sudo systemctl hibernate I get the following message:

    “Call to Hibernate failed: Access denied”

    I followed the exact steps plus the suggested update on a fresh Fedora Workstation 41 installation, what am I doing wrong, please help, thank you

    • Sorry BR Web, it seems this procedure was not adequately tested. The author has requested revisions/corrections and I am attempting to make them now.

      Edit: The revisions have been made. Please try again.

      gb

      • BR Web

        Unfortunately the updated version doesn’t work either on my device, it will hibernate once, then it will never hibernate again, also, after resuming from the first hibernation Bluetooth will. be dead, not very reliable with my device

        • Devices not resuming properly after hibernation is a known problem on Linux. I think that is why it is not enabled by default. Things might be improving a little, depending on your hardware, but it is an area that is in-development and about the only way to know if it will work for some particular hardware is to try it and see. Personally, I prefer to shutdown my PC when I’m not using it. IMO, having to periodically save all my work is not at all a bad thing.

  15. Ben

    The info in this article was not quite correct for my “new” Fedora 41 install on a Lenovo ThinkPad T14 Gen 5 (AMD), with Secure Boot enabled. However it pointed me in the right direction.

    Three things need to be done:
    1. create a swap file
    2. update dracut to add resume support (uncertain if this is required but it didn’t hurt)
    3. update SELinux policy to properly tag the swapfile
    – if you don’t do this, you’ll get a “Call to Hibernate failed: Access denied” error when invoking

    sudo systemctl hibernate

    Here’s what I did:

    SWAPSIZE=$(free | awk '/Mem/ {x=$2/1024/1024; printf "%.0fG", (x&lt;2 ? 2*x : x&lt;8 ? 1.5*x : x) }')
    SWAPFILE=/var/swap/swapfile

    sudo btrfs subvolume create /var/swap

    sudo btrfs filesystem mkswapfile --size $SWAPSIZE --uuid clear $SWAPFILE

    echo $SWAPFILE none swap defaults 0 0 | sudo tee --append /etc/fstab
    sudo swapon --all --verbose

    # https://wiki.archlinux.org/title/Dracut#Hibernation
    echo 'add_dracutmodules+=" resume "' | sudo tee /etc/dracut.conf.d/resume.conf
    sudo dracut --force

    sudo semanage fcontext --add --type swapfile_t $SWAPFILE
    sudo restorecon -RF /var/swap

    Unfortunately after all that, the T14’s wifi ath11k_pci driver has a fatal bug that was fixed ca. 2023 but reverted in August 2024 and remains open:
    https://bugzilla.kernel.org/show_bug.cgi?id=214649

  16. This coupled with changing /etc/systemd/logind.conf so that the lid action does suspend-then-hibernate has finally got my linux where I want it. I don’t know why Linux distros have decided they dislike suspend-then-hibernate, but I love it. I’d much rather my machine save to disk and come back to life with more battery than anything else.

  17. Berend

    I tried this on Fedora KDE yesterday and got got access denied as well.
    bootctl gives me ” systemd-boot not installed in ESP.”

    tried a bunch of extra things and got locked out of KDE, so i will wait for a beter solution.
    Would be awsome to get this to work. my laptop drains fast while in suspend mode.

Comments are Closed

The opinions expressed on this website are those of each author, not of the author's employer or of Red Hat. Fedora Magazine aspires to publish all content under a Creative Commons license but may not be able to do so in all cases. You are responsible for ensuring that you have the necessary permission to reuse any work on this site. The Fedora logo is a trademark of Red Hat, Inc. Terms and Conditions