Screen Locking on Sleep

This page explains what you can do to have your screen locked when the machine goes to sleep (f.ex. when you close the laptop lid). It assumes that you do not want or can't use the mechanism provided by your desktop environment (KDE, Gnome) or by the lock program (xscreensaver). As an example screen lock program, the i3lock program is used below.

Note, that some examples below require you to specify the user that will be suspending the laptop. In other words - it is not a solution for multiuser laptops. You are welcome to update this page with solutions that work with multiuser laptops. [would User=$USER work?]

When running systemd (per-user sleep.target)

While systemd does not have a built-in sleep.target in the user scope, it is possible to emulate one with the help of D-Bus. Alternatively, you can try the example below that relies only on the global sleep.target.

First, create your personal, user-level sleep.target in $HOME/.config/systemd/user/sleep.target with the following contents:

[Unit]
Description=User level sleep target
StopWhenUnneeded=yes

Then, you need to create a watcher shell script watch_sleep.sh that monitors D-Bus for sleep events and invokes your newly minted sleep.target:

#!/bin/sh
dbus-monitor --system "type='signal',interface='org.freedesktop.login1.Manager',member=PrepareForSleep" \
| while read x; do
        case "$x" in
                *"boolean false"*)
                        systemctl --user --no-block stop sleep.target
                ;;
                *"boolean true"*)
                        systemctl --user --no-block start sleep.target
                ;;
    esac
done

Put this script at a convenient location and make sure it is executed as soon as you login with the help of yet another user service unit $HOME/.config/systemd/user/watch_sleep.service:

[Unit]
Description=watch for D-Bus sleep events

[Service]
ExecStart=/path/to/your/watch_sleep.sh
Restart=on-failure

[Install]
WantedBy=default.target

Now you can create additional user service units which are executed when the system is about to go to sleep. Screen locking can be achieved with a service such as $HOME/.config/systemd/user/i3lock.service:

[Unit]
Description=Run i3lock if the system goes to sleep
Before=sleep.target

[Service]
Type=forking
ExecStart=/usr/bin/i3lock

[Install]
WantedBy=sleep.target

When running systemd (global sleep.target)

Add a file /etc/systemd/system/i3lock.service with the following contents:

# source: https://bbs.archlinux.org/viewtopic.php?pid=1170536#p1170536 by 65kid
#
[Unit]
Description=i3lock
Before=sleep.target

[Service]
User=the_login_of_the_user_that_suspends
Type=forking
Environment=DISPLAY=:0
ExecStart=/usr/bin/i3lock

[Install]
WantedBy=sleep.target

Now enable the service from the command line as root with:

# systemctl enable i3lock.service

When running sysvinit

The following was working for me (TpO) on Debian wheezy under sysvinit, but stopped working on Debian jessie under systemd.

Add a file /etc/pm/sleep.d/01_screenlock with the following contents:

#!/bin/bash
#
# 01_screenlock: lock screen at suspend with i3lock
# based on http://bbs.archlinux.org/viewtopic.php?id=68158 by mokkurkalve
#

IS_ACTIVE="$( pidof i3lock )"

lock_screen() {
  # skip if i3lock is allready running
  if [ ! "$IS_ACTIVE" ]; then
       su - the_login_of_the_user_that_suspends -c "/bin/sh -c 'DISPLAY=:0.0 /usr/bin/i3lock'" &
  fi
}

case $1 in
   hibernate)
       lock_screen
       ;;
   suspend)
       lock_screen
       ;;
   thaw)
       # not required.
       ;;
   resume)
       # not required.
       ;;
   *) exit $NA
       ;;
esac