This page documents a complete Arch Linux hibernate setup where the system originally had only zram swap. The workflow creates a persistent disk-backed swapfile, adds the resume target to the UKI kernel command line, adds the mkinitcpio resume hook, rebuilds the boot images, and verifies that the system restores the previous session after hibernate.
Overview
- Hibernate needs disk-backed swap because the RAM image must survive power off.
- zram is useful for runtime swap, but it cannot store a hibernation image because it lives in RAM.
- A swapfile on ext4 is valid for hibernate when the kernel is given the filesystem UUID and resume offset.
- With systemd-boot and UKI, the kernel command line is usually stored in /etc/kernel/cmdline.
- The resume hook must run in initramfs before normal filesystem startup.
- After a successful resume, the hibernation image is invalidated and the swap area is reused normally.
Initial problem
The system had the hibernate command available, but it did not have a practical hibernate setup. The only active swap was zram, which is not suitable for hibernate.
systemctl hibernateExample failure:
Call to Hibernate failed: Not enough suitable swap space for hibernation available on compatible block devices and file systemsCheck memory, swap, filesystem, and free disk
Check the current memory size, active swap devices, root filesystem type, and available disk space before creating a swapfile.
free -h
swapon --show
findmnt -no FSTYPE /
df -h /Example output before the swapfile setup:
total used free shared buff/cache available
Mem: 62Gi 7.6Gi 49Gi 106Mi 4.9Gi 54Gi
Swap: 4.0Gi 0B 4.0Gi
NAME TYPE SIZE USED PRIO
/dev/zram0 partition 4G 0B 100
ext4
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/root 1.8T 537G 1.2T 31% /- The system has 62 GiB RAM.
- The only swap is 4 GiB zram.
- The root filesystem is ext4.
- The root filesystem has enough free disk space for a large swapfile.
Create the disk-backed swapfile
Create a disk-backed swapfile large enough for hibernate. For a 62 GiB RAM machine, an 80 GiB swapfile is a practical size. This keeps zram for normal runtime swap and adds the swapfile for hibernate.
sudo fallocate -l 80G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfileVerify the active swap devices:
swapon --show
free -hExpected output shape:
NAME TYPE SIZE USED PRIO
/dev/zram0 partition 4G 0B 100
/swapfile file 80G 0B -2
Swap: 83Gi 0B 83GiMake the swapfile persistent
Add the swapfile to /etc/fstab so it is enabled automatically after reboot. Keep zram as the higher priority runtime swap and give the disk swapfile a lower priority.
echo '/swapfile none swap defaults,pri=10 0 0' | sudo tee -a /etc/fstabVerify after the next reboot with:
swapon --showExpected output shape after reboot:
NAME TYPE SIZE USED PRIO
/swapfile file 80G 0B 10
/dev/zram0 partition 4G 0B 100Understand the two hibernate requirements
A working hibernate setup needs two separate pieces. The swapfile gives the system a place to write the memory image. The boot configuration tells the next boot where to read that image back from.
| Requirement | Purpose | Status after creating swapfile |
|---|---|---|
| Disk-backed swap | Stores the RAM image during hibernate | Ready |
| Resume configuration | Finds and restores the saved image during early boot | Still needed |
If hibernate powers off but the next boot starts a fresh session, the storage exists but the resume path is missing.
Get the resume UUID and offset
For a swapfile, the kernel needs the filesystem UUID and the physical offset of the swapfile. This is different from a swap partition because /swapfile is a file inside the root filesystem.
findmnt -no UUID -T /swapfile
sudo filefrag -v /swapfile | awk '$1=="0:" {print $4}' | sed 's/\.\.//'Example values from this setup:
f6c19f5d-1c81-4856-8ee6-8552dfe9f973
447834112These values become the resume kernel parameters.
resume=UUID=f6c19f5d-1c81-4856-8ee6-8552dfe9f973 resume_offset=447834112Confirm the boot method
Check whether the system uses GRUB or systemd-boot with UKI. In this setup, GRUB was not present and bootctl confirmed systemd-boot with UKI.
test -f /etc/default/grub && echo "grub default config exists"
test -f /boot/grub/grub.cfg && echo "grub boot config exists"
bootctl statusUseful signs of systemd-boot with UKI:
Current Boot Loader: systemd-boot
Current Stub: systemd-stub
type: Boot Loader Specification Type #2 (UKI, .efi)
source: /boot/EFI/Linux/arch-linux.efi- Do not run grub-mkconfig if GRUB is not used.
- Do not assume /boot/loader/entries/*.conf controls the kernel command line when using UKI.
- For this UKI setup, /etc/kernel/cmdline is the command line source.
Check the current kernel command line source
Read /etc/kernel/cmdline. This file should match the active kernel command line before adding the resume parameters.
cat /etc/kernel/cmdlineInitial value from this setup:
cryptdevice=PARTUUID=9432a0b4-f59e-4c24-95c7-23a637e1765a:root root=/dev/mapper/root zswap.enabled=0 rw rootfstype=ext4Update the UKI kernel command line
Back up the current file, then add resume=UUID and resume_offset to the same single line. This does not make every boot resume from hibernate. It only makes early boot check for a valid hibernation image at that location.
sudo cp /etc/kernel/cmdline /etc/kernel/cmdline.bak
sudo tee /etc/kernel/cmdline >/dev/null <<'EOF'
cryptdevice=PARTUUID=9432a0b4-f59e-4c24-95c7-23a637e1765a:root root=/dev/mapper/root zswap.enabled=0 rw rootfstype=ext4 resume=UUID=f6c19f5d-1c81-4856-8ee6-8552dfe9f973 resume_offset=447834112
EOF
cat /etc/kernel/cmdline- resume=UUID points to the filesystem that contains the swapfile.
- resume_offset points to the physical start of the swapfile inside that filesystem.
- Normal reboot and normal shutdown still boot normally when no valid hibernation image exists.
Update mkinitcpio hooks
Add the resume hook before filesystems. This makes initramfs check for the hibernation image early enough during boot.
sudo cp /etc/mkinitcpio.conf /etc/mkinitcpio.conf.bak
sudo nano /etc/mkinitcpio.confOriginal active hook line from this setup:
HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block encrypt filesystems fsck)Updated active hook line:
HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block encrypt resume filesystems fsck)- Keep the existing hooks.
- Only insert resume before filesystems.
- For encrypted root using the encrypt hook, keep encrypt before resume.
Rebuild UKI and initramfs
Rebuild the boot images so the updated command line and resume hook are included in the UKI files.
sudo mkinitcpio -PWatch for errors. Warnings may appear depending on firmware and modules, but the command should complete successfully. If the command fails, do not continue to hibernate testing until the error is fixed.
Reboot and verify active configuration
Reboot once after rebuilding. Then verify that the running kernel command line includes the resume parameters and that the swapfile is active.
sudo rebootAfter reboot:
cat /proc/cmdline
swapon --showExpected output shape:
cryptdevice=PARTUUID=9432a0b4-f59e-4c24-95c7-23a637e1765a:root root=/dev/mapper/root zswap.enabled=0 rw rootfstype=ext4 resume=UUID=f6c19f5d-1c81-4856-8ee6-8552dfe9f973 resume_offset=447834112
NAME TYPE SIZE USED PRIO
/swapfile file 80G 0B 10
/dev/zram0 partition 4G 0B 100Test hibernate restore
Create a simple marker under /tmp, hibernate, then power the laptop back on. If hibernate works, the old desktop session returns and the marker still exists.
touch /tmp/hibernate-ram-test
date
systemctl hibernateResume with the laptop power button. Then check:
ls -l /tmp/hibernate-ram-test
date| Result | Meaning |
|---|---|
| Previous desktop and apps return | Hibernate restore works |
| /tmp/hibernate-ram-test exists | The old memory session was restored |
| Fresh login with no old apps | Resume configuration is not being used or the image was not accepted |
Kernel choice rule
A hibernation image contains kernel state, loaded modules, driver state, device state, userspace processes, and the desktop session. Resume with the same kernel entry that created the image.
| Hibernate created from | Resume with |
|---|---|
| Rolling kernel | Rolling kernel |
| LTS kernel | LTS kernel |
- Do not intentionally hibernate from rolling and resume with LTS.
- Do not intentionally hibernate from LTS and resume with rolling.
- If rolling is the default boot entry, hibernate from rolling for daily use.
- If LTS is preferred for stability, make LTS the default boot entry before using hibernate regularly.
uname -rHow hibernate images are reused
Every hibernate call writes a new image into swap. It does not create separate image files. After a successful resume, the image is invalidated and the swap area can be used normally again.
- Hibernate now writes the current session image into /swapfile.
- On the next boot, initramfs checks the configured resume location.
- If a valid image exists, the old session is restored.
- If no valid image exists, the system boots normally.
- Old hibernation images do not pile up as separate files.
Normal boot behavior after this setup
The resume parameters do not force the system to restore from hibernate every time. They only allow the boot process to check for a valid hibernation image.
| Action | Next boot behavior |
|---|---|
| systemctl hibernate | Power on restores the old session if the same kernel entry is used |
| sudo reboot | Boots normally |
| sudo poweroff | Boots normally on next power on |
| Normal shutdown from desktop | Boots normally on next power on |
| No valid hibernate image exists | Boots normally |
Debug commands
Use these commands if hibernate powers off but resumes into a fresh session.
cat /proc/cmdline
grep '^HOOKS=' /etc/mkinitcpio.conf
swapon --show
journalctl -b -1 | grep -Ei 'hibernate|resume|PM:|swap'
journalctl -b | grep -Ei 'hibernate|resume|PM:|swap'Rollback notes
If hibernate support needs to be removed, restore the backed up command line and mkinitcpio config, rebuild UKI, and reboot. Remove the swapfile only after disabling it and removing the fstab entry.
# Restore boot configuration backups
sudo cp /etc/kernel/cmdline.bak /etc/kernel/cmdline
sudo cp /etc/mkinitcpio.conf.bak /etc/mkinitcpio.conf
sudo mkinitcpio -P
sudo rebootOptional swapfile removal:
# Disable the swapfile for the current session
sudo swapoff /swapfile
# Remove or comment the /swapfile line in /etc/fstab
sudo nano /etc/fstab
# Delete the swapfile after it is no longer active
sudo rm /swapfileConfig file locations
- Kernel command line source for UKI: /etc/kernel/cmdline
- mkinitcpio hooks: /etc/mkinitcpio.conf
- Persistent swap configuration: /etc/fstab
- Swapfile path: /swapfile
- systemd-boot status check: bootctl status
- Active runtime kernel command line: /proc/cmdline