FW12 Battery Improvement - suspend-then-hibernate

I used a variety of forums to try to create a working suspend-then-hibernate system that worked for me. I’ve had AI create a summary of what I did, this has worked on my 12 and 16 and helped my battery life.

THIS IS AI GENERATED VERIFY BEFORE USE. I am not a programmer by trade, just wanted better battery for my laptop :)**

Which Linux distro are you using?** Fedora

Which release version? Fedora 44

Which kernel are you using? 7.0.12-201.fc44.x86_64

Which BIOS version are you using? 03.07

Which Framework Laptop 12 model are you using? 13th Gen Intel® Core™

**
Suspend-then-Hibernate on Framework Laptop 12 (Fedora + LUKS + btrfs)**

This guide walks through setting up suspend-then-hibernate on a Framework Laptop 12 running Fedora with LUKS encryption and btrfs. When you close the lid, the laptop suspends instantly (fast wake). After a set delay, it automatically hibernates to save battery — less than 1% drain over days.

What this solves: Fedora’s default sleep (s2idle) drains 1–2W, which can kill your battery overnight. Hibernate writes RAM to disk and powers off completely, using zero battery.

Tested on: Framework Laptop 12, Fedora 44 (kernel 7.0.12), 16GB RAM, LUKS-encrypted btrfs


Prerequisites

  • Framework Laptop 12 running Fedora (should also work on Framework 13/16)
  • UEFI boot mode (standard on Framework laptops)
  • Enough free disk space for a swap file equal to your RAM size

Step 1 — Disable Secure Boot

Secure boot enables kernel lockdown, which blocks hibernate from writing the RAM image to disk. This must be disabled.

  1. Power off your laptop
  2. Press F2 during boot to enter BIOS/UEFI setup (not F12 — that’s the boot order menu)
  3. Navigate to Security → Secure Boot and set it to Disabled
  4. Save and exit (usually F10)

After booting back into Fedora, verify it took:

mokutil --sb-state

You should see SecureBoot disabled. If it still says enabled, go back into the BIOS and make sure you saved the change.

Security note: Secure boot protects against bootkit attacks (someone physically installing a malicious bootloader). Your LUKS encryption is the stronger protection — without your passphrase, nobody can read your data regardless of secure boot. For a personal laptop, disabling it is a reasonable tradeoff.


Step 2 — Create a Swap File

Hibernate dumps your entire RAM contents to disk, so you need a swap file at least as large as your RAM. Fedora’s default “swap” is zram (compressed RAM), which disappears when powered off and is useless for hibernate.

Create a dedicated btrfs subvolume for the swap file. A separate subvolume prevents the swap file from interfering with btrfs snapshots or copy-on-write:

sudo btrfs subvolume create /var/swap

Disable copy-on-write on the subvolume. btrfs requires this for swap files:

sudo chattr +C /var/swap

Create a 16GB swap file (adjust to match your RAM size):

sudo btrfs filesystem mkswapfile --size 16G --uuid clear /var/swap/swapfile

Add the swap file to fstab so it’s enabled on every boot:

echo '/var/swap/swapfile none swap defaults 0 0' | sudo tee --append /etc/fstab

Activate the swap file now without rebooting:

sudo swapon /var/swap/swapfile

Verify both zram and the new swap file are active:

sudo swapon --show

You should see both /dev/zram0 and /var/swap/swapfile listed.


Step 3 — Add the Resume Module to dracut

The initramfs needs the resume module so it can find and restore from the swap file during boot:

echo 'add_dracutmodules+=" resume "' | sudo tee /etc/dracut.conf.d/resume.conf

Rebuild the initramfs:

sudo dracut --force

Step 4 — Fix SELinux Policy

Without this, SELinux blocks systemd from accessing the swap file during hibernate:

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

Step 5 — Add Kernel Resume Parameters to GRUB

The kernel needs to know where the hibernate image lives. Get your root filesystem UUID:

sudo findmnt -no UUID /

Get the physical offset of the swap file on disk:

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

Note both values. Now add them to the GRUB config. Replace the UUID and offset below with your actual values:

sudo sed -i 's|rhgb quiet|rhgb quiet resume=UUID=YOUR-UUID-HERE resume_offset=YOUR-OFFSET-HERE|' /etc/default/grub

Rebuild GRUB:

sudo grub2-mkconfig -o /boot/grub2/grub.cfg

Verify the parameters were added:

grep resume /etc/default/grub

You should see resume=UUID=... and resume_offset=... in the GRUB_CMDLINE_LINUX line.


Step 6 — Configure sleep.conf

This tells systemd to allow hibernate and suspend-then-hibernate, and sets how long to stay in regular suspend before transitioning to hibernate:

sudo bash -c 'cat > /etc/systemd/sleep.conf << EOF
[Sleep]
AllowSuspend=yes
AllowHibernation=yes
AllowSuspendThenHibernate=yes
HibernateDelaySec=30min
EOF'

Adjust HibernateDelaySec to your preference. 30 minutes is a good balance — short enough to save battery if you walk away, long enough that you get instant wake most of the time.


Step 7 — Configure Lid Close Behavior

By default, closing the lid triggers regular suspend. Change it to suspend-then-hibernate:

sudo bash -c 'cat > /etc/systemd/logind.conf << EOF
[Login]
HandleLidSwitch=suspend-then-hibernate
HandleLidSwitchExternalPower=suspend-then-hibernate
EOF'

Apply the changes:

sudo systemctl restart systemd-logind

Step 8 — Reboot and Test

Reboot to pick up the kernel resume parameters:

sudo reboot

After logging in, first test basic hibernate. Leave some windows open:

sudo systemctl hibernate

The machine should power off completely. Press the power button — it will ask for your LUKS passphrase, then restore everything as you left it within 5–10 seconds.

If hibernate works, test suspend-then-hibernate by closing the lid and waiting past your HibernateDelaySec delay. When you open the lid, if it asks for your LUKS passphrase, hibernate kicked in and everything is working.


Troubleshooting

“Sleep verb ‘hibernate’ is not configured or configuration is not supported by kernel”

Run sudo dmesg | grep -i -E "hibernate|lockdown|secure". If you see “kernel is locked down” or “hibernation is restricted”, secure boot is still enabled. Reboot into BIOS (F2) and verify it’s actually disabled. Confirm with mokutil --sb-state.

Hibernate works but suspend-then-hibernate doesn’t trigger

Check that both config files are correct:

cat /etc/systemd/sleep.conf
cat /etc/systemd/logind.conf

Make sure there’s no extra text or command artifacts in the files — they should contain only the config sections.

busctl says “na” for CanHibernate

This means systemd thinks hibernate isn’t available. Check that the swap file is active (swapon --show), the kernel has the resume parameters (cat /proc/cmdline), and SELinux isn’t blocking it (sudo audit2allow -b).

Wake from hibernate is slow

Speed depends on how much RAM is in use (the kernel only writes used pages) and your NVMe speed. With 16GB RAM and a modern NVMe, expect 5–10 seconds after entering your LUKS passphrase.


References

2 Likes