Is it possible to hibernate with swap-file?

Hello everyone,

One one of my nixos installation I’m using swapfile and noticed that hibernation never works.
I made sure that resume=/var/swap-file and resume_offset=myoffset are present in my kernel boot args.
I did calculate resume_offset using filefrag -v /var/swapfile | awk '{if($1=="0:"){print $4}}' as per information that i found on arch wiki Power management/Suspend and hibernate - ArchWiki.

I also noticed that in init script following lines:

# Clear the resume device.
if test -n "$resumeDevice"; then
    mkswap "$resumeDevice" || echo 'Failed to clear saved image.'
fi

Does this mean that swap device will be always flushed?

Here is relevant part of my configuration:

  boot.kernelParams = [  "resume=/var/swapfile" "resume_offset=450560" ];
  swapDevices = [ { device = "/var/swapfile"; size = 32768; } ];
  boot.resumeDevice = "/var/swapfile";

I’m currently using nixos-unstable channel with 5.0+ kernel version.

Any information would help me understand what is going on better.

Thank you very much in advance!

4 Likes

Ok, this was a problem on my end.

boot.resumeDevice = "/dev/mapper/myroot";

Is the correct option, no need for resume=/var/swapfile in boot.kernelParams also.
resumeDevice should be pointing at partition that swap file resides on.

More info can be found here:

https://www.kernel.org/doc/Documentation/power/swsusp-and-swap-files.txt

4 Likes

Hi everyone

I got it to work with a complex setup so I thought I would leave this here for the future generations.

My setup is Btrfs + LUKS2 + TPM unlock + swapfile. Long story short, I got to this setup by doing the recommended auto partitioning during the install, then a long time later I changed things up. I used a live USB NixOS, removed my swap partition and filled the space with the root partition in gparted (leaving a few megabytes at the end empty). I followed a guide to convert from ext4 to btrfs and another guide to upgrade to LUKS2 from the default LUKS1 and also switched to a stronger key algo there. The TPM enrolling is pretty simple too.

Btrfs convert guide
Luks upgrade guide
TPM enroll guide

I only have 2 partitions, the boot and the root. During the boot sequence the encrypted root volume gets automatically unlocked using the TPM and mapped to /dev/dm-0. I found this with ll /dev/mapper/luks*

I have an 18G swapfile at /var/swapfile. It’s auto created by my NixOS config.
I used btrfs inspect-internal map-swapfile -r /var/swapfile to get the resume offset for the kernel parameter.

Here’s my config:

  swapDevices = [ { device = "/var/swapfile"; size = 18*1024; } ];
  boot.resumeDevice = "/dev/dm-0";  # the unlocked drive mapping
  boot.kernelParams = [
    "resume_offset=10134041"
  ];

After building and rebooting I can finally hibernate with systemctl hibernate and my PC wakes up from keyboard or mouse input.

I still don’t know how to add a hibernate button to the shutdown menu and disable the wake from mouse/keyboard but it’s good progress for day.
I’m planning to try Suspend then hibernate - #5 by ericgundrum next

2 Likes

Getting the resume_offset on ext4:

sudo filefrag -v /swapfile|awk 'NR==4{gsub(/\./,"");print $4;}'

(from Swap partition or swap file (on a ext4 partition)? - Page 2 - Linux Mint Forums)

I believe that since 24.05, you no longer need to specify resumeDevice or resume_offset if you use boot.initrd.systemd.enable = true, because now systemd will dynamically determine the necessary hibernation details and store it in EFI variables that systemd can use in initrd to resume.

(I also have this really stupid PR to add support for this to the scripted initrd, but don’t expect this to ever be merged)

4 Likes

I can confirm, it’s enough to only set swapDevices

1 Like