Sleep Is a Spectrum (And Linux Takes That Literally)
On Windows you hit sleep and stuff works. On Linux, you might suspend successfully for a week and then one day wake up to a hung system, a blank screen, or a kernel panic that takes your session with it. It’s not Linux’s fault specifically — the firmware, hardware, and drivers are all conspiring against you — but you need to understand what’s happening to fix it.
There are multiple sleep states. They trade power savings for complexity and resume reliability. Here’s the breakdown:
The Sleep States (S1 through S4)
The ACPI spec defines sleep states S1 through S5 (S5 is powered off). The useful ones:
S1 — CPU Stop Grant: CPU stops executing instructions, RAM stays powered. Very fast resume, almost no power savings. Almost nobody uses this.
S2 — Similar to S1: CPU powered off. Rare. Not really a thing on modern hardware.
S3 — Suspend to RAM (STR): The one you call “sleep.” CPU and most devices powered off. RAM stays powered to retain state. Typically uses 1-5 watts. Resume in 1-3 seconds. This is what systemctl suspend does.
S4 — Hibernate (Suspend to Disk): Everything written to swap/disk, then powered off completely. Uses 0 watts. Resume in 10-30 seconds (basically a specialized boot). This is what systemctl hibernate does.
Hybrid Sleep: Saves state to disk (like hibernate) but also stays in S3 (like suspend). If power is lost, it can resume from disk. Best of both worlds, slightly slower to enter than pure suspend.
# What sleep states does your hardware support?
cat /sys/power/state
# Typical output: freeze mem disk
# Check supported hibernation modes
cat /sys/power/disk
# Typical output: platform shutdown reboot suspend [platform]
Suspend to RAM: Usually Just Works
# Suspend immediately
systemctl suspend
# Or the old way
echo mem > /sys/power/state
Suspend usually works on modern hardware. When it doesn’t, the problems are:
- GPU driver not supporting suspend/resume (nouveau is a frequent offender)
- USB controllers not waking properly
- Wi-Fi firmware not supporting power state transitions
Debug it:
# Check what happened during last suspend/resume cycle
journalctl -b -1 -u systemd-sleep
journalctl -b -1 | grep -i "suspend\|resume\|wake"
# See what's blocking suspend
cat /sys/power/wakeup_count
cat /proc/acpi/wakeup
Hibernate: Requires More Setup
Hibernate is trickier because it requires a properly configured swap space and the initramfs needs to know where to find it.
Step 1: Make Sure You Have Enough Swap
For hibernate, you need swap space at least as large as your RAM. More is better because your RAM might not be 100% used.
# Check current swap
swapon --show
free -h
# If you need more swap — create a swapfile
sudo fallocate -l 16G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# Make it permanent
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
For a dedicated swap partition, the partition already exists in most installs — just verify it’s large enough.
Step 2: Find the Resume Device
You need to tell the kernel where to find the saved hibernate image on boot.
# Find your swap partition or file's UUID
sudo blkid | grep swap
# OR for a swapfile:
stat /swapfile
# Note the device it's on
# For a swapfile, get the offset
sudo filefrag -v /swapfile | head -5
# The first extent's physical_offset is what you need
Step 3: Configure GRUB for Resume
Edit your GRUB config:
sudo nano /etc/default/grub
For a swap partition:
GRUB_CMDLINE_LINUX="resume=UUID=your-swap-uuid-here"
For a swapfile (replace with your actual device UUID and offset):
GRUB_CMDLINE_LINUX="resume=UUID=your-root-device-uuid resume_offset=12345678"
Then update GRUB:
# Debian/Ubuntu
sudo update-grub
# RHEL/Fedora
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
Step 4: Update the Initramfs
The initramfs needs to include the resume hook so it can restore the hibernate image on boot:
# Ubuntu/Debian — edit initramfs config
cat /etc/initramfs-tools/conf.d/resume
# Should contain: RESUME=UUID=your-swap-uuid
# If it doesn't exist or is wrong, create/edit it:
echo "RESUME=UUID=$(findmnt -no UUID /swapfile 2>/dev/null || blkid -s UUID -o value /dev/sdX)" \
| sudo tee /etc/initramfs-tools/conf.d/resume
# Rebuild initramfs
sudo update-initramfs -u -k all
# Test hibernate
systemctl hibernate
If it works, your system powers off and comes back with your session intact. If it doesn’t, check journalctl -b -1 for clues.
UEFI Secure Boot Complications
Hibernate can fail with Secure Boot if the hibernate image is considered untrusted. The typical symptom: system resumes to a fresh session instead of your saved state, or refuses to load the hibernate image entirely.
The kernel checks that the hibernate image was created by a trusted kernel. If you’re using DKMS modules (like NVIDIA drivers or VirtualBox) and they’re not signed, Secure Boot can interfere.
Options:
- Disable Secure Boot in UEFI settings (easiest for home lab)
- Sign your kernel modules properly (the Right Way)
- Use
lockdown=integritykernel parameter and accept the limitations
# Check if Secure Boot is enabled
mokutil --sb-state
# Check if lockdown is active
cat /sys/kernel/security/lockdown
Hybrid Sleep: The Best Compromise
For laptops and machines where power cuts are possible, hybrid sleep is often the best option:
# Enable hybrid sleep as the default sleep mode
sudo nano /etc/systemd/sleep.conf
[Sleep]
SuspendMode=suspend
HibernateMode=platform shutdown
HybridSleepMode=suspend platform shutdown
HybridSleepDelay=120min
SuspendState=mem
HibernateState=disk
HybridSleepState=disk
# Test hybrid sleep
systemctl hybrid-sleep
The HybridSleepDelay option in newer systemd means: suspend normally, but if the system is still asleep after that duration, automatically hibernate. Brilliant for laptops — fast wakes for short naps, full hibernation for overnight.
Laptop Lid Close Behavior
This drives everyone insane at least once. Control it in /etc/systemd/logind.conf:
[Login]
HandleLidSwitch=suspend # What to do when lid closes
HandleLidSwitchExternalPower=suspend # When plugged in
HandleLidSwitchDocked=ignore # When docked (connected to external display)
IdleAction=suspend # What to do after idle timeout
IdleActionSec=30min
sudo systemctl restart systemd-logind
Options for HandleLidSwitch: suspend, hibernate, hybrid-sleep, suspend-then-hibernate, poweroff, ignore.
Wake-on-LAN
Wake-on-LAN (WoL) lets you remotely wake a sleeping machine by sending a “magic packet” to its MAC address. Useful for home labs where you want a server to suspend when idle but wake on demand.
# Check if your NIC supports WoL
sudo ethtool eth0 | grep -i wake
# Enable WoL
sudo ethtool -s eth0 wol g # g = magic packet
# Make it persistent with a systemd service
# /etc/systemd/system/wol.service
[Unit]
Description=Enable Wake-on-LAN
After=network.target
[Service]
Type=oneshot
ExecStart=/sbin/ethtool -s eth0 wol g
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
sudo systemctl enable --now wol.service
# Send the magic packet from another machine
# Install wakeonlan: sudo apt install wakeonlan
wakeonlan AA:BB:CC:DD:EE:FF
# Or with etherwake
sudo etherwake -i eth0 AA:BB:CC:DD:EE:FF
For WoL to work through suspension, you also need to enable it in the UEFI/BIOS settings under “Power Management” or similar.
Troubleshooting Common Failures
System suspends but wakes up immediately: Something is triggering a wakeup. Check:
cat /proc/acpi/wakeup
# Disable a wakeup source (e.g., USB)
echo USB3 | sudo tee /proc/acpi/wakeup
Blank screen after resume: Usually a GPU driver issue. Try:
# For NVIDIA
sudo systemctl enable nvidia-suspend.service
sudo systemctl enable nvidia-hibernate.service
sudo systemctl enable nvidia-resume.service
Hibernate fails with “not enough swap”: Your swap is too small. Add more swap space.
Resume from hibernate boots to login screen instead of session: Usually a display manager issue, not a hibernate failure. Your session is restored at the kernel level, but the display manager intercepts before showing it. Check if your DM has a “resume session” option.
System won’t hibernate, returns to running state immediately: Check systemd-inhibit --list — something is holding an inhibitor lock:
systemd-inhibit --list
# Kill the offending process or wait for it to finish
Getting suspend and hibernate working properly takes some tuning, but once it’s dialed in, you stop thinking about it entirely. The payoff — especially for laptops — is real: faster wake times than a full boot, battery preservation, and sessions that survive overnight without running your fans all night.
Your laptop deserves to sleep. Let it.