Added hibernation support
Resolves: #105
- Creates btrfs subvolume for swap file, to not break snapshots
- Creates swap file with size of ram
- Adds swap file to
/etc/fstabto mount swap file on boot - Adds resume module via
HOOKS+=(resume)in/etc/mkinitcpio.conf.d/omarchy_resume.conf - Adds
Hibernateoption to Power menu
I'd love to get some feedback 😄
Not sure about install step, but I can confirm that the hibernate work like it should be. I'm also on Nvidia which most the problem come from and doesn't have any issue. Hope this get merge soon because I have to create a copy of Omarchy menu just to test it out or just run systemctl hibernate in terminal, but I prefer it under Suspend like this.
@killeik ok, I got some problem with the hyprlock crash(not related), so I tried to reinstall and the first thing I do is to run the hibernate.sh command to test.
Run systemctl hibernate like usual.
But when power on, it brings me to the Omarchy Bootloader screen. So I'm not sure what wrong.
Boot up to the linux only open a new fresh just like when reboot, others app open or the last state doesn't return.
@nielpattin
it brings me to the Omarchy Bootloader screen
It's okay. The boot sequence from hibernation starts like a fresh boot. It should decrypt the disk and start the kernel. Later on, however, it finds a RAM dump on the disk and loads that instead of loading fresh.
Boot up to the linux only open a new fresh just like when reboot, others app open or the last state doesn't return.
Let's debug I need output of that one (putted them in one command, to not make you Ctrl+C/Ctrl+V all the way :D )
bash -c 'set -x ;
swapon ;
free -h ;
sudo btrfs subvolume show /swap ;
sudo btrfs inspect-internal map-swapfile /swap/swapfile ;
cat /sys/power/resume_offset ;
cat /sys/power/resume ;
cat /etc/fstab ;
cat /etc/mkinitcpio.conf.d/omarchy_resume.conf ;'
And kernel logs after hibernation (they are not so small, so send them as file, maybe)
sudo dmesg -TH
For convenience, you can send them to me in DM in Discord, I'm @killeik on omarchy server
After some debugging in DM, it was discovered that there was a magical Nvidia, for which the standard mode of operation on Linux is to torment the user. Other than that, everything worked fine.
I've tested this on my Framework laptop / AMD Ryzen and it works great 👍 Thanks!
Need to update for current branch, make the Hibernate option conditional on the swap being available, and add a migration with a gum confirm something like "Use XX GB on drive to make hibernate available?".
Need to update for current branch, make the Hibernate option conditional on the swap being available, and add a migration with a gum confirm something like "Use XX GB on drive to make hibernate available?".
While you add it. Also make a check if swap is already configured. I have an encrypted swap on my machine so hibernation.sh would break my machine with custom partitions / swap / encryption.
My apologies. I updated my fork branch to the current active branch, accidentally deleting the changes I had added, and GitHub automatically closed the pull request because the branches started to match.
By the way, I added migration and made the hibernation option in omarchy-menu optional.
Tested conditional hibernation in power menu, and migration - everything works correctly.
The only pitfall is that if the user manually created a swap and didn't enable the resume hook, the boot sequence will not resume from the saved hibernation image and will start fresh.
I found a way to check if the hooks are enabled on the current initramfs with limine:
lsinitcpio /boot/EFI/Linux/*.efi | grep 'hooks/resume'
However, I'm unsure if it will work on GRUB and other systems.
Did you try the PR? I tried multiple PR in my own fork, and the menu does not work. I suspect this PR might break the omarchy menu system
Did you try the PR? I tried multiple PR in my own fork, and the menu does not work. I suspect this PR might break the omarchy menu system
I've tested this PR on both of my computers and it works correctly. I actually don't have any ideas how it can break menu, because my change for it is very simple. So can you please give more info what's going on in your fork?
I've tested this PR on both of my computers and it works correctly. I actually don't have any ideas how it can break menu, because my change for it is very simple. So can you please give more info what's going on in your fork?
https://github.com/woopstar/omarchy/commits/master/
I will check tomorrow which PR that broke the app launcher then :)
It was #1661 that broke the menu. I tested this. Works as it should. But it shows the lock menu that "hangs" while it waits for hibernation to be ready. Should we consider showing something else if possible? Would it be possible to have it say "Entering hibernation" instead of showing the lock screen, which you cannot type or do anything in?
It was https://github.com/basecamp/omarchy/pull/1661 that broke the menu. I tested this. Works as it should.
Thank you!
But it shows the lock menu that "hangs" while it waits for hibernation to be ready. Should we consider showing something else if possible? Would it be possible to have it say "Entering hibernation" instead of showing the lock screen, which you cannot type or do anything in?
Neither hypridle, which invokes the lock screen before sleep or hibernation, nor hyprlock, which works as a lock screen, has any difference between sleep and hibernation. Therefore, it's not possible at this level.
However, systemd has different targets: suspend.target, hibernate.target, hybrid-sleep.target, and suspend-then-hibernate.target. Technically, we could write a service that runs before hibernate.target and changes the hyprlock configuration to display something like "Hibernating, wait" and then changes it back after hibernation. However, it feels like a bad hack, changing user-space config on every hibernation is kinda crazy.
To do that the normal way, we would probably need to create an issue in Hyprildle/Hyprlock.
However, systemd has different targets: suspend.target, hibernate.target, hybrid-sleep.target, and suspend-then-hibernate.target. Technically, we could write a service that runs before hibernate.target and changes the hyprlock configuration to display something like "Hibernating, wait" and then changes it back after hibernation. However, it feels like a bad hack, changing user-space config on every hibernation is kinda crazy.
Yeah, let's not walk down that road. But I can confirm the PR works as expected :)
I am thinking about moving to OMARCHY from my customized ARCH and i think this was the script I used to enable the Swap. I used a swap file instead of a volume (i think the subvolume is the better approach). I drop my config / code as it may be helpful. I am using hibernate when closing the lid. I checked the issues for hibernate as this is an important feature for me.
#!/bin/sh
# check if su or root
if [ "$(id -u)" != "0" ]; then
echo "This script must be run as root" 1>&2
exit 1
fi
# check if btrfs
if [ ! -d /sys/fs/btrfs ]; then
echo "This script is only for btrfs filesystems" 1>&2
exit 1
fi
# check if swapfile exists if not create it with 96GB
if [ ! -f /swap/swapfile ]; then
echo "Creating swapfile with 96GB"
fallocate -l 96G /swap/swapfile
chmod 600 /swap/swapfile
mkswap /swap/swapfile
swapon /swap/swapfile
fi
cd /tmp
# :: btrfs_map_physical :: #
wget https://raw.githubusercontent.com/osandov/osandov-linux/master/scripts/btrfs_map_physical.c
gcc -O2 -o btrfs_map_physical btrfs_map_physical.c
# :: edit grub :: #
offset=$(./btrfs_map_physical /swap/swapfile)
offset_arr=($(echo ${offset}))
offset_pagesize=($(getconf PAGESIZE))
offset=$((offset_arr[25] / offset_pagesize))
btrfsroot=`findmnt / -no UUID`
echo "btrfsroot=$btrfsroot"
echo "offset=$offset"
# create a backup of /etc/default/grub
cp /etc/default/grub /etc/default/grub.bak
# edit /etc/default/grub
sed -i "s#loglevel=3#resume=/dev/mapper/root loglevel=3#" /etc/default/grub
sed -i "s/loglevel=3/resume_offset=$offset loglevelbtrfs property set \/swap\/swapfile compression none=3/" /etc/default/grub
My /etc/systemd/logind.conf
[Login]
#NAutoVTs=6
#ReserveVT=6
#KillUserProcesses=no
#KillOnlyUsers=
#KillExcludeUsers=root
#InhibitDelayMaxSec=5
#UserStopDelaySec=10
#SleepOperation=suspend-then-hibernate suspend
HandlePowerKey=lock
#HandlePowerKeyLongPress=ignore
#HandleRebootKey=reboot
#HandleRebootKeyLongPress=poweroff
#HandleSuspendKey=suspend
#HandleSuspendKeyLongPress=hibernate
#HandleHibernateKey=hibernate
#HandleHibernateKeyLongPress=ignore
HandleLidSwitch=suspend-then-hibernate
HandleLidSwitchExternalPower=suspend-then-hibernate
#HandleLidSwitchDocked=ignore
#PowerKeyIgnoreInhibited=no
#SuspendKeyIgnoreInhibited=no
#HibernateKeyIgnoreInhibited=no
#LidSwitchIgnoreInhibited=yes
#RebootKeyIgnoreInhibited=no
#HoldoffTimeoutSec=30s
#IdleAction=ignore
#IdleActionSec=30min
#RuntimeDirectorySize=10%
#RuntimeDirectoryInodesMax=
#RemoveIPC=yes
#InhibitorsMax=8192
#SessionsMax=8192
#StopIdleSessionSec=infinity
@killeik I've been thinking if this should also enable the suspend-then-hibernate support.
$ cat /etc/systemd/sleep.conf.d/omarchy.conf
[Sleep]
HibernateDelaySec=60min
AllowSuspendThenHibernate=yes
$ cat /etc/systemd/logind.conf.d/omarchy.conf
[Login]
HandleLidSwitch=suspend-then-hibernate
HandleLidSwitchExternalPower=suspend-then-hibernate
HandleLidSwitchDocked=suspend-then-hibernate
Unsure if we also must:
systemctl enable systemd-suspend-then-hibernate.service
References: https://man.archlinux.org/man/systemd-sleep.conf.5 https://man.archlinux.org/man/logind.conf.5.en
If we want to do something like this, I suggest using sleep instead of straight-forward suspend-then-hibernate for HandleLidSwitch:
sleep Put the system to sleep, through suspend, hibernate, hybrid-sleep, or suspend-then-hibernate. The sleep operation to use is automatically selected by systemd-logind.service(8). By default, suspend-then-hibernate is used, and falls back to suspend and then hibernate if not supported. Refer to SleepOperation= setting in logind.conf(5) for more details. This command is asynchronous, and will return after the sleep operation is successfully enqueued. It will not wait for the sleep/resume cycle to complete.
Added in version 256.
It will work if the system has or does not have hibernation mode.
I'm also not sure if we really want to change HibernateDelaySec.
Setting the AllowSuspendThenHibernate=yes may actually break users without hibernation.
This flag, as I understand it, is intended to turn off the features, not to enable them.
Systemd doesn't need any changes to the configuration to find system support for hibernation.
And the systemd-suspend-then-hibernate.service - it's not a daemon. It's a one-shot command to start the suspend-then-hibernate sequence.
Note that systemd-suspend.service, systemd-hibernate.service, systemd-hybrid-sleep.service, and systemd-suspend-then-hibernate.service should never be executed directly. Instead, trigger system sleep with a command such as systemctl suspend or systemctl hibernate.
But I'm not sure if it's a good idea to talk about these improvements in this PR. My idea was just to add support for hibernation.
There is an easier way to find resume=UUID=<UUID> and resume_offset cmdline parameters:
findmnt -no UUID -T /swap/swapfile
btrfs inspect-internal map-swapfile -r /swap/swapfile
And I add resume=UUID=<UUID> resume_offset=<the-number-from-inspect-internal> at the end of my cmdline in my limine.conf file. But I'm on my custom Arch Linux setup. Not sure about Omarchy
https://wiki.archlinux.org/title/Power_management/Suspend_and_hibernate#Acquire_swap_file_offset
@DominicBoettger
This would be a really cool feature to extend the battery life!
Great job. Worked for me too.
I prefer suspend-then-hibernate with a 1 hour delay. So I changed systemctl suspend to systemctl suspend-then-hibernate in the menu.
And similarly for /etc/systemd/logind.conf: HandleLidSwitch=suspend-then-hibernate
And /etc/systemd/sleep.conf: HibernateDelaySec=3600.
Why no merge? dhh likes his bag toasty?
Does this needs more testing reports from more people before it gets merged?
Migration has an interactive prompt we need to sort:
Also, some tweaks to the migration:
echo "Offer hibernation if missing as a system-menu option"
if omarchy-hibernation-available; then
exit 0
fi
MEM_TOTAL_HUMAN="$(free --human |grep "Mem" |awk '{print $2}')"
if gum confirm "Use $MEM_TOTAL_HUMAN on boot drive to make hibernation available?"; then
source $OMARCHY_PATH/install/config/hibernation.sh
fi
It unfortunately doesn't work consistently on my machine either. There's no feedback while it's trying to write the hibernation file, but even when I left it for a few minutes, it never fully shut down the computer. I manually had to do that.
Then on reboot, it's also stuck on the decryption screen without feedback for a long time. Long enough that you think it might be broken. Eventually it did boot up.
On the second run, I must not have waited long enough for the hibernation write to actually go through, because I shut the computer off after maybe 20 seconds, and when I reboot again, there was no hibernation restored.
I totally get why this is desirable to have, but if we can't get it to work consistently, I don't think we can offer it out of the box.
This was on a 128GB AMD 395+ in the Beelink GTR9 Pro.
@dhh, I made the suggested changes. Now, there won't be an interactive prompt. Previously, I had to use mkinitcpio because omarchy wasn't defaulting to use only limine uki.
Regarding the issue with your PC not shutting down, do you have time to debug it? Try adding these parameters to sleep conf: https://wiki.archlinux.org/title/Power_management/Suspend_and_hibernate#System_does_not_power_off_when_hibernating If this solves the problem, I will add the parameters to the installation script
Also, if the system doesn't restore the correct state after hibernation, can you share the output of the command sudo dmesg -TH? There will probably be information explaining why that happened.
From my limited understanding (arch noob here), subvolumes aren’t recommended for hibernation and may lead to weird results if CoW and compression aren’t disabled for the subvolume.
Can anyone confirm?
From my limited understanding (arch noob here), subvolumes aren’t recommended for hibernation and may lead to weird results if CoW and compression aren’t disabled for the subvolume.
From https://btrfs.readthedocs.io/en/latest/btrfs-man5.html#swapfile-support
subvolume - cannot be snapshotted if it contains any active swapfiles
So, to create snapshots, it's required to have a separate subvolume for swap.
About compression - newly created subvolume doesn't contain compression flags.
And command btrfs filesystem mkswapfile - disables CoW for swapfile
sudo lsattr /swap
---------------C------ /swap/swapfile
I've taken the newest .iso of Omarchy, installed it on my ThinkPad X220, and updated it. Then I've copied the changed files from this repo to the folders located in "~/.local/share/omarchy/." and gave them the executable flag. Then I've run the "1758205457.sh" file and rebooted the laptop. Then I've added "HandleLidSwitch=suspend-then-hibernate" to "/etc/systemd/login.conf" and "HibernationDelaySec=2min" (to test it) and "AllowSuspendThenHibernate=yes" in "/etc/systemd/sleep.conf". The "Hibernation" option in Power Menu, and suspend then hibernate works flawlessly, but after entering the password to the "OMARCHY" decryption screen, I have to put the password again into the user login screen (one with the fingerprint icon).
ThinkPad X220 specs: processor: Intel i5-2540M memory: 16GB DDR3 1866MHz disk: 240GB SSD
I am using GitHub for the first time in my life, so if I've done something wrong by leaving this comment, please tell me. I've given a lot of information (this may help in some way).
... The "Hibernation" option in Power Menu, and suspend then hibernate works flawlessly, but after entering the password to the "OMARCHY" decryption screen, I have to put the password again into the user login screen (one with the fingerprint icon).
@braintornapart So, the problem is that you had to enter your password twice?
That's how hypridle/lock works. I wrote about that before.
Neither hypridle, which invokes the lock screen before sleep or hibernation, nor hyprlock, which works as a lock screen, has any difference between sleep and hibernation.
If we want to keep the login screen after sleep mode, we also have to keep it after hibernation mode. The first prompt on the decryption screen is required because of the encrypted disks, and we can't disable it.
It's a bit annoying, but fixing it requires changes to hypridle to differentiate between hibernation and sleep.