Difference between revisions of "Systemd/User"

From ArchWiki
Jump to: navigation, search
(Setup since systemd 206: added PAM workaround for 207)
(generalize, move to proper section)
 
(149 intermediate revisions by 46 users not shown)
Line 3: Line 3:
 
[[Category:Boot process]]
 
[[Category:Boot process]]
 
[[es:Systemd/User]]
 
[[es:Systemd/User]]
 +
[[fr:Systemd/utilisateur]]
 
[[it:Systemd/User]]
 
[[it:Systemd/User]]
{{Article summary start}}
+
[[ja:Systemd/ユーザー]]
{{Article summary text|Covers how to set up [[systemd]] user sessions.}}
+
[[ru:Systemd/User]]
{{Article summary heading|Related}}
+
[[zh-CN:Systemd/User]]
{{Article summary wiki|systemd}}
+
{{Related articles start}}
{{Article summary end}}
+
{{Related|systemd}}
 +
{{Related|Automatic login to virtual console}}
 +
{{Related|Start X at login}}
 +
{{Related articles end}}
  
 +
[[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.
  
[[systemd]] offers users the ability to run an instance of [[systemd]] to manage their session and services. This allows users to start, stop, enable, and disable units found within certain directories when systemd is run by the user. This is convenient for daemons and other services that are commonly run as a user other than root or a special user, such as [[mpd]].
+
== How it works ==
  
== Setup since systemd 206 ==
+
As per default configuration in {{ic|/etc/pam.d/system-login}}, the {{ic|pam_systemd}} module automatically launches a {{ic|systemd --user}} instance when the user logs in for the first time. 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. When [[#Automatic start-up of systemd user instances]] is enabled, the instance is started on boot and will not be killed. The systemd user instance is responsible for managing user services, which can be used to run daemons or automated tasks, with all the benefits of systemd, such as socket activation, timers, dependency system or strict process control via cgroups.
{{Note|User sessions are in development, have some missing features and are not yet supported upstream. See [[http://lists.freedesktop.org/archives/systemd-devel/2013-July/012392.html]] and [[http://lists.freedesktop.org/archives/systemd-devel/2013-August/012517.html]] for some details on the current state of affairs.}}
+
Since version 206, the mechanism for systemd user instances has changed. Now the {{ic|pam_systemd.so}} module launches a user instance by default on the first login of an user, by starting {{ic|user@.service}}. In its current state there are some differences with respect to previous systemd versions, that one must be aware of:
+
* The {{ic|systemd --user}} instance runs outside of any user session. This is ok for running, say {{ic|mpd}}, but may be annoying if one tries to start a window manager from the systemd user instance. Then polkit will prevent from mounting usb's, rebooting, etc. as an unprivileged user, because the window manager is running outside of the active session.
+
* The units in the user instance do not inherit any environment, so it must be set manually.
+
* {{ic|user-session@.service}} from {{AUR|user-session-units}} is obsolete now.
+
  
Steps to use user instance units:
+
Similarly to system units, user units are located in the following directories (ordered by ascending precedence):
1. Make sure the systemd user instance starts properly. You can check if it is there with {{bc|systemctl --user status}} Since systemd 206 there should be a systemd user instance running by default, which is started in the {{ic|pam_systemd.so}} pam module for the first login of a user.
+
 
{{Note|Since version 207, systemd uses a different PAM service for user@.service, and includes an incorrect default PAM config.
+
* {{ic|/usr/lib/systemd/user/}} where units provided by installed packages belong.
Fix it with: {{ic|# sed -i s/system-auth/system-login/g /etc/pam.d/systemd-user}} (or replace all occurrences of {{ic|system-auth}} in that file with {{ic|system-login}}).}}
+
* {{ic|~/.local/share/systemd/user/}} where units of packages that have been installed in the home directory belong.
2. Add the environment variables you need, in a drop in config file for {{ic|user@.service}}. At least it should contain the following
+
* {{ic|/etc/systemd/user/}} where system-wide user units are placed by the system administrator.
{{hc|/etc/systemd/system/user@.service.d/environment.conf|
+
* {{ic|~/.config/systemd/user/}} where the user puts its own units.
[Service]
+
 
Environment=DISPLAY=:0
+
When systemd user instance starts, it brings up the target {{ic|default.target}}. Other units can be controlled manually with {{ic|systemctl --user}}.
Environment=XDG_RUNTIME_DIR=/run/user/%I
+
 
Environment=SHELL=%s
+
{{Note|
 +
* 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 flux. 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.
 +
* {{ic|systemd --user}} runs as a separate process from the {{ic|systemd --system}} process. User units can not reference or depend on system units.
 
}}
 
}}
3. Put all your user units in {{ic|$HOME/.config/systemd/user}}. When the user instance starts, it launches the default target at {{ic|$HOME/.config/systemd/user/default.target}}. After that, you can manage your user units with {{ic|systemctl --user}}.
 
  
== Setup ==
+
== Basic setup ==
{{Out of date|After systemd 206, systemd --user mechanism has changed. (See [[https://bugs.freedesktop.org/show_bug.cgi?id=67471]], [[http://lists.freedesktop.org/archives/systemd-devel/2013-July/012392.html]], [[http://lists.freedesktop.org/archives/systemd-devel/2013-August/012517.html]]) }}
+
=== startx ===
+
  
{{Note|This step is unnecessary if you plan to use autologin.}}
+
All the user services will be placed in {{ic|~/.config/systemd/user/}}. If you want to run services on first login, execute {{ic|systemctl --user enable ''service''}} for any service you want to be autostarted.
  
Users should first set up systemd-logind to manage their session. If [[systemd]] is running as the system init daemon, then this is already happening.
+
=== D-Bus ===
  
Next, the user must launch systemd by putting the following in their {{ic|~/.xinitrc}}.
+
Some programs will need a [[D-Bus]] user message bus, and systemd is the manager of the user message bus.[https://www.archlinux.org/news/d-bus-now-launches-user-buses/] The ''dbus-daemon'' is started once per user for all sessions with the provided {{ic|dbus.socket}} and {{ic|dbus.service}} user units.
{{bc|/usr/lib/systemd/systemd --user}}
+
If the user is not launching the window manager through /usr/lib/systemd/systemd --user, then {{bc|/usr/lib/systemd/systemd --user &}} should be used and launched like anything else in {{ic|~/.xinitrc}}, before execing the window manager.
+
  
After starting X, the user can check whether their session is now being managed by systemd-logind with the following command:
+
{{Note|If you had previously created these units manually under {{ic|/etc/systemd/user/}} or {{ic|~/.config/systemd/user/}}, they can be removed.}}
  
{{bc|<nowiki>
+
=== Environment variables ===
$ loginctl --no-pager show-session $XDG_SESSION_ID | grep Active
+
</nowiki>}}
+
  
If this command prints {{ic|1=Active=yes}}, then the user is now using systemd-logind to manage their session. The user should remove any instances of '''ck-launch-session''' or '''dbus-launch''' from their {{ic|~/.xinitrc}}, as those commands are unneeded.
+
The user instance of systemd does not inherit any of the [[environment variables]] set in places like {{ic|.bashrc}} etc. There are several ways to set environment variables for the systemd user instance:
  
=== Display Managers ===
+
# For users with a {{ic|$HOME}} directory, use the {{ic|DefaultEnvironment}} option in {{ic|~/.config/systemd/user.conf}}. Affects only that user's user unit.
All of the major display managers are now using systemd-logind by default, so the {{ic|loginctl}} command from the previous section should work as stated. A user simply has to add {{ic|/usr/lib/systemd/systemd --user}} as a program to be started by their desktop environment.
+
# Use the {{ic|DefaultEnvironment}} option in {{ic|/etc/systemd/user.conf}} file. Affects all user units.
 +
# Add a drop-in config file in {{ic|/etc/systemd/system/user@.service.d/}}. Affects all user units; see [[#Service example]]
 +
# At any time, use {{ic|systemctl --user set-environment}} or {{ic|systemctl --user import-environment}}. Affects all user units started after setting the environment variables, but not the units that were already running.
 +
# Using the {{ic|dbus-update-activation-environment --systemd --all}} command provided by [[dbus]]. Has the same effect as {{ic|systemctl --user import-environment}}, but also affects the D-Bus session. You can add this to the end of your shell initialization file.
  
==== GNOME 3 (using GDM) ====
+
One variable you may want to set is {{ic|PATH}}.
For users who wish to have GDM/GNOME 3 auto-start their {{ic|/usr/lib/systemd/systemd --user}} session upon login, they just need to add a special log in session for this:
+
 
{{hc|/usr/share/xsessions/gnome-systemd.desktop|<nowiki>
+
==== Service example ====
[Desktop Entry]
+
Create the [[Systemd#Drop-in files|drop-in]] directory {{ic|/etc/systemd/system/user@.service.d/}} and inside create a file that has the extension {{ic|.conf}} (e.g. {{ic|local.conf}}):
Type=Application
+
{{hc|/etc/systemd/system/user@.service.d/local.conf|2=
Name=systemd
+
[Service]
Comment=Runs 'systemd' as a user instance.
+
Environment="PATH=/usr/lib/ccache/bin/:$PATH"
Exec=/usr/lib/systemd/systemd --user
+
Environment="EDITOR=nano -c"
 +
Environment="BROWSER=firefox"
 +
Environment="NO_AT_BRIDGE=1"
 +
}}
 +
 
 +
==== DISPLAY and XAUTHORITY ====
 +
 
 +
{{ic|DISPLAY}} is used by any X application to know which display to use and {{ic|XAUTHORITY}} to provide a path to the user's {{ic|.Xauthority}} file and thus the cookie needed to access the X server. If you plan on launching X applications from systemd units, these variables need to be set. Systemd provides a script in {{ic|/etc/X11/xinit/xinitrc.d/50-systemd-user.sh}} to import those variables into the systemd user session on X launch. [https://github.com/systemd/systemd/blob/v219/NEWS#L194] So unless you start X in a nonstandard way, user services should be aware of the {{ic|DISPLAY}} and {{ic|XAUTHORITY}}.
 +
 
 +
==== PATH ====
 +
 
 +
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:
 +
 
 +
{{hc|~/.bash_profile|<nowiki>
 +
systemctl --user import-environment PATH
 
</nowiki>}}
 
</nowiki>}}
  
Make sure to choose the {{ic|systemd}} session option at the GDM login screen.
+
==== pam_environment ====
{{Note|This has only been tested with a pure GDM and GNOME 3 setup. For other set ups, YYMV. This method does not need the systemd user-session scripts installed.}}
+
  
=== Using /usr/lib/systemd/systemd --user To Manage Your Session ===
+
Environment variables can be made available through use of the {{ic|pam_env.so}} module. Create the file {{ic|~/.pam_environment}}, for example:
  
Systemd has many amazing features, one of which is the ability to track programs using cgroups (by running {{ic|systemctl status}}). While awesome for a '''pid 1''' process to do, it is also extremely useful for users, and having it set up and initialize user programs, all the while tracking what is in each cgroup is even more amazing.
+
{{hc|~/.pam_environment|2=
 +
XDG_CONFIG_HOME DEFAULT=@{HOME}/.local/config
 +
XDG_DATA_HOME  DEFAULT=@{HOME}/.local/data
 +
}}
  
All of your systemd user units will go to {{ic|$HOME/.config/systemd/user}}. These units take precedence over units in other systemd unit directories.
+
For details about the syntax of the {{ic|.pam_environment}} file see [[Environment_variables#Using_pam_env]]. You can verify that the configuration was successful by running the command {{ic|systemctl --user show-environment}}:
  
There are two packages you need to get this working, both currently available from the [[AUR]]: {{AUR|systemd-xorg-launch-helper-git}} and optionally, {{AUR|systemd-user-session-units-git}} if you want to have autologin working.
+
{{hc|$ systemctl --user show-environment|2=
 +
...
 +
XDG_CONFIG_HOME=/home/''user''/.local/config
 +
XDG_DATA_HOME=/home/''user''/.local/data
 +
...
 +
}}
  
Next is setting up your targets. You should set up two, one for window manager and another as a default target. The window manager target should be populated like so:
+
=== Automatic start-up of systemd user instances ===
  
{{hc|$HOME/.config/systemd/user/wm.target|<nowiki>
+
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. Use the following command to enable lingering for specific user:
[Unit]
+
Description=Window manager target
+
Wants=xorg.target
+
Wants=mystuff.target
+
Requires=dbus.socket
+
AllowIsolate=true
+
  
[Install]
+
# loginctl enable-linger ''username''
Alias=default.target
+
</nowiki>}}
+
This will be the target for your graphical interface.
+
  
Put together a second target called {{ic|mystuff.target}}. All services but your window manager should contain a {{ic|WantedBy}} line, under {{ic|[Install]}}, pointing at this unit.
+
{{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]].}}
  
{{hc|$HOME/.config/systemd/user/mystuff.target|<nowiki>
+
== Xorg and systemd ==
[Unit]
+
Description=Xinitrc Stuff
+
Wants=wm.target
+
  
[Install]
+
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.
Alias=default.target
+
</nowiki>}}
+
  
Create a symbolic link from this unit to {{ic|default.target}}. When you start {{ic|/usr/lib/systemd/systemd --user}}, it will start this target.
+
=== Automatic login into Xorg without display manager ===
  
Next you need to begin writing services. First you should throw together a service for your window manager:
+
{{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? }}
  
{{hc|$HOME/.config/systemd/user/YOUR_WM.service|<nowiki>
+
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.
[Unit]
+
Description=your window manager service
+
Before=mystuff.target
+
After=xorg.target
+
Requires=xorg.target
+
  
[Service]
+
You need to have [[#D-Bus]] correctly set up and {{AUR|xlogin-git}} installed.
#Environment=PATH=uncomment:to:override:your:PATH
+
ExecStart=/full/path/to/wm/executable
+
Restart=always
+
RestartSec=10
+
+
[Install]
+
WantedBy=wm.target
+
</nowiki>}}
+
  
{{Note|The {{ic|[Install]}} section includes a 'WantedBy' part. When using {{ic|systemctl --user enable}} it will link this as {{ic|$HOME/.config/systemd/user/wm.target.wants/YOUR_WM.service}}, allowing it to be started at login. Is recommended enabling this service, not linking it manually.}}
+
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).
  
You can fill your user unit directory with a plethora of services, including ones for '''mpd''', '''gpg-agent''', '''offlineimap''', '''parcellite''', '''pulse''', '''tmux''', '''urxvtd''', '''xbindkeys''' and '''xmodmap''' to name a few.
+
The session will use its own dbus daemon, but various systemd utilities will automatically connect to the {{ic|dbus.service}} instance.
  
To exit your session, use {{ic|systemctl --user exit}}.
+
Finally, enable ('''as root''') the ''xlogin'' service for automatic login at boot:
  
===Auto-login===
+
# systemctl enable xlogin@''username''
  
If you want to have systemd automatically log you in on boot, then you can use the unit in user-session-units to do so. Enabling a screen locker for will stop someone from booting your computer into a nice, logged in session.
+
The user session lives entirely inside a systemd scope and everything in the user session should work just fine.
Add this line to {{ic|/etc/pam.d/login}} and {{ic|/etc/pam.d/system-auth}}:
+
{{bc|session   required    pam_systemd.so}}
+
  
Because {{ic|user-session@.service}} starts on tty1, you will need to add {{ic|1=Conflicts=getty@tty1.service}} to the service file, if it doesn't exist already. Alternately, you can have it run on tty7 instead by modifying {{ic|TTYPath}} accordingly as well as the {{ic|ExecStart}} line in {{ic|xorg.service}} ({{ic|cp /usr/lib/systemd/user/xorg.service /etc/systemd/user/}} and make the modifications there).
+
=== Xorg as a systemd user service ===
  
Once this is done, {{ic|systemctl --user enable}} {{ic|YOUR_WM.service}}
+
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.
  
{{Note|One must be careful with tty's to keep the systemd session active. Systemd sets a session as inactive when the active tty is different from the one that the login took place. This means that the X server must be run in the same tty as the login in {{ic|user-session@.service}}. If the tty in {{ic|TTYPath}} does not match the one xorg is launched in, the systemd session will be inactive from the point of view of your X applications, and you will not be able to mount USB drives, for instance.}}
+
{{Pkg|xorg-server}} provides integration with systemd in two ways:
 +
* 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]).
 +
* 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}}.
  
One of the most important things you can add to the service files you will be writing is the use of {{ic|1=Before=}} and {{ic|1=After=}} in the {{ic|[Unit]}} section. These two parts will determine the order things are started. Say you have a graphical application you want to start on boot, you would put {{ic|1=After=xorg.target}} into your unit. Say you start '''ncmpcpp''', which requires '''mpd''' to start, you can put {{ic|1=After=mpd.service}} into your ncmpcpp unit. You will eventually figure out exactly how this needs to go either from experience or from reading the systemd manual pages. Starting with [http://www.freedesktop.org/software/systemd/man/systemd.unit.html systemd.unit(5)] is a good idea.
+
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.
  
=== Other use cases ===
+
{{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.}}
  
==== Persistent terminal multiplexer ====
+
{{Warning|1=On xorg 1.18 socket activation seems to be broken. The client triggering the activation deadlocks. See the upstream bug report [https://bugs.freedesktop.org/show_bug.cgi?id=93072]. As a temporary workaround you can start the xorg server without socket activation, making sure the clients connect after a delay, so the server is fully started. There seems to be no nice mechanism te get startup notification for the X server.}}
  
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).
+
This is how to launch xorg from a user service:
  
To create this type of user session, procede as above, but instead of creating wm.target, create multiplexer.target:
+
1. Make xorg run with root privileges and for any user, by editing {{ic|/etc/X11/Xwrapper.config}}
  
{{bc|1=
+
{{hc|/etc/X11/Xwrapper.config|<nowiki>
[Unit]
+
allowed_users=anybody
Description=Terminal multiplexer
+
needs_root_rights=yes
Documentation=info:screen man:screen(1) man:tmux(1)
+
</nowiki>}}
After=cruft.target
+
Wants=cruft.target
+
  
[Install]
+
2. Add the following units to {{ic|~/.config/systemd/user}}
Alias=default.target
+
}}
+
  
{{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.
+
{{hc|~/.config/systemd/user/xorg@.socket|<nowiki>
 +
[Unit]
 +
Description=Socket for xorg at display %i
  
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.
+
[Socket]
 +
ListenStream=/tmp/.X11-unix/X%i
 +
</nowiki>}}
  
{{bc|1=
+
{{hc|~/.config/systemd/user/xorg@.service|<nowiki>
 
[Unit]
 
[Unit]
Description=tmux: A terminal multiplixer Documentation=man:tmux(1)
+
Description=Xorg server at display %i
After=gpg-agent.service
+
 
Wants=gpg-agent.service
+
Requires=xorg@%i.socket
 +
After=xorg@%i.socket
  
 
[Service]
 
[Service]
Type=forking
+
Type=simple
ExecStart=/usr/bin/tmux start
+
SuccessExitStatus=0 1
ExecStop=/usr/bin/tmux kill-server
+
Environment=DISPLAY=:0
+
EnvironmentFile=/tmp/gpg-agent-info
+
  
[Install]
+
ExecStart=/usr/bin/Xorg :%i -nolisten tcp -noreset -verbose 2 "vt${XDG_VTNR}"
WantedBy=multiplexer.target
+
</nowiki>}}
}}
+
  
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!
+
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
  
===== Starting X =====
+
$ systemctl --user set-environment XDG_VTNR=1
  
You have probably noticed that, since the terminal multiplexer is now {{ic|default.target}}, X will not start automatically at boot. To start X, proceed as above, but do not activate or manually link to {{ic|default.target}} {{ic|wm.target}}. Instead, assuming you are booting to a terminal, we will simply be using a hack-ish workaround and masking {{ic|/usr/bin/startx}} with a shell alias:
+
{{Note|xorg should be launched at the same virtual terminal where the user logged in. Otherwise logind will consider the session inactive.}}
  
{{bc|1=alias startx='systemctl --user start wm.target'}}
+
3. Make sure to configure the {{ic|DISPLAY}} environment variable as explained [[#DISPLAY_and_XAUTHORITY|above]].
 +
 
 +
4. Then, to enable socket activation for xorg on display 0 and tty 2 one would do:
 +
 
 +
$ systemctl --user set-environment XDG_VTNR=2    # So that xorg@.service knows which vt use
 +
$ systemctl --user start xorg@0.socket            # Start listening on the socket for display 0
 +
 
 +
Now running any X application will launch xorg on virtual terminal 2 automatically.
 +
 
 +
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}}.
 +
 
 +
{{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]}}
 +
 
 +
== Writing user units ==
  
== User Services ==
 
Users may now interact with units located in the following directories just as they would with system services (ordered by ascending precedence):
 
* {{ic|/usr/lib/systemd/user/}}
 
* {{ic|/etc/systemd/user/}}
 
* {{ic|~/.config/systemd/user/}}
 
To control the systemd instance, the user must use the command {{ic|systemctl --user}}.
 
=== Installed by packages ===
 
A unit installed by a package that is meant to be run by a [[systemd]] user instance should install the unit to {{ic|/usr/lib/systemd/user/}}. The system adminstration can then modify the unit by copying it to {{ic|/etc/systemd/user/}}. A user can then modify the unit by copying it to {{ic|~/.config/systemd/user/}}.
 
 
=== Example ===
 
=== Example ===
 +
 
The following is an example of a user version of the mpd service.
 
The following is an example of a user version of the mpd service.
{{hc|mpd.service|<nowiki>
+
{{hc|~/.config/systemd/user/mpd.service|<nowiki>
 
[Unit]
 
[Unit]
 
Description=Music Player Daemon
 
Description=Music Player Daemon
Line 212: Line 207:
 
WantedBy=default.target
 
WantedBy=default.target
 
</nowiki>}}
 
</nowiki>}}
 +
 
=== Example with variables ===
 
=== Example with variables ===
 +
 
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:
 
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:
{{hc|sickbeard.service|<nowiki>
+
 
 +
{{hc|~/.config/systemd/user/sickbeard.service|<nowiki>
 
[Unit]
 
[Unit]
 
Description=SickBeard Daemon
 
Description=SickBeard Daemon
Line 229: Line 227:
 
=== Note about X applications ===
 
=== Note about X applications ===
  
Most X apps need a {{ic|DISPLAY}} variable to run (so it's likely the first reason why your service files aren't starting), so you have to make sure to include it:
+
Most X apps need a {{ic|DISPLAY}} variable to run. See [[#DISPLAY and XAUTHORITY]] for how to this variable is set for the entire systemd user instance.
  
{{hc|$HOME/.config/systemd/user/parcellite.service|<nowiki>
+
=== Reading the journal ===
[Unit]
+
Description=Parcellite clipboard manager
+
  
[Service]
+
The journal for the user can be read using the analogous command:
ExecStart=/usr/bin/parcellite
+
 
Environment=DISPLAY=:0 # <= !
+
$ journalctl --user
 +
 
 +
To specify a unit, one can use
 +
 
 +
$ journalctl --user -u myunit.service
 +
 
 +
For a user unit, use
 +
 
 +
$ journalctl --user --user-unit myunit.service
 +
 
 +
Note that there seems to be some sort of bug that can sometimes stop output from user services from being properly attributed to their service unit.  Therefore, filtering by the {{ic|-u}} may unwittingly exclude some of the output from the service units.
 +
 
 +
== Some use cases ==
 +
 
 +
=== Persistent terminal multiplexer ===
 +
 
 +
{{Out of date|References {{ic|user-session@.service}} instead of {{ic|user@.service}}; the latter does not contain {{ic|1=Conflicts=getty@tty1.service}}.}}
 +
 
 +
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).
 +
 
 +
To create this type of user session, procede as above, but instead of creating wm.target, create multiplexer.target:
 +
 
 +
{{bc|1=
 +
[Unit]
 +
Description=Terminal multiplexer
 +
Documentation=info:screen man:screen(1) man:tmux(1)
 +
After=cruft.target
 +
Wants=cruft.target
  
 
[Install]
 
[Install]
WantedBy=mystuff.target
+
Alias=default.target
</nowiki>}}
+
}}
  
A simpler way, if using {{AUR|user-session-units}}, is to define it in {{ic|user-session@yourloginname.service}} so it's inherited. Add {{ic|1=Environment=DISPLAY=:0}} to the {{ic|[Service]}} section. Another helpful environment variable to set here is {{ic|SHELL}}.
+
{{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.
  
A cleaner way though, is to '''not''' hard code the DISPLAY environment variable (specially if you run more than on display):
+
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.
  
{{hc|$HOME/.config/systemd/user/x-app-template@.service|<nowiki>
+
{{bc|1=
 
[Unit]
 
[Unit]
Description=Your amazing and original description
+
Description=tmux: A terminal multiplixer
 +
Documentation=man:tmux(1)
 +
After=gpg-agent.service
 +
Wants=gpg-agent.service
  
 
[Service]
 
[Service]
ExecStart=/full/path/to/the/app
+
Type=forking
Environment=DISPLAY=%i # <= !
+
ExecStart=/usr/bin/tmux start
 +
ExecStop=/usr/bin/tmux kill-server
 +
Environment=DISPLAY=:0
 +
EnvironmentFile=/tmp/gpg-agent-info
  
 
[Install]
 
[Install]
WantedBy=mystuff.target
+
WantedBy=multiplexer.target
</nowiki>}}
+
}}
  
Then you can run it with:
+
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!
  
systemctl --user {start|enable} x-app@your-desired-display.service # <= :0 in most cases
+
=== Window manager ===
  
Some X apps may not start up because the display socket is not available yet. This can be fixed by adding something like
+
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:
  
{{hc|$HOME/.config/systemd/user/x-app-template@.service|<nowiki>
+
{{hc|~/.config/systemd/user/awesome.service|<nowiki>
 
[Unit]
 
[Unit]
 +
Description=Awesome window manager
 
After=xorg.target
 
After=xorg.target
 
Requires=xorg.target
 
Requires=xorg.target
  
...
+
[Service]
 +
ExecStart=/usr/bin/awesome
 +
Restart=always
 +
RestartSec=10
 +
 +
[Install]
 +
WantedBy=wm.target
 
</nowiki>}}
 
</nowiki>}}
  
to your units (the {{ic|xorg.target}} is part of {{AUR|xorg-launch-helper}}).
+
{{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.}}
 +
 
 +
== Kill user processes on logout ==
 +
 
 +
Arch Linux builds the {{pkg|systemd}} package with {{ic|--without-kill-user-processes}}, setting {{ic|1=KillUserProcesses}} to {{ic|no}} by default. This setting causes user processes not to be killed when the user completely logs out. To change this behavior in order to have all user processes killed on the user's logout, set {{ic|1=KillUserProcesses=yes}} in {{ic|/etc/systemd/logind.conf}}.
 +
 
 +
Note that changing this setting breaks terminal multiplexers such as [[tmux]] and [[screen]]. If you change this setting, you can still use a terminal multiplexer by using {{ic|systemd-run}} as follows:
 +
 
 +
$ systemd-run --scope --user ''command'' ''args''
 +
 
 +
For example, to run {{ic|screen}} you would do:
 +
 
 +
$ systemd-run --scope --user screen -S ''foo''
  
 
== See also ==
 
== See also ==
* [https://bitbucket.org/KaiSforza/systemd-user-units/wiki/Home KaiSforza's bitbucket wiki]
+
* [https://bitbucket.org/KaiSforza/systemd-user-units/wiki/Home KaiSforza's Bitbucket wiki]
* [https://github.com/zoqaeski/systemd-user-units Zoqaeski's units on Github]
+
* [https://github.com/zoqaeski/systemd-user-units Zoqaeski's units on GitHub]
* [https://github.com/grawity/systemd-user-units Collection of useful systemd user units]
+
* [https://bbs.archlinux.org/viewtopic.php?id=167115 Arch forum thread about changes in systemd 206 user instances]
* [https://bitbucket.org/KaiSforza/systemd-user-units More systemd user units]
+
* [https://bbs.archlinux.org/viewtopic.php?id=167115 Forum thread about changes in systemd 206 user instances]
+

Latest revision as of 15:03, 6 December 2016

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.

How it works

As per default configuration in /etc/pam.d/system-login, the pam_systemd module automatically launches a systemd --user instance when the user logs in for the first time. 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. When #Automatic start-up of systemd user instances is enabled, the instance is started on boot and will not be killed. The systemd user instance is responsible for managing user services, which can be used to run daemons or automated tasks, with all the benefits of systemd, such as socket activation, timers, dependency system or strict process control via cgroups.

Similarly to system units, user units are located in the following directories (ordered by ascending precedence):

  • /usr/lib/systemd/user/ where units provided by installed packages belong.
  • ~/.local/share/systemd/user/ where units of packages that have been installed in the home directory belong.
  • /etc/systemd/user/ where system-wide user units are placed by the system administrator.
  • ~/.config/systemd/user/ where the user puts its own units.

When systemd user instance starts, it brings up the target default.target. Other units can be controlled manually with systemctl --user.

Note:
  • Be aware that the 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 flux. See [1] and [2] for some hints on where things are going.
  • systemd --user runs as a separate process from the systemd --system process. User units can not reference or depend on system units.

Basic setup

All the user services will be placed in ~/.config/systemd/user/. If you want to run services on first login, execute systemctl --user enable service for any service you want to be autostarted.

D-Bus

Some programs will need a D-Bus user message bus, and systemd is the manager of the user message bus.[3] The dbus-daemon is started once per user for all sessions with the provided dbus.socket and dbus.service user units.

Note: If you had previously created these units manually under /etc/systemd/user/ or ~/.config/systemd/user/, they can be removed.

Environment variables

The user instance of systemd does not inherit any of the environment variables set in places like .bashrc etc. There are several ways to set environment variables for the systemd user instance:

  1. For users with a $HOME directory, use the DefaultEnvironment option in ~/.config/systemd/user.conf. Affects only that user's user unit.
  2. Use the DefaultEnvironment option in /etc/systemd/user.conf file. Affects all user units.
  3. Add a drop-in config file in /etc/systemd/system/user@.service.d/. Affects all user units; see #Service example
  4. At any time, use systemctl --user set-environment or systemctl --user import-environment. Affects all user units started after setting the environment variables, but not the units that were already running.
  5. Using the dbus-update-activation-environment --systemd --all command provided by dbus. Has the same effect as systemctl --user import-environment, but also affects the D-Bus session. You can add this to the end of your shell initialization file.

One variable you may want to set is PATH.

Service example

Create the drop-in directory /etc/systemd/system/user@.service.d/ and inside create a file that has the extension .conf (e.g. local.conf):

/etc/systemd/system/user@.service.d/local.conf
[Service]
Environment="PATH=/usr/lib/ccache/bin/:$PATH"
Environment="EDITOR=nano -c"
Environment="BROWSER=firefox"
Environment="NO_AT_BRIDGE=1"

DISPLAY and XAUTHORITY

DISPLAY is used by any X application to know which display to use and XAUTHORITY to provide a path to the user's .Xauthority file and thus the cookie needed to access the X server. If you plan on launching X applications from systemd units, these variables need to be set. Systemd provides a script in /etc/X11/xinit/xinitrc.d/50-systemd-user.sh to import those variables into the systemd user session on X launch. [4] So unless you start X in a nonstandard way, user services should be aware of the DISPLAY and XAUTHORITY.

PATH

If you customize your PATH and plan on launching applications that make use of it from systemd units, you should make sure the modified PATH is set on the systemd environment. Assuming you set your PATH in .bash_profile, the best way to make systemd aware of your modified PATH is by adding the following to .bash_profile after the PATH variable is set:

~/.bash_profile
systemctl --user import-environment PATH

pam_environment

Environment variables can be made available through use of the pam_env.so module. Create the file ~/.pam_environment, for example:

~/.pam_environment
XDG_CONFIG_HOME DEFAULT=@{HOME}/.local/config
XDG_DATA_HOME   DEFAULT=@{HOME}/.local/data

For details about the syntax of the .pam_environment file see Environment_variables#Using_pam_env. You can verify that the configuration was successful by running the command systemctl --user show-environment:

$ systemctl --user show-environment
...
XDG_CONFIG_HOME=/home/user/.local/config
XDG_DATA_HOME=/home/user/.local/data
...

Automatic start-up of systemd user instances

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. Use the following command to enable lingering for specific user:

# loginctl enable-linger username
Warning: systemd services are not sessions, they run outside of logind. Do not use lingering to enable automatic login as it will break the session.

Xorg and systemd

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.

Automatic login into Xorg without display manager

Tango-inaccurate.pngThe factual accuracy of this article or section is disputed.Tango-inaccurate.png

Reason: 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? (Discuss in Talk:Systemd/User#)

This option will launch a system unit that will start a user session with an xorg server and then run the usual ~/.xinitrc to launch the window manager, etc.

You need to have #D-Bus correctly set up and xlogin-gitAUR installed.

Set up your xinitrc from the skeleton, so that it will source the files in /etc/X11/xinit/xinitrc.d/. Running your ~/.xinitrc should not return, so either have wait as the last command, or add exec to the last command that will be called and which should not return (your window manager, for instance).

The session will use its own dbus daemon, but various systemd utilities will automatically connect to the dbus.service instance.

Finally, enable (as root) the xlogin service for automatic login at boot:

# systemctl enable xlogin@username

The user session lives entirely inside a systemd scope and everything in the user session should work just fine.

Xorg as a systemd user service

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.

xorg-server provides integration with systemd in two ways:

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.

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 logind's GetSessionByPID using its own pid as argument. See this thread and 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.
Warning: On xorg 1.18 socket activation seems to be broken. The client triggering the activation deadlocks. See the upstream bug report [5]. As a temporary workaround you can start the xorg server without socket activation, making sure the clients connect after a delay, so the server is fully started. There seems to be no nice mechanism te get startup notification for the X server.

This is how to launch xorg from a user service:

1. Make xorg run with root privileges and for any user, by editing /etc/X11/Xwrapper.config

/etc/X11/Xwrapper.config
allowed_users=anybody
needs_root_rights=yes

2. Add the following units to ~/.config/systemd/user

~/.config/systemd/user/xorg@.socket
[Unit]
Description=Socket for xorg at display %i

[Socket]
ListenStream=/tmp/.X11-unix/X%i
~/.config/systemd/user/xorg@.service
[Unit]
Description=Xorg server at display %i

Requires=xorg@%i.socket
After=xorg@%i.socket

[Service]
Type=simple
SuccessExitStatus=0 1

ExecStart=/usr/bin/Xorg :%i -nolisten tcp -noreset -verbose 2 "vt${XDG_VTNR}"

where ${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

$ systemctl --user set-environment XDG_VTNR=1
Note: xorg should be launched at the same virtual terminal where the user logged in. Otherwise logind will consider the session inactive.

3. Make sure to configure the DISPLAY environment variable as explained above.

4. Then, to enable socket activation for xorg on display 0 and tty 2 one would do:

$ systemctl --user set-environment XDG_VTNR=2     # So that xorg@.service knows which vt use
$ systemctl --user start xorg@0.socket            # Start listening on the socket for display 0

Now running any X application will launch xorg on virtual terminal 2 automatically.

The environment variable XDG_VTNR can be set in the systemd environment from .bash_profile, and then one could start any X application, including a window manager, as a systemd unit that depends on xorg@0.socket.

Warning: Currently running a window manager as a user service means it runs outside of a session with the problems this may bring: break the session. However, it seems that systemd developers intend to make something like this possible. See [6] and [7]

Writing user units

Example

The following is an example of a user version of the mpd service.

~/.config/systemd/user/mpd.service
[Unit]
Description=Music Player Daemon

[Service]
ExecStart=/usr/bin/mpd --no-daemon

[Install]
WantedBy=default.target

Example with variables

The following is an example of a user version of sickbeard.service, which takes into account variable home directories where SickBeard can find certain files:

~/.config/systemd/user/sickbeard.service
[Unit]
Description=SickBeard Daemon

[Service]
ExecStart=/usr/bin/env python2 /opt/sickbeard/SickBeard.py --config %h/.sickbeard/config.ini --datadir %h/.sickbeard

[Install]
WantedBy=default.target

As detailed in man systemd.unit, the %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.

Note about X applications

Most X apps need a DISPLAY variable to run. See #DISPLAY and XAUTHORITY for how to this variable is set for the entire systemd user instance.

Reading the journal

The journal for the user can be read using the analogous command:

$ journalctl --user

To specify a unit, one can use

$ journalctl --user -u myunit.service

For a user unit, use

$ journalctl --user --user-unit myunit.service

Note that there seems to be some sort of bug that can sometimes stop output from user services from being properly attributed to their service unit. Therefore, filtering by the -u may unwittingly exclude some of the output from the service units.

Some use cases

Persistent terminal multiplexer

Tango-view-refresh-red.pngThis article or section is out of date.Tango-view-refresh-red.png

Reason: References user-session@.service instead of user@.service; the latter does not contain Conflicts=getty@tty1.service. (Discuss in Talk:Systemd/User#)

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).

To create this type of user session, procede as above, but instead of creating wm.target, create multiplexer.target:

[Unit]
Description=Terminal multiplexer
Documentation=info:screen man:screen(1) man:tmux(1)
After=cruft.target
Wants=cruft.target

[Install]
Alias=default.target

cruft.target, like 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.

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 /tmp/gpg-agent-info. This sample session, when you start X, will also be able to run X programs, since DISPLAY is set.

[Unit]
Description=tmux: A terminal multiplixer 
Documentation=man:tmux(1)
After=gpg-agent.service
Wants=gpg-agent.service

[Service]
Type=forking
ExecStart=/usr/bin/tmux start
ExecStop=/usr/bin/tmux kill-server
Environment=DISPLAY=:0
EnvironmentFile=/tmp/gpg-agent-info

[Install]
WantedBy=multiplexer.target

Once this is done, systemctl --user enable tmux.service, multiplexer.target and any services you created to be run by cruft.target and you should be set to go! Activated user-session@.service as described above, but be sure to remove the Conflicts=getty@tty1.service from 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!

Window manager

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:

~/.config/systemd/user/awesome.service
[Unit]
Description=Awesome window manager
After=xorg.target
Requires=xorg.target

[Service]
ExecStart=/usr/bin/awesome
Restart=always
RestartSec=10
 
[Install]
WantedBy=wm.target
Note: The [Install] section includes a WantedBy part. When using systemctl --user enable it will link this as ~/.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.

Kill user processes on logout

Arch Linux builds the systemd package with --without-kill-user-processes, setting KillUserProcesses to no by default. This setting causes user processes not to be killed when the user completely logs out. To change this behavior in order to have all user processes killed on the user's logout, set KillUserProcesses=yes in /etc/systemd/logind.conf.

Note that changing this setting breaks terminal multiplexers such as tmux and screen. If you change this setting, you can still use a terminal multiplexer by using systemd-run as follows:

$ systemd-run --scope --user command args

For example, to run screen you would do:

$ systemd-run --scope --user screen -S foo

See also