This blog is an abbreviated version of my day today… The TL;DR would be: systemctl --user is uber frustrating so just use the system config and get over yourself.


If you read the TL;DR above, then you’d guess correctly that I wasted a lot of time today setting up a user space systemd config for my PC. It failed, or I failed. I gave up on it because it refused to work as I might expect and was harder than it needed to be.

Why was the user space configuration harder than the system config? Probably just because it’s relatively new. I fully expect it to get better in the future; I will be disappointed if it doesn’t. That doesn’t answer the question though. The user and system systemd processes have mutually exclusive load paths and know nothing about the other’s units. There doesn’t seem to be a read-only way for the user to depend on system level units like network-online.target, graphical.target or multi-user.target.

I was close to getting a config working without those despite all that. I wrote a few "oneshot" services that served as the boolean checks for running services and then set up the dependencies from there. For some reason there were endless problems over and over.

Eventually I gave up. A cleaned out the user space config and retuned the units I had made for the system level systemd process. In a short while I had my PC starting up with the config I had wanted to have running in the user space. A short while after that I was able to disable the dumb autostart.sh that I was launching from my Awesome WM config file. There were tons of other problems with the autostart.sh script like duplicate processes when restarting awesome so I was happy to be able to disable that script.

The main quirky thing about the config was that I found it more reliable to acquire XAUTHORITY when I set a timer to trigger the service. Even if the timer is set to trigger after 0.1 seconds it seems to work much smoother.

So with that in mind I created two targets to uses as umbrella’s for my custom configured services. The idea is to make it easy to set up maintain this type of thing on a few different boxes. One target, csand.target, is for non-X units and the other, csand-graphical.target, is for programs that need XAUTHORITY.

The non-X services should have Install sections and can be directly enabled to start. The X services need to have a timer and should not have an Install section. The timer should be enabled to start the service at boot. All of the service units that require X will contain the line:

Environment="DISPLAY=:0" "XAUTHORITY=/home/csand/.Xauthority"

Also, be careful with services that exit right away. They need a few additional properties in the service unit file, namely, Type=oneshot and RemainAfterExit=yes.

If you forget the "Type" option then systemd will keep calling the start command thinking that the service is failing over and over. It may stop after a while but there are some events that will trigger the process over and over. Be careful to avoid these infinite loops as it can really bog things down.

Normally a oneshot process stays in an inactive state; when triggered it returns success and then goes back to inactive. When using a timer to trigger a "oneshot" service then you need to tell systemd to consider the service active even though it doesn’t have any remaining processes otherwise it will be restarted over and over again.

One last tip. If the service has a command that should be used to stop the service instead of sending SIGHUP then set the ExecStop= property in the service file.

At some point, when it has matured a little bit and perhaps has become more stable, I want to outline my config in deeper detail to show how the dependencies were all set up.

Until then, happy systemd-ing!!

" "