Configure systemd Sleep Modes with sleep.conf.d

A laptop that will not suspend the way you expect usually just needs a sleep.conf.d drop-in, not a kernel rebuild. You will finish with a small, reversible systemd drop-in that controls which sleep modes are advertised or how suspend-then-hibernate behaves. The examples target systemd 255, the version installed on this machine. Allow about fifteen minutes, plus a reboot or a later sleep test if you need to exercise the change.

You need a shell, the systemd package, and sudo access to edit /etc/systemd. Reading the current configuration is unprivileged. Writing a drop-in and testing an actual sleep transition require elevated privileges and can interrupt running work.

1. Check the installed version and the available kernel modes

Start with read-only checks. They prevent a common mistake: configuring a mode that the kernel does not offer on this machine.

$ systemctl --version | head -1
systemd 255 (255.4-1ubuntu8.17)
$ cat /sys/power/state
freeze mem disk
$ cat /sys/power/disk
[platform] shutdown reboot suspend test_resume

Your output can differ. The entries in /sys/power/state are candidates for SuspendState=; the entries in /sys/power/disk are candidates for HibernateMode=. These values come from the running kernel, not a portable systemd list. If disk is absent, do not configure hibernation and assume it will work.

Checkpoint: Keep the output somewhere you can compare after editing. Do not run a sleep command as part of this check.

2. Inspect the effective sleep configuration

systemd reads the main sleep configuration and then drop-ins. On this host, the compiled defaults are visible with:

$ systemd-analyze cat-config systemd/sleep.conf

Look for the [Sleep] section and any uncommented settings. The usual local path is /etc/systemd/sleep.conf.d/*.conf. Vendor files can live under /usr/lib/systemd or /usr/local/lib/systemd. Drop-ins have higher precedence than the main file, and files are sorted lexicographically across those directories: for a setting that accepts one value, the last matching entry wins.

That ordering is why a name such as 50-local.conf is easier to reason about than an unnumbered file. A package may add a later file, so inspect the combined output whenever a setting appears to be ignored.

3. Create a local drop-in

Choose one change for the first edit. This example asks systemd to prefer the kernel's freeze state when suspend is requested:

$ sudo install -d -m 0755 /etc/systemd/sleep.conf.d
$ sudoedit /etc/systemd/sleep.conf.d/50-local.conf

Put this in the editor:

[Sleep]
SuspendState=freeze

Save and exit, then inspect the result:

$ sudo systemd-analyze cat-config systemd/sleep.conf
...

The command should show 50-local.conf and the SuspendState=freeze entry. The ellipsis above means other host-specific lines, not literal text to type.

This changes the state written by systemd-suspend.service on a later suspend request. It does not itself suspend the machine, and it does not make freeze available if the kernel did not list it.

4. Use suspend-then-hibernate deliberately

suspend-then-hibernate first keeps the machine suspended in RAM and later hibernates it. With no battery, systemd uses HibernateDelaySec=, which defaults to two hours when it is unset. With a battery, systemd may use low-battery alarms or periodic checks instead. Setting a delay makes the time-based part explicit:

[Sleep]
HibernateDelaySec=45min
SuspendEstimationSec=60min

HibernateDelaySec= is used by systemd-suspend-then-hibernate.service. SuspendEstimationSec= is a fallback used to estimate battery discharge when the other detection methods are unavailable; it was added in systemd 253. These options do not force the machine to sleep, they only affect what happens after a suspend-then-hibernate request.

Warning: Do not choose a delay without considering wakeups. The service can wake the machine to check time or battery state, and hibernation can fail if the kernel, swap arrangement or firmware does not support it.

5. Disable a mode only when you mean to remove it

The Allow... switches control which modes systemd advertises when the mode is otherwise possible. For example, this removes direct hibernation from the advertised choices:

[Sleep]
AllowHibernation=no

There is a useful dependency to remember: AllowHibernation=no or AllowSuspend=no also disables suspend-then-hibernate and hybrid sleep, because both use suspend and hibernation internally. The specific switches AllowSuspendThenHibernate=yes and AllowHybridSleep=yes can override those implications. These switches were added in systemd 240.

Do not use this as a general troubleshooting step. It can remove options that desktop tools and other users expect to see. If you only need a different kernel state or hibernation mode, configure SuspendState= or HibernateMode= instead.

6. Verify without triggering sleep

After saving a change, read the effective configuration again:

$ systemd-analyze cat-config systemd/sleep.conf | less

Then compare every configured state with the files from step 1. For example, a valid local choice on this host is SuspendState=freeze, while HibernateMode=platform shutdown lists two values for systemd to try in order. If none of the configured values can be written by the kernel, the operation is aborted.

Warning: There is no generic dry-run that proves a full suspend or hibernation transition will succeed. A real test is service-disrupting and can lose unsaved work. Save work first, ensure you can physically or remotely recover the machine, and test only during a maintenance window. A setting that passes systemd-analyze cat-config can still fail later because of firmware, swap, drivers or power-management policy.

7. Undo the change

To return to the previous behaviour, remove or rename only the drop-in you created, then inspect the effective result again:

$ sudo mv /etc/systemd/sleep.conf.d/50-local.conf /etc/systemd/sleep.conf.d/50-local.conf.disabled
$ systemd-analyze cat-config systemd/sleep.conf

The file no longer ends in .conf, so systemd does not read it as a drop-in. This is a recoverable undo: move it back if you need the setting again. Do not delete a vendor file under /usr/lib to undo a package setting. If a vendor drop-in must be disabled, the documented mechanism is an administrator-owned symlink with the same filename to /dev/null under the corresponding /etc/systemd directory.

Done means