|
| 1 | ++++ |
| 2 | +date = '2025-07-27T11:51:54+02:00' |
| 3 | +draft = false |
| 4 | +title = 'Never return to a drained laptop again!' |
| 5 | +summary = 'Enable hibernation in Ubuntu 24.10' |
| 6 | ++++ |
| 7 | + |
| 8 | +There have been several occasions where I haven't used my laptop in a few days, only to return to a |
| 9 | +completely drained battery. This is not only annoying, but also not very good for the battery. |
| 10 | + |
| 11 | +Maybe it's a false memory, but I want to recall that most OS's used to have a "Suspend, and then hibernate" feature. But now hibernation isn't even a default option in Ubuntu? |
| 12 | + |
| 13 | +This is a short guide on how to enable hibernation on Ubuntu 24.10. |
| 14 | + |
| 15 | +{{< alert >}} |
| 16 | +**Note:** I'm writing this in retrospect, and the instructions are probably not complete. |
| 17 | +This is mostly as a reminder to myself if I ever have to set it up again. |
| 18 | +{{</alert >}} |
| 19 | + |
| 20 | +## Setting it up |
| 21 | + |
| 22 | +### Resizing the swap file |
| 23 | + |
| 24 | +My system had a swap file (as opposed to a swap partition), but it was only 4GB in size (iirc). For |
| 25 | +hibernation purposes, it's recommended that your swap should be the size of your RAM, although |
| 26 | +there are ways to get |
| 27 | +[away with less](https://wiki.archlinux.org/title/Power_management/Suspend_and_hibernate#About_swap_partition/file_size). |
| 28 | + |
| 29 | +This command told me that my swap file was located at `/swap.img`. |
| 30 | + |
| 31 | +```bash |
| 32 | +swapon --show |
| 33 | +``` |
| 34 | + |
| 35 | +To resize it, I did the following commands: |
| 36 | + |
| 37 | +```bash |
| 38 | +# Disable the swap file |
| 39 | +sudo swapoff -a |
| 40 | +# Remove the old swap file |
| 41 | +sudo rm /swap.img |
| 42 | +# Use `dd` to create a new 16GB file with zeroes |
| 43 | +sudo dd if=/dev/zero of=/swap.img count=16384 bs=1MiB |
| 44 | +# Set the correct permissions |
| 45 | +sudo chmod 600 /swap.img |
| 46 | +# Enable this file to be used as swap |
| 47 | +sudo swapon /swap.img |
| 48 | +``` |
| 49 | + |
| 50 | +Instead of creating the file manually, it's also possible to use the command `mkswap`, which will |
| 51 | +set up the file with the correct permissions. |
| 52 | + |
| 53 | +Since I already had a swap file, it was already listed in `/etc/fstab` as: |
| 54 | + |
| 55 | +```bash |
| 56 | +/swap.img none swap sw 0 0 |
| 57 | +``` |
| 58 | + |
| 59 | +### Add kernel parameter to `grub` |
| 60 | + |
| 61 | +We need to pass `resume` and `resume_offset` as kernel parameters at boot. |
| 62 | + |
| 63 | +{{< alert >}} |
| 64 | +I'm not certain this is necessary. Newer `systemd` and `initramfs` will |
| 65 | +try to figure out where the resume data is. See `man initramfs-tools` and |
| 66 | +`man systemd-hibernate-resume`. But maybe when we are using a swap **file** rather than a |
| 67 | +partition, we need to where on a specific partition that file is? |
| 68 | +{{</alert>}} |
| 69 | + |
| 70 | +In `/etc/default/grub`, we add the `resume` parameter as the `UUID` of partition where the swap file lives. And `resume_offset` is where on that partition the file begins. (I think?) |
| 71 | + |
| 72 | +How do we find these values? |
| 73 | + |
| 74 | +The `UUID` we can find with the `findmnt` command: |
| 75 | + |
| 76 | +```bash |
| 77 | +sudo findmnt -no UUID -T /swap.img |
| 78 | +``` |
| 79 | + |
| 80 | +And it should print the UUID. E.g.: |
| 81 | + |
| 82 | +```plaintext |
| 83 | +abcd1234-1234-1234-bdbd-asdfaaaabbbb |
| 84 | +``` |
| 85 | + |
| 86 | +We find the offset with the `filefrag` command. |
| 87 | + |
| 88 | +```bash |
| 89 | +sudo filefrag -v /swap.img |
| 90 | +``` |
| 91 | + |
| 92 | +```plaintext |
| 93 | +File size of /swap.img is 17179869184 (4194304 blocks of 4096 bytes) |
| 94 | + ext: logical_offset: physical_offset: length: expected: flags: |
| 95 | + 0: 0.. 425983: [22118400..] 22544383: 425984: |
| 96 | +... |
| 97 | +``` |
| 98 | + |
| 99 | +I've "highlighted" where the swap file starts, our offset, with square brackets, i.e. `22118400`. |
| 100 | + |
| 101 | +```bash |
| 102 | +GRUB_CMDLINE_LINUX_DEFAULT="<...> resume=UUID=<your uuid> resume_offset=<some offset>" |
| 103 | +``` |
| 104 | + |
| 105 | +Example: |
| 106 | + |
| 107 | +```bash |
| 108 | +GRUB_CMDLINE_LINUX_DEFAULT="<...> resume=UUID=abcd1234-1234-1234-bdbd-asdfaaaabbbb resume_offset=1234" |
| 109 | +``` |
| 110 | + |
| 111 | +And finally, to add this to your `grub` menu, run: |
| 112 | + |
| 113 | +```bash |
| 114 | +sudo update-grub |
| 115 | +``` |
| 116 | + |
| 117 | +Then reboot to make it go into effect. After reboot, you can test it out by running: |
| 118 | + |
| 119 | +```bash |
| 120 | +systemctl hibernate |
| 121 | +``` |
| 122 | + |
| 123 | +## Suspend, then hibernate |
| 124 | + |
| 125 | +I don't want my system to hibernate all the time, I just want it to hibernate if I don't use it for a while. Thankfully, [Chris Arderne](https://rdrn.me/ubuntu-hibernate-luks/#sleep-then-hibernate) has us covered. |
| 126 | + |
| 127 | +We can get this behavior by changing the `HandleLidSwitch` parameter in `/etc/systemd/logind.conf`: |
| 128 | + |
| 129 | +```plaintext |
| 130 | +[Login] |
| 131 | +HandleLidSwitch=suspend-then-hibernate |
| 132 | +``` |
| 133 | + |
| 134 | +If the battery goes below 5%, the computer will hibernate. But we can also set it to hibernate based on time! |
| 135 | + |
| 136 | +In `/etc/systemd/sleep.conf` we can set the `HibernateDelaySec` paramter. I've set it to go into hibernation after 30 minutes. |
| 137 | + |
| 138 | +```plaintext |
| 139 | +[sleep] |
| 140 | +... |
| 141 | +HibernateDelaySec=1800 |
| 142 | +``` |
| 143 | + |
| 144 | +And then restart the logind service: |
| 145 | + |
| 146 | +```bash |
| 147 | +sudo systemctl restart systemd-logind.service |
| 148 | +``` |
| 149 | + |
| 150 | +## Sources |
| 151 | + |
| 152 | +* [Arch Linux Wiki](https://wiki.archlinux.org/title/Power_management/Suspend_and_hibernate#Hibernation) |
| 153 | +* [Chris Arderne blog](https://rdrn.me/ubuntu-hibernate-luks/) |
| 154 | +* `man systemd-sleep.conf` |
| 155 | +* `man logind.conf` |
0 commit comments