Using systemd user units to react to sleep/suspend
Using systemd
to manage user-level services is great. There’s a few caveats though, and one of
them is that there’s no easy way to depend on system level units.
That’s because systemd --user
runs as a separate process from the systemd –system process. User
units can not reference or depend on system units or units of other users. [1]
While arguably safer, we could still benefit from the convenience that some units might bring to the
table, such as sleep.target
and suspend.target
. Those are the easiest way to run a service
before and after the computer slept.
There’s however, a clean way to proxy out these hooks from the system to the user instance. To do that, you will need to create a system unit that will trigger a user target:
/etc/systemd/system/[email protected]
[Unit]
Description=Call user's suspend target after system suspend
After=suspend.target
[Service]
Type=oneshot
ExecStart=/usr/bin/systemctl --user --machine=%i@ start --wait suspend.target
[Install]
WantedBy=suspend.target
Enable it by running sudo systemctl daemon-reload && sudo systemctl enable suspend@$(whoami)
Now we’ll create a new user target that activates all needed user services:
~/.config/systemd/user/suspend.target
[Unit]
Description=User level suspend target
StopWhenUnneeded=yes
Wants=alert-me.service
Wants=send-me-some-email.service
Notice that there’s already a few example service specification as dependency on Wants
. You can
declare as many as you want, as long as they’re user units.
Edit the services you need and make sure you run systemctl --user daemon-reload
after.
You will need to duplicate these files if you want to install it for sleep
as well. But that’s it,
from now on you are able to run user services on system sleep/suspend.