If you have a Linux laptop you probably wonder where's hibernation and hybrid sleep – especially if you're using an Ubuntu-based distribution such as Ubuntu Desktop, Kubuntu, TUXEDO OS, KDE Neon, etc. In this article we'll see what hibernation and hybrid sleep are, their caveats, and how to enable them on Linux with special instructions for Ubuntu-based distros. My test machine is a TUXEDO InfinityBook Pro 14" Gen 7, a rebranded Clevo laptop I purchased a couple of years ago. Without further ado, let's dive into it.
What's hibernation?
Having a computer running all the time, even when not using it, is wasting energy. This is especially important on an unplugged laptop as it depletes the battery for no good reason.
The simplest way to deal with that is suspending the Operating System, also known as “sleep”, or “suspend to RAM”. The memory remains powered on, but the CPU and the various chipsets and devices are either completely turned off, or running at a very low power state. This allows for a very fast restoration of the computer state, at the expense of still depleting your battery (albeit at a lower rate).
The alternative to sleep mode is hibernation, also known as “suspend to disk”. The contents of the memory are written to disk, then the computer fully shuts down. When you power it on again, the memory contents are read from disk, and your Operating System is restored to the exact state you had when you put the computer to hibernation. This allows for essentially zero power consumption, at the expense of a longer time to fully restore the computer state – usually a bit less time than a full cold boot.
Hybrid sleep, as the name implies, is a combination of the two. You put your computer to sleep like normal. However, if the battery charge reaches a critical state (typically 5% charge), or the computer has been sleeping for a set period of time the computer will wake up and put itself into hibernation. This combines the benefits of both approaches. You can resume your work quickly if you're taking a short break, but you won't waste your battery charge, or lose your session, if you go on an unexpectedly longer break or your battery charge is really low. This is how modern Windows and Apple laptops work, and you can have it on your Linux laptop, too!
Sleep caveats
First of all, sleep and hibernation must be supported by your computer's CPU and firmware. You can check if they are supported by doing
cat /sys/power/state
If you see mem
in the output your computer supports sleep mode. If you see disk
then your computer supports hibernation.
Sleep mode can be implemented in one of many ways. The most common ones are s2idle
and deep
. You can see which methods are supported by your computer, and which one is used, by doing
cat /sys/power/mem_sleep
The value in brackets is the one which is going to be used. And this is where things start getting confusing. Please stay with me.
Historically, s2idle
was (the past tense is important here) the least desirable sleep method as it only put the CPU and devices in a low power state. The system was effectively still running, albeit at a somewhat reduced power draw. Conversely, deep
was the most preferred method as it turned everything off except for RAM. The reason there were two vastly different implementations was hardware support; s2idle
is implemented purely in software, whereas deep
requires firmware support.
If you have a laptop with a 4th gen Intel Core processor or newer you might be surprised to see that the default sleep mode is the supposedly inferior s2idle
. Well, here is the confusing part. On these newer processors the s2idle
actually refers to a different sleep mode called Modern Sleep or Connected Sleep, implementing Intel's S0ix power state. It allows a power consumption that's as low as deep
, but with an even faster restoration time. However, if your firmware is buggy it may end up drawing more power than deep
. If you find that your battery depletes in a matter of hours using this sleep mode, you may want to try the deep
sleep mode instead.
If you want to change the sleep mode used by the kernel to deep
you can edit /etc/default/grub
and change the line starting with GRUB_CMDLINE_LINUX_DEFAULT
, adding mem_sleep_default=deep
into it. Then run sudo update-grub
to reinstall the boot loader, and reboot your computer.
deep
sleep mode is unlikely to work on modern systems. If your computer fails to wake up from sleep you need to instead use mem_sleep_default=s2idle
in GRUB's configuration.Hibernation pitfalls
Hibernation has to store your RAM contents onto disk. This requires a swap partition or swap file that's at least as big as your RAM, plus however much swap space you normally use. My rule of thumb is amount of RAM plus one or two GiB. Note that this space must be allocated in a SINGLE swap partition or swap file; having two or more swap spaces totaling the right amount won't cut it!
Because of the above, if you have lots of RAM but a small storage device hibernation may present a challenge insofar it “wastes” disk space. That was a legitimate concern a few years ago. Now, you can get a pretty decent 2 TiB NVMe drive for about €100, rendering this point moot for most people. If, however, budget or policy prevent you from upgrading to roomier storage you may want to weigh whether hibernation is more valuable to you than storage space. It all comes down to what is your use case.
Hibernation stores all of your RAM contents into the disk. If you are using an unencrypted swap partition, or a swap file (because swap files can be used with hibernation only if they are stored in unencrypted partitions) you have a security risk. If someone steals your device while it's hibernating they will be able to read your RAM contents as stored on your disk, extracting any secrets stored in memory. This can be detrimental to security. I advise that you always use an encrypted swap partition, or a logical swap partition in a LUKS2-encrypted LVM partition. In fact, I would NOT recommend setting up hibernation if you don't use swap space encryption.
Remember when I said that hibernating your computer uses “essentially zero” power? Well, that's not entirely true. A small amount of power is always used by your computer's firmware so that the computer's power button can work. In practical terms, it takes weeks to drain the battery in this power off state, and it only becomes relevant if you are not using your laptop for weeks or months at a time.
Finally, hibernation can be finicky. Your hardware may simply not work very well with going into or coming out of hibernation. I had a desktop like that. One out of five times it'd come out of hibernation it would simply hang, except if I used an LTS kernel, pointing to some sort of kernel driver issue. I sold that desktop before I had the chance to troubleshoot it, so there's that.
Enabling hibernation
Step 1. Can you hibernate?
If you skimped the information above, start by running cat /sys/power/state
and make sure disk
is listed in the output. If it's not, hibernation is not supported by your computer's firmware. End of story, so sorry.
Step 2. Locate your swap partition
Make sure you have a swap partition that's big enough. Rule of thumb: the partition size should be the amount of memory you have, plus 1 or 2 GiB. I have 64GiB or RAM, so I created a partition that's 65 GiB.
Make sure the swap partition is listed in /etc/fstab. For example:
UUID=01234567-c0ff-eede-adbe-ef0123456789 none swap defaults 0 0
Note down the UUID you see there. If you see a device name instead (such as /dev/sda1
) run blkid
and note down the UUID reported for that device. In our example, the UUID will be 01234567-c0ff-eede-adbe-ef0123456789
.
Step 3. Make sure Linux knows about the swap partition
Make sure the swap partition is enabled by running swapon
. You should see your swap device being listed:
NAME TYPE SIZE USED PRIO
/dev/dm-2 partition 65G 44M -2
Note that you see the device name, not the UUID. If you are using LVM on a LUKS2-encrypted partition like I do you will see a device name similar to /dev/dm-2 which may not ring a bell. If you run ls -l /dev/mapper you will see something that makes a lot more sense:
total 0
drwxr-xr-x 2 root root 120 Apr 20 19:17 ./
drwxr-xr-x 22 root root 4820 Apr 20 19:17 ../
crw------- 1 root root 10, 236 Apr 20 19:17 control
lrwxrwxrwx 1 root root 7 Apr 20 19:17 crypt_dev_nvme0n1p3 -> ../dm-0
lrwxrwxrwx 1 root root 7 Apr 20 19:17 system-root -> ../dm-1
lrwxrwxrwx 1 root root 7 Apr 20 19:17 system-swap -> ../dm-2
That last line tells me that /dev/mapper/system-swap is /dev/dm-2 so, indeed, my logical swap partition on the LUKS2-encrypted LVM is the one that swapon
reports as enabled.
If you do not see your swap partition enabled make sure to add it to /etc/fstab
and run sudo swapon -a
to enable all swap partitions.
Do not proceed until you have verified that your swap partition is enabled, and it's big enough for hibernation.
Step 4. Update the Linux kernel parameters
Edit the file /etc/default/grub
e.g. by running sudo nano /etc/default/grub
.
Find the line starting with GRUB_CMDLINE_LINUX_DEFAULT
and append resume=UUID=01234567-c0ff-eede-adbe-ef0123456789
to it, where 01234567-c0ff-eede-adbe-ef0123456789
is the UUID of the swap partition. For example, if the line reads
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
change it to read
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash resume=UUID=01234567-c0ff-eede-adbe-ef0123456789"
Then run sudo update-grub
to update the boot loader.
Step 5. Update the initial RAM disk
We will need to create a new file /etc/initramfs-tools/conf.d/99-resume
which tells the kernel's initial RAM disk where to look for hibernation data. For example, run sudo nano /etc/initramfs-tools/conf.d/99-resume
and paste the following:
RESUME=UUID=01234567-c0ff-eede-adbe-ef0123456789
where 01234567-c0ff-eede-adbe-ef0123456789
is the UUID of the swap partition.
Then update the initial RAM disk by running sudo update-initramfs -k all -c
Step 6. Reboot
Reboot your computer.
Technically not necessary, but it's always a good idea to make sure the computer reboots normally i.e. we didn't botch anything up to this point.
Step 7. Check hibernation works
Open a terminal and run systemctl hibernate
At this point you will see your session being paused, like when you enter sleep mode, and your screen may turn off and turn on again. Do not touch anything. After a few seconds your computer will shut down.
Wait a few seconds, then power up your computer again. After entering your disk encryption password (if you use any encrypted partitions) you should see a message that the system is resuming from such and such device. Wait a few seconds and you should be back to your display manager's login screen. Log in and you should you see your desktop, exactly as you left it. Success!
Step 7. Configure hybrid sleep
Edit the /etc/systemd/sleep.conf
file, e.g. sudo nano /etc/systemd/sleep.conf
and append the following:
AllowHybridSleep=yes
HibernateDelaySec=30m
This tells systemd to enable hybrid sleep (suspend-then-hibernate), with the time threshold being 30 minutes. In other words, if your computer stays sleeping for 30 minutes it will wake up and hibernate itself. You can of course change that to your liking. If you want to test you can set this to 2 or 3 minutes; don't use smaller values, you may run into problems because entering sleep does take some amount of time.
Necessary tweaks for Ubuntu-based distros
If you are on an Ubuntu-based distribution you may have noted that you are missing a logout menu icon to hibernate your computer, and your power settings appear to be completely unaware of the fact that your computer now supports hibernation. That's because Ubuntu is explicitly disabling hibernation in all of its desktops. This unfortunately applies to downstream distributions like Kubuntu, KDE Neon, and TUXEDO OS.
We have to do TWO changes.
First, run sudo mkdir -p /var/lib/polkit-1/localauthority/50-local.d
to create a new PolKit configuration directory, then sudo nano /var/lib/polkit-1/localauthority/50-local.d/99-hibernate.pkla
and paste the following into the new file:
[Re-enable hibernate by default in upower] Identity=unix-user:* Action=org.freedesktop.upower.hibernate ResultActive=yes [Re-enable hibernate by default in logind] Identity=unix-user:* Action=org.freedesktop.login1.hibernate;org.freedesktop.login1.handle-hibernate-key;org.freedesktop.login1;org.freedesktop.login1.hibernate-multiple-sessions;org.freedesktop.login1.hibernate-ignore-inhibit;org.freedesktop.login1.manager.hibernate ResultActive=yes
/etc/polkit-1/localauthority/50-local.d
instead.If you are wondering, this undoes Ubuntu's upstream disabling of hibernation in /var/lib/polkit-1/localauthority/10-vendor.d/com.ubuntu.desktop.pkla
.
While this was enough for Ubuntu up to 20.04, newer versions of Ubuntu apply further PolKit rules which prevent non-root users from managing hibernation. Groan. So, let's create a new /etc/polkit-1/rules.d/99-hibernate.rules
file to undo these changes. Run sudo nano /etc/polkit-1/rules.d/99-hibernate.rules
and paste the following:
polkit.addRule(function(action, subject) {
if (action.id == "org.freedesktop.login1.suspend" ||
action.id == "org.freedesktop.login1.suspend-multiple-sessions" ||
action.id == "org.freedesktop.login1.hibernate" ||
action.id == "org.freedesktop.login1.hibernate-multiple-sessions" ||
action.id == "org.freedesktop.login1.handle-hibernate-key" ||
action.id == "org.freedesktop.login1.hibernate-ignore-inhibit" ||
action.id == "org.freedesktop.login1" ||
action.id == "org.freedesktop.login1.manager.hibernate") {
return polkit.Result.YES;
}
});
Now run systemctl restart polkit
to apply our PolKit changes.
Log out, and then log back in for the desktop environment to see the PolKit changes.
At this point you should see the Hibernate icon (at least I do, in KDE), and be able to manage hibernation settings in your desktop environment's power settings.
To test that our changes did work run the following in a terminal window:
dbus-send --system --print-reply --dest=org.freedesktop.login1 /org/freedesktop/login1 org.freedesktop.login1.Manager.Hibernate boolean:true
You should see that your system goes into the hibernation procedure once you press ENTER.