https://wiki.archlinux.org/api.php?action=feedcontributions&user=Jagguli&feedformat=atomArchWiki - User contributions [en]2024-03-28T20:56:06ZUser contributionsMediaWiki 1.41.0https://wiki.archlinux.org/index.php?title=Systemd/User&diff=328944Systemd/User2014-08-06T00:04:53Z<p>Jagguli: /* Basic setup */</p>
<hr />
<div>{{Lowercase title}}<br />
[[Category:Daemons and system services]]<br />
[[Category:Boot process]]<br />
[[es:Systemd/User]]<br />
[[fr:Systemd/utilisateur]]<br />
[[it:Systemd/User]]<br />
[[ja:Systemd/User]]<br />
{{Related articles start}}<br />
{{Related|systemd}}<br />
{{Related|Automatic login to virtual console}}<br />
{{Related|Start X at Login}}<br />
{{Related articles end}}<br />
{{Poor writing|Explain from the basic to the specialized, not the other way around}}<br />
<br />
[[systemd]] offers users the ability to manage services under the user's control with a per-user systemd instance, enabling users to start, stop, enable, and disable their own units. This is convenient for daemons and other services that are commonly run for a single user, such as [[mpd]], or to perform automated tasks like fetching mail. With some caveats it is even possible to run xorg and the entire window manager from user services.<br />
<br />
== How it works ==<br />
<br />
On the first login of an user, systemd automatically launches a {{ic | systemd --user}} instance, responsible to manage user services. This process will survive as long as there is some session for that user, and will be killed as soon as the last session for the user is closed. By default no user services are run. user services can be used to run daemons or automated tasks, with all the benefits of systemd, like socket activation, timers, dependency system, strict process control via cgroups...<br />
<br />
User's units are located in the following directories just as they would with system services (ordered by ascending precedence):<br />
* {{ic|/usr/lib/systemd/user/}} where services provided by installed packages go.<br />
* {{ic|/etc/systemd/user/}} where system-wide user services are placed by the system administrator.<br />
* {{ic|~/.config/systemd/user/}} where the user puts its own services.<br />
<br />
When systemd user instance starts, it brings up the target {{ic|default.target}}. After that systemd's user instance can be controlled manually with {{ic|systemctl --user}}.<br />
<br />
{{Warning|Be aware that the {{ic| systemd --user}} instance is a per-user process, and not per-session. The rationale is that most resources handled by user services, like sockets or state files will be per-user (live on the user's home dir) and not per session. This means that all user services run outside of a session. As a consequence, programs that need to be run inside a session will probably break in user services. The way systemd handles user sessions is pretty much in flow. See [https://mail.gnome.org/archives/desktop-devel-list/2014-January/msg00079.html] and [http://lists.freedesktop.org/archives/systemd-devel/2014-March/017552.html] for some hints on where things are going.}}<br />
<br />
== Basic setup ==<br />
<br />
Systemd user instance should be started automatically on first login. To check that it is already running you can use {{ic|systemctl --user status}}.<br />
<br />
{{Note|If systemd user instance is not started automatically check the file {{ic|/etc/pam.d/system-login}}. It should contain a line similar to {{ic|-session optional pam_systemd.so}}. Also check if a ''.pacnew'' file exists.}}<br />
<br />
All the user services will be placed in {{ic|~/.config/systemd/user}}. If you want to run services on first login, create a directory {{ic|default.target.wants}}, and symlink any unit you want to be autostarted in there. This adds them as a Want dependency for the {{ic|default.target}}.<br />
<br />
{{Note|Since systemd 206, the mechanism for systemd user instances has changed. Now the {{ic|pam_systemd.so}} module launches a user instance by default. There is no need to launch it manually. {{ic|user-session@.service}} from {{AUR|user-session-units}} is obsolete now. With this change {{ic|systemd --user}} runs outside of a user session, with the consequences this entails.}}<br />
<br />
{{Note|Ensure that XDG_RUNTIME_DIR environment variable is set, else you may get ''Failed to get D-Bus connection: No such file or directory'' when running systemctl --user }}<br />
<br />
=== D-Bus ===<br />
<br />
Some programs, including systemd itself, will need a [[dbus]] user message bus. Traditionally this is started when launching a desktop environment via {{ic|dbus-launch}}. However if you are going to use the systemd user instance, it is very desirable to run the dbus server as a systemd service.<br />
<br />
{{Note|With the upcoming transition of systemd to kdbus, systemd will become the manager of system and user message buses anyway.}}<br />
<br />
To set this up, you need to:<br />
<br />
1. Add a service and socket units for the dbus server in {{ic|/etc/systemd/user/}}<br />
<br />
{{hc|/etc/systemd/user/dbus.socket|<nowiki><br />
[Unit]<br />
Description=D-Bus Message Bus Socket<br />
Before=sockets.target<br />
<br />
[Socket]<br />
ListenStream=%t/dbus/user_bus_socket<br />
<br />
[Install]<br />
WantedBy=default.target<br />
</nowiki>}}<br />
<br />
{{hc|/etc/systemd/user/dbus.service|<nowiki><br />
[Unit]<br />
Description=D-Bus Message Bus<br />
Requires=dbus.socket<br />
<br />
[Service]<br />
ExecStart=/usr/bin/dbus-daemon --session --address=systemd: --nofork --nopidfile --systemd-activation<br />
ExecReload=/usr/bin/dbus-send --print-reply --session --type=method_call --dest=org.freedesktop.DBus / org.freedesktop.DBus.ReloadConfig<br />
</nowiki>}}<br />
<br />
2. The environment variable {{ic|DBUS_SESSION_BUS_ADDRESS}} must be set. It can be done using a drop-in config file for {{ic|user@.service}}, by creating the following file:<br />
<br />
{{hc|/etc/systemd/system/user@.service.d/dbus.conf|<nowiki><br />
[Service]<br />
Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/%I/dbus/user_bus_socket<br />
</nowiki>}}<br />
<br />
{{Note|Before systemd 209 {{ic|DBUS_SESSION_BUS_ADDRESS}} was set in upstream's {{ic|user@.service}} unit, but not anymore. The reason seems to be that once the transition to kdbus is done, this variable will be set by {{ic|pam_systemd.so}}. }}<br />
<br />
3. Activate the socket for all users by running as root:<br />
<br />
# systemctl --global enable dbus.socket<br />
<br />
=== Environment variables ===<br />
<br />
The user instance of systemd does not inherit any of the [[environment variables]] set in places like {{ic|.bashrc}}, etc. There are two ways te set environment variables for the systemd instance:<br />
<br />
1. Add a drop-in config file in {{ic|/etc/systemd/system/user@.service.d}} as it was done for D-Bus. This makes the variable available for the entire lifetime of the systemd user instance.<br />
<br />
2. At any time, use {{ic|systemctl --user set-environment}} or {{ic|systemctl --user import-environment}}. All units started after that command will get the updated environment variables, but not the units that were already running.<br />
<br />
Some variables you probably may want to set are {{ic|DISPLAY}} or {{ic|PATH}}.<br />
<br />
==== DISPLAY ====<br />
<br />
Display is used by any X application to know which display to use. If you plan on launching X applications from systemd units, you need to set this variable, using the following drop-in config:<br />
<br />
{{hc|/etc/systemd/system/user@.service.d/display.conf|<nowiki><br />
[Service]<br />
Environment=DISPLAY=:0<br />
</nowiki>}}<br />
<br />
This hard-codes {{ic|DISPLAY}} to {{ic|:0}} which is the usual choice when running a single X server.<br />
<br />
{{Note|It is better to set {{ic|DISPLAY}} using a drop-in config file since this way it is available from the beginning. If {{ic|DISPLAY}} is set later, {{ic|dbus.service}} will most probably not get it, and right now (until kdbus arrives) the dbus-daemon is responsible for launching dbus activated services, and those would never see the {{ic|DISPLAY}} variable.}}<br />
<br />
==== PATH ====<br />
<br />
As any other environment variable you set in {{ic|.bashrc}} or {{ic|.bash_profile}}, the {{ic|PATH}} variable is not available to systemd. If you customize your {{ic|PATH}} and plan on launching applications that make use of it from systemd units, you should make sure the modified {{ic|PATH}} is set on the systemd environment. Assuming you set your {{ic|PATH}} in {{ic|.bash_profile}}, the best way to make systemd aware of your modified {{ic|PATH}} is by adding the following to {{ic|.bash_profile}} after the {{ic|PATH}} variable is set:<br />
<br />
{{hc|~/.bash_profile|<nowiki><br />
systemctl --user import-environment PATH<br />
</nowiki>}}<br />
<br />
==== Other variables ====<br />
<br />
If you need other environment variables to be accessible from systemd services, you can set them from {{ic|.bashrc}} or {{ic|.bash_profile}}, or even a systemd service, using any of the following commands:<br />
<br />
$ systemctl --user set-environment VARIABLE=value # Set VARIABLE to value<br />
$ systemctl --user import-environment VARIABLE # Import VARIABLE from the calling environment<br />
$ systemctl --user import-environment # Import all variables from the calling environment<br />
<br />
=== Automatic start-up of systemd user instances ===<br />
<br />
The systemd user instance is started after the first login of a user and killed after the last session of the user is closed. Sometimes it may be useful to start it right after boot, and keep the systemd user instance running after the last session closes, for instance to have some user process running without any open session. Lingering is used to that effect.<br />
<br />
{{Warning|systemd services are '''not''' sessions, they run outside of ''logind''. Do not use lingering to enable automatic login as it will [[General troubleshooting#Session permissions|break the session]].}}<br />
<br />
Use the following command to enable lingering for specific user:<br />
<br />
# loginctl enable-linger ''username''<br />
<br />
== Xorg and systemd ==<br />
<br />
There are several ways to run xorg within systemd units. Below there are two options, either by starting a new user session with an xorg process, or by launching xorg from a systemd user service.<br />
<br />
=== Automatic login into Xorg without display manager ===<br />
<br />
{{Accuracy|This setup ends up with two user D-Bus buses, one for the desktop, and an other for systemd. Why can't we use the systemd one alone? }}<br />
<br />
This option will launch a system unit that will start a user session with an xorg server and then run the usual {{ic|~/.xinitrc}} to launch the window manager, etc.<br />
<br />
You need to have [[#D-Bus]] correctly set up and {{AUR|xlogin-git}} installed.<br />
<br />
Set up your [[xinitrc]] from the skeleton, so that it will source the files in {{ic|/etc/X11/xinit/xinitrc.d/}}. Running your {{ic|~/.xinitrc}} should not return, so either have {{ic|wait}} as the last command, or add {{ic|exec}} to the last command that will be called and which should not return (your window manager, for instance).<br />
<br />
The session will use its own dbus daemon, but various systemd utilities need the {{ic|dbus.service}} instance. Possible solution to this is to create aliases for such commands:<br />
<br />
{{hc|~/.bashrc|<nowiki><br />
for sd_cmd in systemctl systemd-analyze systemd-run; do<br />
alias $sd_cmd='DBUS_SESSION_BUS_ADDRESS="unix:path=$XDG_RUNTIME_DIR/dbus/user_bus_socket" '$sd_cmd<br />
done<br />
</nowiki>}}<br />
<br />
Finally, enable ('''as root''') the ''xlogin'' service for automatic login at boot:<br />
<br />
# systemctl enable xlogin@''username''<br />
<br />
The user session lives entirely inside a systemd scope and everything in the user session should work just fine.<br />
<br />
=== Xorg as a systemd user service ===<br />
<br />
Alternatively, [[xorg]] can be run from within a systemd user service. This is nice since other X-related units can be made to depend on xorg, etc, but on the other hand, it has some drawbacks explained below.<br />
<br />
Since version 1.16 {{Pkg|xorg-server}} provides better integration with systemd in two ways:<br />
* Can be run unprivileged, delegating device management to logind (see Hans de Goede commits around [http://cgit.freedesktop.org/xorg/xserver/commit/?id=82863656ec449644cd34a86388ba40f36cea11e9 this commit]).<br />
* Can be made into a socket activated service (see [http://cgit.freedesktop.org/xorg/xserver/commit/?id=b3d3ffd19937827bcbdb833a628f9b1814a6e189 this commit]). This removes the need for {{AUR|systemd-xorg-launch-helper-git}}.<br />
<br />
Unfortunately, to be able to run xorg in unprivileged mode, it needs to run inside a session. So, right now the handicap of running xorg as user service is that it must be run with root privileges (like before 1.16), and can't take advantage of the unprivileged mode introduced in 1.16.<br />
<br />
{{Note|This is not a fundamental restriction imposed by logind, but the reason seems to be that xorg needs to know which session to take over, and right now it gets this information calling [http://www.freedesktop.org/wiki/Software/systemd/logind logind]'s {{ic|GetSessionByPID}} using its own pid as argument. See [http://lists.x.org/archives/xorg-devel/2014-February/040476.html this thread] and [http://cgit.freedesktop.org/xorg/xserver/tree/hw/xfree86/os-support/linux/systemd-logind.c xorg sources]. It seems likely that xorg could be modified to get the session from the tty it is attaching to, and then it could run unprivileged from a user service outside a session.}}<br />
<br />
This is how to launch xorg from a user service:<br />
<br />
1. Make xorg run with root privileges and for any user, by editing {{ic|/etc/X11/Xwrapper.config}} <br />
<br />
{{hc|/etc/X11/Xwrapper.config|<nowiki><br />
allowed_users=anybody<br />
needs_root_rights=yes<br />
</nowiki>}}<br />
<br />
2. Add the following units to {{ic|~/.config/systemd/user}}<br />
<br />
{{hc|~/.config/systemd/user/xorg@.socket|<nowiki><br />
[Unit]<br />
Description=Socket for xorg at display %i<br />
<br />
[Socket]<br />
ListenStream=/tmp/.X11-unix/X%i<br />
</nowiki>}}<br />
<br />
{{hc|~/.config/systemd/user/xorg@.service|<nowiki><br />
[Unit]<br />
Description=Xorg server at display %i<br />
<br />
Requires=xorg@%i.socket<br />
After=xorg@%i.socket<br />
<br />
[Service]<br />
Type=simple<br />
SuccessExitStatus=0 1<br />
<br />
ExecStart=/usr/bin/Xorg :%i -nolisten tcp -noreset -verbose 2 "vt${XDG_VTNR}"<br />
</nowiki>}}<br />
<br />
where {{ic|${XDG_VTNR} }} is the virtual terminal where xorg will be launched, either hard-coded in the service unit, or set in the systemd environment with<br />
<br />
$ systemctl --user set-environment XDG_VTNR=1<br />
<br />
{{Note|xorg should be launched at the same virtual terminal where the user logged in. Otherwise logind will consider the session inactive.}}<br />
<br />
3. Make sure to configure the {{ic|DISPLAY}} environment variable as explained [[#DISPLAY|above]].<br />
<br />
4. Then, to enable socket activation for xorg on display 0 and tty 2 one would do:<br />
<br />
$ systemctl --user set-environment XDG_VTNR=2 # So that xorg@.service knows which vt use<br />
$ systemctl --user start xorg@0.socket # Start listening on the socket for display 0<br />
<br />
Now running any X application will launch xorg on virtual terminal 2 automatically.<br />
<br />
The environment variable {{ic|XDG_VTNR}} can be set in the systemd environment from {{ic|.bash_profile}}, and then one could start any X application, including a window manager, as a systemd unit that depends on {{ic|xorg@0.socket}}.<br />
<br />
{{Warning|Currently running a window manager as a user service means it runs outside of a session with the problems this may bring: [[General troubleshooting#Session permissions|break the session]]. However, it seems that systemd developers intend to make something like this possible. See [https://mail.gnome.org/archives/desktop-devel-list/2014-January/msg00079.html] and [http://lists.freedesktop.org/archives/systemd-devel/2014-March/017552.html]}}<br />
<br />
== Writing user units ==<br />
<br />
=== Example ===<br />
<br />
The following is an example of a user version of the mpd service.<br />
{{hc|~/.config/systemd/user/mpd.service|<nowiki><br />
[Unit]<br />
Description=Music Player Daemon<br />
<br />
[Service]<br />
ExecStart=/usr/bin/mpd --no-daemon<br />
<br />
[Install]<br />
WantedBy=default.target<br />
</nowiki>}}<br />
<br />
=== Example with variables ===<br />
<br />
The following is an example of a user version of {{ic|sickbeard.service}}, which takes into account variable home directories where SickBeard can find certain files:<br />
<br />
{{hc|~/.config/systemd/user/sickbeard.service|<nowiki><br />
[Unit]<br />
Description=SickBeard Daemon<br />
<br />
[Service]<br />
ExecStart=/usr/bin/env python2 /opt/sickbeard/SickBeard.py --config %h/.sickbeard/config.ini --datadir %h/.sickbeard<br />
<br />
[Install]<br />
WantedBy=default.target<br />
</nowiki>}}<br />
<br />
As detailed in {{ic|man systemd.unit}}, the {{ic|%h}} variable is replaced by the home directory of the user running the service. There are other variables that can be taken into account in the [[systemd]] manpages.<br />
<br />
=== Note about X applications ===<br />
<br />
Most X apps need a {{ic|DISPLAY}} variable to run (so it's likely the first reason why your service files aren't starting). See [[#DISPLAY]] for how to set this variable for the entire systemd user instance. Alternatively, you could set this variable for a single unit as follows:<br />
<br />
{{hc|~/.config/systemd/user/parcellite.service|2=<br />
[Unit]<br />
Description=Parcellite clipboard manager<br />
<br />
[Service]<br />
ExecStart=/usr/bin/parcellite<br />
'''Environment=DISPLAY=:0'''<br />
<br />
[Install]<br />
WantedBy=mystuff.target<br />
}}<br />
<br />
== Some use cases ==<br />
<br />
=== Persistent terminal multiplexer ===<br />
<br />
{{Out of date|References {{ic|user-session@.service}} instead of {{ic|user@.service}}; the latter does not contain {{ic|1=Conflicts=getty@tty1.service}}.}}<br />
<br />
You may wish your user session to default to running a terminal multiplexer, such as [[GNU Screen]] or [[Tmux]], in the background rather than logging you into a window manager session. Separating login from X login is most likely only useful for those who boot to a TTY instead of to a display manager (in which case you can simply bundle everything you start in with myStuff.target). <br />
<br />
To create this type of user session, procede as above, but instead of creating wm.target, create multiplexer.target:<br />
<br />
{{bc|1=<br />
[Unit]<br />
Description=Terminal multiplexer<br />
Documentation=info:screen man:screen(1) man:tmux(1)<br />
After=cruft.target<br />
Wants=cruft.target<br />
<br />
[Install]<br />
Alias=default.target<br />
}}<br />
<br />
{{ic|cruft.target}}, like {{ic|mystuff.target}} above, should start anything you think should run before tmux or screen starts (or which you want started at boot regardless of timing), such as a GnuPG daemon session.<br />
<br />
You then need to create a service for your multiplexer session. Here is a sample service, using tmux as an example and sourcing a gpg-agent session which wrote its information to {{ic|/tmp/gpg-agent-info}}. This sample session, when you start X, will also be able to run X programs, since DISPLAY is set.<br />
<br />
{{bc|1=<br />
[Unit]<br />
Description=tmux: A terminal multiplixer Documentation=man:tmux(1)<br />
After=gpg-agent.service<br />
Wants=gpg-agent.service<br />
<br />
[Service]<br />
Type=forking<br />
ExecStart=/usr/bin/tmux start<br />
ExecStop=/usr/bin/tmux kill-server<br />
Environment=DISPLAY=:0<br />
EnvironmentFile=/tmp/gpg-agent-info<br />
<br />
[Install]<br />
WantedBy=multiplexer.target<br />
}}<br />
<br />
Once this is done, {{ic|systemctl --user enable}} {{ic|tmux.service}}, {{ic|multiplexer.target}} and any services you created to be run by {{ic|cruft.target}} and you should be set to go! Activated {{ic|user-session@.service}} as described above, but be sure to remove the {{ic|1=Conflicts=getty@tty1.service}} from {{ic|user-session@.service}}, since your user session will not be taking over a TTY. Congratulations! You have a running terminal multiplexer and some other useful programs ready to start at boot!<br />
<br />
=== Window manager ===<br />
<br />
To run a window manager as a systemd service, you first need to run [[#Xorg as a systemd user service]]. In the following we will use awesome as an example:<br />
<br />
{{hc|~/.config/systemd/user/awesome.service|<nowiki><br />
[Unit]<br />
Description=Awesome window manager<br />
After=xorg.target<br />
Requires=xorg.target<br />
<br />
[Service]<br />
ExecStart=/usr/bin/awesome<br />
Restart=always<br />
RestartSec=10<br />
<br />
[Install]<br />
WantedBy=wm.target<br />
</nowiki>}}<br />
<br />
{{Note|The {{ic|[Install]}} section includes a {{ic|WantedBy}} part. When using {{ic|systemctl --user enable}} it will link this as {{ic|~/.config/systemd/user/wm.target.wants/''window_manager''.service}}, allowing it to be started at login. Is recommended to enable this service, not to link it manually.}}<br />
<br />
== See also ==<br />
* [https://bitbucket.org/KaiSforza/systemd-user-units/wiki/Home KaiSforza's Bitbucket wiki]<br />
* [https://github.com/zoqaeski/systemd-user-units Zoqaeski's units on GitHub]<br />
* [https://github.com/grawity/systemd-user-units Collection of useful systemd user units]<br />
* [https://bitbucket.org/KaiSforza/systemd-user-units More systemd user units]<br />
* [https://bbs.archlinux.org/viewtopic.php?id=167115 Arch forum thread about changes in systemd 206 user instances]</div>Jagguli