Skip to content

Systemd integration

Caleb Bassi edited this page May 16, 2019 · 15 revisions

Managing user applications with systemd

On systemd based Linux distributions, systemd can be used as an alternative way to start and manage user services and applications. Some general examples of services managed by systemd include gpg-agent, pulseaudio, dbus, etc, but in the case of sway, such services may also include waybar, swayidle, mako, and similar. Note that this method works for both X11 and Wayland programs.

In order to integrate sway with systemd and start user applications automatically when sway starts, we need to configure a sway session target that will also bind to the standard graphical-session.target user target. This allows services to be started by systemd after sway launches by specifying WantedBy=sway-session.target or WantedBy=graphical-session.target in the application's systemd unit file.

To configure the sway session target, place the following systemd unit file either locally at ~/.config/systemd/user/sway-session.target, or globally for all users at /etc/systemd/user/sway-session.target:

[Unit]
Description=sway compositor session
Documentation=man:systemd.special(7)
BindsTo=graphical-session.target
Wants=graphical-session-pre.target
After=graphical-session-pre.target

In order for the unit file to work properly, add the following lines to either /etc/sway/config.d/10-systemd which will include it in the default config, or add them to the end of the user's config file:

exec "systemctl --user import-environment; systemctl --user start sway-session.target"

This imports all of sway's environment variables into the systemd user manager, allowing its services to access these variables (for example the D-Bus session address), and then starts the sway session user target.

Note that the systemctl commands must be run synchronously and can't be split into two exec statements, since otherwise the session target may be started before systemctl import-environment is complete, and services that require certain variables will fail to run.

To walkthrough the stages of how this works:

  • The user logs in via sddm or getty and the systemd user manager is automatically started (by pam_systemd and logind).
  • When sway is run, it will import the environment variables into the systemd user manager and start the sway session target.
  • The systemd user manager will then start all the services that depend on that target, and will provide them access to the imported env variables.

Running sway itself as a --user service

Place the following unit file either at ~/.config/systemd/user/sway.service or /etc/systemd/user/sway.service:

[Unit]
Description=sway - SirCmpwn's Wayland window manager
Documentation=man:sway(5)
BindsTo=graphical-session.target
Wants=graphical-session-pre.target
After=graphical-session-pre.target

[Service]
Type=simple
EnvironmentFile=-%h/.config/sway/env
ExecStart=/usr/bin/sway
Restart=on-failure
RestartSec=1
TimeoutStopSec=10

This service file will load environment variables from ~/.config/sway/env, a KEY=VALUE file. That's a good place to put variables such as _JAVA_AWT_WM_NONREPARENTING=1 or CLUTTER_BACKEND=wayland (note: no need for export there, that is not a shell file).

Now, you want your login manager to start the service via systemd, and not sway directly. In order to do that, it's easiest to just create a new wayland session in /usr/share/wayland-sessions/sway-session.desktop:

[Desktop Entry]
Name=Sway Service
Comment=SirCmpwn's Wayland window manager as a systemd service
Exec=sway-service.sh
Type=Application

and put the sway-service.sh somewhere on your PATH (/usr/local/bin/sway-service.sh should be fine):

#! /bin/sh

# first import environment variables from the login manager
systemctl --user import-environment
# then start the service
exec systemctl --wait --user start sway.service

Next time you login via gdm/sddm just choose "sway-service", instead of just "sway".

Example service units for other programs

Waybar

Starts Waybar as part of the sway session and stops it when graphical-session.target stops:

# ~/.config/systemd/user/waybar.service or /etc/systemd/user/waybar.service
[Unit]
Description=Highly customizable Wayland bar for Sway and Wlroots based compositors.
Documentation=https://github.com/Alexays/Waybar/wiki/
PartOf=graphical-session.target

[Service]
Type=simple
ExecStart=/usr/bin/waybar

[Install]
WantedBy=sway-session.target

Enable and start the service with systemctl --user enable --now waybar.

If you want Waybar to start for any graphical session, you could replace the WantedBy= directive with WantedBy=graphical-session.target before enabling it (although it might not make sense to use Waybar with gnome or i3).

swayidle

[Unit]
Description=Idle manager for Wayland
Documentation=man:swayidle(1)
PartOf=graphical-session.target

[Service]
Type=simple
ExecStart=/usr/bin/swayidle -w \
            timeout 300 'swaylock -f -c 000000' \
            timeout 600 'swaymsg "output * dpms off"' \
                resume 'swaymsg "output * dpms on"' \
            before-sleep 'swaylock -f -c 000000'

[Install]
WantedBy=sway-session.target

mako

[Unit]
Description=A lightweight Wayland notification daemon
Documentation=man:mako(1)
PartOf=graphical-session.target

[Service]
Type=simple
ExecStart=/usr/bin/mako

[Install]
WantedBy=sway-session.target
You can’t perform that action at this time.