Writing a service that depends on Xorg

systemd

I'm trying to write a user level service for redshift, and it needs to wait until Xorg is up and running. My current service file looks like this:

[Unit]
Description=Redshift
After=graphical.target

[Service]
Environment=DISPLAY=:0
ExecStart=/bin/redshift -l 28:-13 -t 5300:3300 -b 0.80:0.91 -m randr
Restart=always

[Install]
WantedBy=default.target

However, it seems that it attempts to start before Xorg is up, and I have to manually start the service afterwards. I guess I'm using the wrong After= target. Any hints?

Best Answer

I've been researching this and grawity's answer seems out of date. You can now setup user services with systemd that run with as part of the user's session. They can have DISPLAY and XAUTHORITY set (currently in Arch, Debian Stretch+ and Ubuntu).

This makes sense over the previous recommendations of using desktop autostart files, as you get process management just like you would a system level app (restart, etc).

Best docs right now is the Arch wiki; Systemd/User

TLDR version;

  1. Create desired *.service file in ~/.config/systemd/user/
  2. Run systemctl --user enable [service] (exclude .service suffix)
  3. Optionally run systemctl --user start [service] to start now
  4. Use systemctl --user status [service] to check how it's doing

A couple other useful commands.

  • systemctl --user list-unit-files - view all user units
  • systemctl --user daemon-reload - if you edit a .service file

-- Later...

I upgraded and converted most of my session daemons to systemd .service files. So I can add a couple of additional notes.

There was no default hook to run the services at login, so you must trigger it yourself. I do it from my ~/.xsession file.

systemctl --user import-environment PATH DBUS_SESSION_BUS_ADDRESS
systemctl --no-block --user start xsession.target

The first line imports some environment variables into the systemd user session and the second kicks off the target. My xsession.target file;

[Unit]
Description=Xsession running
BindsTo=graphical-session.target

My xbindkeys.service as an example.

[Unit]
Description=xbindkeys
PartOf=graphical-session.target

[Service]
ExecStart=/usr/bin/xbindkeys -n -f ${HOME}/projects/dotfiles/.xbindkeysrc
Restart=always

[Install]
WantedBy=xsession.target