Based on various sources I have cobbled together ~/.config/systemd/user/screenlock.service
:
[Unit]
Description=Lock X session
Before=sleep.target
[Service]
Environment=DISPLAY=:0
ExecStart=/usr/bin/xautolock -locknow
[Install]
WantedBy=sleep.target
I've enabled it using systemctl --user enable screenlock.service
. But after rebooting, logging in, suspending and resuming (tested both with systemctl suspend
and by closing the lid) the screen is not locked and there is nothing in journalctl --user-unit screenlock.service
. What am I doing wrong?
Running DISPLAY=:0 /usr/bin/xautolock -locknow
locks the screen as expected.
$ systemctl --version
systemd 215
+PAM -AUDIT -SELINUX -IMA -SYSVINIT +LIBCRYPTSETUP +GCRYPT +ACL +XZ +SECCOMP -APPARMOR
$ awesome --version
awesome v3.5.5 (Kansas City Shuffle)
• Build: Apr 11 2014 09:36:33 for x86_64 by gcc version 4.8.2 (nobody@)
• Compiled against Lua 5.2.3 (running with Lua 5.2)
• D-Bus support: ✔
$ slim -v
slim version 1.3.6
If I run systemctl --user start screenlock.service
the screen locks immediately and I get a log message in journalctl --user-unit screenlock.service
, so ExecStart
clearly is correct.
xautolock -locker slock &
Creating a system service with the same file works (that is, slock
is active when resuming):
# ln -s "${HOME}/.config/systemd/user/screenlock.service" /usr/lib/systemd/system/screenlock.service
# systemctl enable screenlock.service
$ systemctl suspend
But I do not want to add a user-specific file outside $HOME
for several reasons:
- User services should be clearly separated from system services
- User services should be controlled without using superuser privileges
- Configuration should be easily version controlled
Best Answer
sleep.target
is specific to system services. The reason is,sleep.target
is not a magic target that automatically gets activated when going to sleep. It's just a regular target that puts the system to sleep – so the 'user' instances of course won't have an equivalent. (And unfortunately the 'user' instances currently have no way to depend on systemwide services.)(That, and there's the whole "hardcoding $DISPLAY" business. Every time you hardcode session parameters in an OS that's based on the heavily multi-user/multi-seat Unix, root kills a kitten.)
So there are two good ways to do this (I suggest the 2nd one):
Method 1
Create a system service (or a systemd-sleep(8) hook) that makes systemd-logind broadcast the "lock all sessions" signal when the system goes to sleep:
Then, within your X11 session (i.e. from ~/.xinitrc), run something that reacts to the signal:
(GNOME, Cinnamon, KDE,
Enlightenmentalready support this natively.)Method 2
Within your X11 session, run something that directly watches for the system going to sleep, e.g. by hooking into systemd-logind's "inhibitors".
The aforementioned xss-lock actually does exactly that, even without the explicit "lock all" signal, so it is enough to have it running:
It will run
slock
as soon as it sees systemd-logind preparing to suspend the computer.