From Fedora Project Wiki

m (Use the new scriptlets page location to avoid a redirect.)
 
(118 intermediate revisions by 7 users not shown)
Line 1: Line 1:
= Fedora systemd Services =
= Fedora systemd Services =
This document describes the guidelines for systemd services, for use and inclusion in Fedora packages.  
This document describes the guidelines for systemd services, for use and inclusion in Fedora packages.


= Unit Files =
== Definitions ==
The systemd equivalent for an SysV initscript is called a Unit file. Each package that contains software that wants/needs to start a service at boot must have a systemd unit file.


{{admon/note|SysV Initscripts|Packages may also provide a SysV initscript file, but are not required to do so. This format is considered legacy, but Fedora still contains init mechanisms such as upstart which do not support the systemd unit file format. The guidelines for SysV initscripts can be found here: [[Packaging:SysVInitScript]]}}
Since systemd includes some concepts which are extensions of previous concepts, the following definitions may be useful:


== Naming ==
<b>Service</b>: A process or task executed and controlled by the init system (e.g. systemd).<BR>
Unit files have a naming scheme of foobar.service. When considering what basename to use, keep the following advice in mind:
<b>Traditional Service</b>: A service which is explicitly started or stopped, either by the init system at boot or manually by a superuser.  In systemd, one of several types of service controlled by a <code>.service</code> file.<BR>
<b>Activated service</b>: A service that is not (or not necessarily) started explicitly by the user but start when certain other events happen or certain state becomes true.<BR>
<b>Socket-activated Service</b>: A service which is waiting for traffic across a socket before activating. In systemd, controlled by a <code>.socket</code> file.<BR>
<b>D-Bus service</b>: A service which activates in response to a message from the D-Bus system bus.<BR>
<b>Unit file</b>: The systemd equivalent of a SysV initscript.<BR>


* Unit files must be named after the software implementation that they support, as opposed to the generic type of software. So, a good name would be "apache-httpd.service", and a bad name would be "httpd.service", as there are multiple httpd implementations, but only one Apache httpd.
== Unit Files ==
Each package that contains software that wants/needs to start a traditional
service at boot <b>MUST</b> have a systemd unit file.


* If the package also includes a SysV initscript, it must have the same base name as the systemd unit file. For example, if the unit file is /lib/systemd/system/foobar.service, then the SysV initscript must be /etc/rc.d/init.d/foobar. If systemd cannot find a native unit file by a specified name it will attempt to fall back to the SysV file with the same specified name.  
Ideally, systemd unit files are reusable across distributions and shipped with
the upstream packages. Please consider working with upstream to integrate the
systemd files you prepare in the upstream sources. Information for developers
on how to integrate systemd support best with their build system you may find
on http://0pointer.de/public/systemd-man/daemon.html


It is our intention to unify service names of well-known software across distributions, so that we can eventually ship the service files in the upstream packages. Hence it is a good idea to discuss service names with maintainers of the same packages in other distributions and agree on a common name.
{{admon/note|Migrating from SysV Initscripts with non-standard service commands|Packages which have SysV initscripts that contain 'non-standard service commands' (commands besides start, stop, reload, force-reload, status, restart, or try-restart) must convert those commands into standalone helper scripts. Systemd does not support non-standard unit commands.}}


== Format ==
=== Naming ===
Every .service file must begin with a [Unit] section:
 
Unit files for traditional services have a naming scheme of foobar.service. When considering what basename to use, keep in mind that we'd like to use the same service names for software across distributions. We'd also like to ship the <code>.service</code> files in the upstream packages. These desires create a few guides for naming a unit file:
 
* Follow upstream if they're already distributing a <code>.service</code> file and it's not likely to conflict with other packages.
* Look at packages in other distros or talk with the maintainers of those packages and upstream to try to come up with a common name.
* Unit files should be named after the software implementation that they support as opposed to the generic type of software. So, a good name would be <code>apache-httpd.service</code> and bad names would be <code>httpd.service</code> or <code>apache.service</code> as there are multiple httpd implementations and multiple projects produced by the apache foundation.
 
For backwards compatibility you may also want to create a symlink from an older, name to the new name. In the above example, for instance, Fedora has always used <code>httpd</code> for the service. When creating the new <code>apache-httpd.service</code> file, also create a symlink named <code>httpd.service</code> that points at <code>apache-httpd.service</code>. Then end users that are used to using <code>service httpd</code> will have it continue to work.
 
=== Basic format ===
 
{{admon/note|Case Sensitivity|All fields in a unit file are case sensitive.}}
 
==== [Unit] ====
Every <code>.service</code> file must begin with a <code>[Unit]</code> section:


<pre>
<pre>
[Unit]
[Unit]
Description=A brief human readable string describing the service (not the service file!)
Description=A brief human readable string describing the service (not the .service file!)
After=syslog.target
Documentation=man:foo.service(8) man:foo.conf(5) http://www.foo.org/docs/
</pre>
</pre>


The Description= line must not exceed 80 characters, and must describe the service, and not the service file. For example, "Apache Web Server" is a good description, but "Starts and Stops the Apache Web Server" is a bad one.  
The <code>Description=</code> line must not exceed 80 characters, and must describe the service, and not the <code>.service</code> file. For example, "Apache Web Server" is a good description, but "Starts and Stops the Apache Web Server" is a bad one.
 
===== Documentation field =====


The After= line is only necessary if the service can log to syslog (most can, so if in doubt, include it).  
Systemd in Fedora 17+ has support for defining documentation in unit files via the Documentation= field (it is ignored in older releases, so it is safe to keep one systemd unit file across all branches). System administrators will be looking at the contents of the Documentation= field to determine what the service is, how to configure it, and where to locate additional documentation relating to the service. Accordingly, packagers are strongly encouraged to include any available sources in the Documentation= field which provide this information. If a man page or info page is present in the package, refer to it using "man:manpage" or "info:infofile" respectively. If the documentation is in plaintext, use "​file://path/to/file". Lastly, if no local documentation exists in the package, but it exists at a url, use the URL (with ​http://) in this field. Multiple URIs can be added to the Documentation= field, as a space separated list. For details on URI definitions and formatting, please refer to the uri(7) manpage (man uri).


Next, the .service file must have a [Service] section:
==== [Service] ====
Next, the <code>.service</code> file must have a <code>[Service]</code> section:


<pre>
<pre>
Line 38: Line 64:
</pre>
</pre>


The Type= setting is very important. For D-Bus services this should be "dbus", for traditional services "forking" is usually a good idea, for services not offering any interfaces to other services "simple" is best. For "one-short" scripts "oneshot" is ideal, often combined with RemainAfterExit=. See http://0pointer.de/public/systemd-man/systemd.service.html for further discussion on the topic. Since "simple" is the default type, .service files which would normally set Type=simple may simply omit the Type line altogether.
The <code>Type=</code> setting is very important. For D-Bus services this
should be "dbus", for traditional services "forking" is usually a good idea,
for services not offering any interfaces to other services "simple" is best.
For "one-shot" scripts "oneshot" is ideal, often combined with
<code>RemainAfterExit=</code>. See
http://0pointer.de/public/systemd-man/systemd.service.html for further
discussion on the topic. Since "simple" is the default type,
<code>.service</code> files which would normally set <code>Type=simple</code> may simply
omit the <code>Type</code> line altogether.


BusName= should be set for all services connecting to D-Bus. (i.e. it is a must for those where Type=dbus, but might make sense otherwise, too) Omit this option if your service does not take a name on the bus.
<code>BusName=</code> should be set for all services connecting to D-Bus. (i.e. it is a must for those where <code>Type=dbus</code>, but might make sense otherwise, too) Omit this option if your service does not take a name on the bus.


ExecStart= is necessary for all services. This line defines the string that you would run to start the service daemon, along with any necessary options.
<code>ExecStart=</code> is necessary for all services. This line defines the string that you would run to start the daemon, along with any necessary options.


ExecReload= should be specified for all services supporting reload. It is highly recommended to add code here that synchronously reloads the configuration file here (i.e. /bin/kill -HUP $MAINPID is usually a poor choice, due to its asynchronous nature). Omit this option if your service does not support reloading.
<code>ExecReload=</code> should be specified for all services supporting reload. It is highly recommended to add code here that synchronously reloads the configuration file here (i.e. <code>/bin/kill -HUP $MAINPID</code> is usually a poor choice, due to its asynchronous nature). Omit this option if your service does not support reloading.


Finally, the .service file must have an [Install] section:
 
==== [Install] ====
Finally, the <code>.service</code> file should have an <code>[Install]</code> section:


<pre>
<pre>
Line 53: Line 89:
</pre>
</pre>


The recommended parameters for WantedBy are either multi-user.target (for most system services) or graphical.target (for services related to the UI).
The recommended parameters for <code>WantedBy=</code> are either <code>graphical.target</code> (services related to the graphical user interface) or <code>multi-user.target</code> (for everything else).  When the user (or our scriptlets) invoke <code>systemctl enable</code> the service will be set to start in these targets.


For more information regarding these options see http://0pointer.de/public/systemd-man/systemd.unit.html and http://0pointer.de/public/systemd-man/systemd.service.html
For more information regarding these options see http://0pointer.de/public/systemd-man/systemd.unit.html and http://0pointer.de/public/systemd-man/systemd.service.html


Strictly speaking ExecStart= (in the [Service] section) is the only option really necessary for a .service file. However, in Fedora you must add the other options mentioned here (as applicable).
=== EnvironmentFiles and support for /etc/sysconfig files ===


== Support for /etc/sysconfig files ==
The <code>EnvironmentFiles=</code> line in the <code>[Service]</code> section of <code>.service</code> files is used to support loading environment variables that can be used in unit files.  For instance, if your sysv-initscript used a file in /etc/sysconfig to set command line options, you can use <code>EnvironmentFiles=</code> like so:
If your service supports /etc/sysconfig files, then you must use EnvironmentFile=/etc/sysconfig/foobar in your .service file, in the [Service] section.


Example:
Example:
Line 66: Line 101:
[Service]
[Service]
Type=forking
Type=forking
EnvironmentFile=/etc/sysconfig/httpd
EnvironmentFile=-/etc/sysconfig/httpd
ExecStart=/usr/sbin/httpd ${OPTIONS}
ExecStart=/usr/sbin/httpd $OPTIONS
ExecReload=/usr/sbin/httpd ${OPTIONS} -k restart
ExecReload=/usr/sbin/httpd $OPTIONS -k restart
</pre>
</pre>


You may then refer to variables set in sysconfig files with ${FOOBAR} and $FOOBAR, in the ExecStart= lines (and related lines). (${FOOBAR} expands the variable into one word, $FOOBAR splits up the variable value at whitespace into multiple words)  
You may then refer to variables set in the <code>/etc/sysconfig/httpd</code> file with
<code>${FOOBAR}</code> and <code>$FOOBAR</code>, in the <code>ExecStart=</code>
lines (and related lines). (<code>${FOOBAR}</code> expands the variable into
one word, <code>$FOOBAR</code> splits up the variable value at whitespace into
multiple words)


== Options to avoid ==
The "-" on the <code>EnvironmentFile=</code> line ensures that no error messages is generated if the environment file does not exist. Since many of these files were optional in sysvinit, you should include the "-" when using this directive.
For most services, we do not want to use requirement dependencies such as Requires= or Wants=. Instead exclusively use ordering dependencies: Before= and After=. This is used to implement loose coupling: if two services are started at the same time their startup is properly ordered, but do not make it strictly necessary to run one if the other is started.


If you use a requirement dependency, use Wants= rather than Requires=, to make things a little bit more robust. If you use a requirement dependency in almost all cases you should also add an ordering dependency, as ordering and requirement dependencies are orthogonal in systemd.
=== Fields to avoid ===
For most services, we do not want to use requirement dependencies in the
<code>[Unit]</code> section, such as <code>Requires=</code> or
<code>Wants=</code>. Instead exclusively use ordering dependencies: <code>Before=</code> and
<code>After=</code>. This is used to implement loose coupling: if someone asks two services
to start at the same time, systemd will properly order their startup but not
make it strictly necessary to run one if the other is started.
 
If you use a requirement dependency, use <code>Wants=</code> rather than
<code>Requires=</code>, to make things a little bit more robust. If you use a
requirement dependency in almost all cases you should also add an ordering
dependency, as ordering and requirement dependencies are orthogonal in systemd.


Here's an example of this common case:
Here's an example of this common case:
Line 84: Line 133:
# Since only <code>After</code> was used, the web application may be temporarily unable to serve some requests but it does not need to restart in order to serve pages after the database comes back up.
# Since only <code>After</code> was used, the web application may be temporarily unable to serve some requests but it does not need to restart in order to serve pages after the database comes back up.


Avoid referring to runlevelX.target units in all lines taking unit names (such as WantedBy), these are legacy names existing for compatibility with SysV only.
Avoid referring to <code>runlevelX.target</code> units in all lines taking unit names (such as <code>WantedBy</code>), these are legacy names existing for compatibility with SysV only.


Avoid Names=. Usually it is a better idea to symlink an additional name in the file system. Note that a name listed in Names= is only useful when a service file is already loaded. However, systemd loads only the service files actually referred to in another loaded service, and uses the filenames during the search. Hence a name in Names= is not useful as a search key, but a symlink in the file system is. Also do not put a (redundant) Names=foobar.service line into a file called foobar.service. We want to keep our service files short.
Avoid <code>Names=</code> (in the <code>[Unit]</code> section). Usually it is a
better idea to symlink an additional name in the file system. Note that a name
listed in <code>Names=</code> is only useful when a service file is already loaded. However,
systemd loads only the service files actually referred to in another loaded
service, and uses the filenames during the search. Hence a name in <code>Names=</code> is
not useful as a search key, but a symlink in the file system is. Also do not
put a (redundant) <code>Names=foobar.service</code> line into a file called <code>foobar.service</code>.
We want to keep our service files short.


Avoid using StandardOutput=kmsg. Use StandardOutput=syslog instead. (same for StandardError=).
Unit files should avoid using <code>StandardOutput=</code> or <code>StandardError=</code>. The default is the right choice for almost all cases, and using the default allows users to change global defaults in /etc/systemd/system.conf.


== Example Unit file ==
=== Example Unit file ===
This is an example systemd unit .service file for ABRT:
This is an example systemd unit <code>.service</code> file for ABRT:


<pre>
<pre>
[Unit]
[Unit]
Description=ABRT Automated Bug Reporting Tool
Description=ABRT Automated Bug Reporting Tool
After=syslog.target


[Service]
[Service]
Line 107: Line 162:
</pre>
</pre>


== Bus Activation ==
== Activation ==
In order to allow parallel startup of a D-Bus service and its consumers it is essential that D-Bus services can be bus activated, and that the D-Bus activation is forwarded to systemd so that you end up with a single service instance only. That means all existing D-Bus services that have previously not been started via bus activation but have been started via SysV scripts should be updated to be capable of bus activation. This is easily implemented by dropping a D-Bus .service file in /usr/share/dbus/system-services/ which uses the SystemdService= directive to redirect activation to systemd. See the D-Bus documentation for more information. (Don't be confused by the fact that both systemd and D-Bus use the .service file suffix, they are different things, though the D-Bus .service often refers to the systemd .service file for the same program with the SystemdService= directive.)
Systemd allows for three forms of activated services: [[#Hardware activation]], [[#Socket activation]], and [[#DBus activation]].
 
=== Hardware activation ===
Hardware activation occurs when a service is installed but only turns on if a certain type of hardware is installed.  Enabling of the service is normally done with a udev rule.  At this time we do not have further guidance on how to write those udev rules.  The service itself installs its <code>.service</code> files in the normal places and are installed by the normal [[Packaging:ScriptletSnippets#Systemd | systemd scriptlets]].  These services should never be enabled by the package as they will be enabled by udev.
 
=== Socket activation ===
Socket activation occurs when a service allows systemd to listen for
connections to a specific socket and, when systemd receives a connection on
that socket, it starts the service.  To do this, the upstream source needs to
have some minor coding work to let systemd listen for connections on the socket
and there needs to be a <code>.socket</code> file in
<code>%{_lib}/systemd/system/</code> that tells systemd to listen to that
socket and what to start when a connection is received.  This is similar in
function to inetd and some, but not all, services coded to work with inetd will
work with socket activation.
 
{{admon/note||
Currently we do not have guidance on how to write socket files as this is something that needs upstream code and they can add a proper <code>.socket</code> file at the same time.}}
 
However, socket activation can also be used to allow parallel startup of services.  If a service supports systemd socket activation as described above and we additionally start it explicitly on boot, then systemd will start it but allow things that depend on it to startup at the same time.  If the dependent service makes a request to the socket activatable service before it has come up, then systemd will cause the request to wait until the socket activatable service has come up and can process the request.  To achieve this effect, the service must be socket activatable as described above, the <code>.service</code> file for the service needs to have a <code>Wants=</code> line for the <code>.socket</code>, and the service must autostart.
 
Note that certain socket activated services (notably network listening ones) require FESCo approval - see [[Packaging:DefaultServices]] for details.  Once you have permission, you can package the <code>.socket</code> file and use the systemd scriptlets that enable the service by default.  You need to also check the <code>.service</code> file to make sure it has a <code>Wants=</code> entry on the <code>.socket</code> file as that ensures that starting the service will also inform systemd of the socket.
 
=== Timer activation ===
 
All packages with timed execution which already depend on systemd (for example
because they contain systemd units) must use timer units instead of cron jobs,
with no dependency or requirements on a crontab.
 
Packages which do not already depend or require systemd must not use timer units
but instead depend and have requirement on crontabs, to avoid introducing
unnecessary new dependencies on systemd directly.
 
=== DBus activation ===
In order to allow parallel startup of a D-Bus service and its consumers it is essential that D-Bus services can be bus activated and the D-Bus activation request is forwarded from the D-Bus system bus to systemd so that you end up with only a single instance of the service, even if a service is triggered by both boot-up and activation. If historically your D-Bus service was not bus-activated but started via a SysV init script, it should be updated to use bus activation. This may be implemented by dropping a D-Bus <code>.service</code> file in <code>/usr/share/dbus-1/system-services/</code> and use the <code>SystemdService=</code> directive therein to redirect the activation to systemd.
 
{{admon/note|.service|systemd and D-Bus both use the <code>.service</code> file
suffix but they are different things. In a systemd driven init process, the
D-Bus <code>.service</code> file will often refer to the systemd <code>.service</code> file for the same
program with the <code>SystemdService</code> directive.}}
 
Here's an example for a D-Bus bus-activable service. The ConsoleKit bus activation file /usr/share/dbus-1/system-services/org.freedesktop.ConsoleKit.service:
 
<pre>
[D-BUS Service]
Name=org.freedesktop.ConsoleKit
Exec=/usr/sbin/console-kit-daemon --no-daemon
User=root
SystemdService=console-kit-daemon.service
</pre>
 
And the matching systemd unit file /lib/systemd/system/console-kit-daemon.service:
 
<pre>
[Unit]
Description=Console Manager
 
[Service]
Type=dbus
BusName=org.freedesktop.ConsoleKit
ExecStart=/usr/sbin/console-kit-daemon --no-daemon
</pre>
 
As you can see <code>SystemdService=</code> is used in the D-Bus activation file to bind the systemd service to the D-Bus service.
 
Traditionally, bus activated D-Bus services could not be disabled without
uninstalling them entirely. systemd allows you to disable services by making
D-Bus invoke an alias systemd service name (that can be created or removed to
enable/disable activation) as an intermediary for the real service.


Note that traditionally bus activated services could not be disabled. systemd does not change this, however in some cases where making it possible to disable a service is desirable (e.g. avahi, NetworkManager), you can easily implement that by directing the D-Bus service to a symlinked alias name of the real service file which is controlled via systemctl enable/disable and which then points to the real service. Example: set SystemdService=dbus-org.freedesktop.Avahi.service instead of SystemdService=avahi-daemon.service, and then make /etc/systemd/system/dbus-org.freedesktop.Avahi.service a symlink → /lib/systemd/system/avahi-daemon.service. A full example for the Avahi case:
You can easily implement disabling by directing the D-Bus service to an alias
name of the real service file (in the filesystem this shows up as a symlink
placed in /etc/systemd/system to the real service file). This alias is then
controlled via "systemctl enable" and "systemctl disable". It is a good idea
(though technically not necessary) to name this alias name after the D-Bus bus
name of the service, prefixed with "dbus-". Example for Avahi, a service that
the admin might need to disable: set
<code>SystemdService=dbus-org.freedesktop.Avahi.service</code> instead of
<code>SystemdService=avahi-daemon.service</code> in the D-Bus activation file, and then make
<code>dbus-org.freedesktop.Avahi.service</code> an optional alias of avahi-daemon.service
that can be controlled via the <code>Alias=</code> directive in the <code>[Install]</code> section of the
systemd service file. This directive is then read by "systemctl enable" and
"systemctl disable" to create resp. remove a symlink to make the service
available resp. unavailable under this additional name. A full example for the
Avahi case:


Here is the D-Bus .service file for Avahi (/usr/share/dbus-1/system-services/org.freedesktop.Avahi.service):
Here is the D-Bus .service file for Avahi (/usr/share/dbus-1/system-services/org.freedesktop.Avahi.service):
Line 123: Line 260:
</pre>
</pre>


Here is the Avahi systemd unit .service file (/lib/systemd/system/avahi-daemon.service):
Here is the Avahi systemd unit <code>.service</code> file (/lib/systemd/system/avahi-daemon.service):


<pre>
<pre>
Line 129: Line 266:
Description=Avahi mDNS/DNS-SD Stack
Description=Avahi mDNS/DNS-SD Stack
Requires=avahi-daemon.socket
Requires=avahi-daemon.socket
After=syslog.target


[Service]
[Service]
Line 144: Line 280:
</pre>
</pre>


The Alias= line ensures that the existance of the /etc/systemd/system/dbus-org.freedesktop.Avahi.service symlink can be controlled by "systemctl enable" and "systemctl disable".
The <code>Alias=</code> line ensures that the existance of the /etc/systemd/system/dbus-org.freedesktop.Avahi.service symlink can be controlled by "systemctl enable" and "systemctl disable".
 
Note that the creation/removal of the alias symlinks should be done with "systemctl enable" and "systemctl disable" only. You should not create these symlinks manually.


In general, it is also recommended to supply native systemd units for all services that are already bus activatable, so that these services can be controlled and supervised centrally like any other service with tools such as systemctl. A similar logic like the one shown above should apply.
In general, it is also recommended to supply native systemd units for all services that are already bus activatable, so that these services can be controlled and supervised centrally like any other service with tools such as systemctl. A similar logic like the one shown above should apply.


= Packaging =
See the D-Bus documentation for more information about bus activation: http://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-starting-services
 
== Automatic restarting ==
If you package a long-running service, please consider enabling systemd's automatic restart feature for it, to improve reliability by making sure the system automatically attempts recovering a failing daemon. Please use
<pre>
[Service]
...
Restart=on-failure
</pre>
or
<pre>
[Service]
...
Restart=on-abnormal
</pre>
in your unit's <code>.service</code> file for this.
 
The former will tell systemd to restart the daemon as soon as it fails regardless of the precise reason. It's a good choice for most long-running services. Some daemons require a way to escape constant restarting by exiting with any non-zero exit code. For those services use <code>Restart=on-abnormal</code>, which will still restart the daemon when it fails "abnormally", on unclean signal, core dump, timeout or watchdog exits, but not on unclean exit codes. It is recommended to to enable automatic restarts for all long-running services, but which setting is the right one, and whether it is useful at all depends on the specific service. Please consult the <code>systemd.service(5)</code> man page for more information on the various settings.
 
== Private devices and networking ==
 
If you package a long-running system service, please consider enabling systemd's <code>PrivateDevices=</code> and <code>PrivateNetwork=</code> settings for it, in order to improve security and minimize the attack surface.
 
When <code>PrivateDevices=yes</code> is set in the [Service] section of a systemd service unit file, the processes run for the service will run in a private file system namespace where /dev is replaced by a minimal version that only includes the device nodes /dev/null, /dev/zero, /dev/full, /dev/urandom, /dev/random, /dev/tty as well as the submounts /dev/shm, /dev/pts, /dev/mqueue, /dev/hugepages, and the /dev/stdout, /dev/stderr, /dev/stdin symlinks. No device nodes for physical devices will be included, however. Furthermore, the CAP_MKNOD capability is removed. Finally, the "devices" cgroup controller is used to ensure that no access to device nodes except the listed ones is possible. This is an efficient way to take away physical device access for services, thus minimizing the attack surface.
 
When <code>PrivateNetwork=yes</code> is set in the [Service] section of a systemd service unit file, the processes run for the service will run in a private network namespace whith a private loopback network interface, and no other network devices. Network communication between host and service can not be initiated. This is an efficient way to take away network access for services, thus minimizing the attack surface.


== Filesystem locations ==
By default both switches default to "no".
Packages with systemd unit files '''must''' put them into %{_unitdir}. %{_unitdir} evaluates to /lib/systemd/system/ on all Fedora systems. Unit files are architecture independent (hence, not %{_lib}) and needed early in the boot process.


== %files section ==
Note that <code>PrivateDevices=yes</code> should not be used for:
Systemd unit .service files must not be marked as %config files. Any configuration should be made available through /etc/sysconfig/<service> rather than in the init script itself.
Init scripts must have 0755 permissions.


== Unit files in spec file scriptlets ==
* Services that actually require physical device access
* Services which may be used to execute arbitrary user or administrator supplied programs (such as cron, ...). We shouldn't limit what people can do with these services.
* This option creates a new file system namespace where mount/umount propagation is turned off back into the host. This means that mounts made by the service will stay private to the service. Thus this option should not be used by services which shall be able to establish mounts in the host.


Most systemd services must be disabled by default, especially if they listen on the network. Also, a package must never turn on a service on upgrade if it was explicitly disabled.
Note that <code>PrivateNetwork=yes</code> should not be used for:
Fedora provides a set of scriptlets to simplify handling the setup of systemd services at package install/upgrade/removal.


<pre>
* Services that actually require network access (with the exception of daemons only needing socket activation)
Requires(post): systemd-units
* Services which may be used to execute arbitrary user or administrator supplied programs. (see above)
Requires(preun): systemd-units
* Services which might need to resolve non-system user and group names. Since on some setups resolving non-system users might require network access to an LDAP or NIS server, enabling this option on might break resolving of these user names. Note however that system users/groups are always resolvable even without network access. Hence it is safe to enable this option for daemons which just need to resolve their own system user or group name.
Requires(postun): systemd-units
* This also disconnects the AF_UNIX abstract namespace from the host (In case you wonder what this refers to: sockets listed in /proc/net/unix that start with an @ are in the abstract namespace, those which start in / are in the file system namespace). This means that services which listen or connect to AF_UNIX sockets in the abstract namespaces might break. AF_UNIX sockets in the file system continue to work correctly even with PrivateNetwork?=yes. We strongly recommend anyway to stop using abstract namespace AF_UNIX sockets, as they bring very little benefit these days. If your package uses them please consider moving them into the file system into a subdirectory in /run (system services) or $XDG_RUNTIME_DIR (user services).
* This also disconnects the AF_NETLINK and AF_AUDIT socket families from the host. For services requiring auditing, that need to subscribe to network configuration changes, or want to subscribe to hardware devices coming and going (udev) PrivateNetwork?=yes cannot be used hence.


%post
For further details see the systemd.exec(5) man page.
if [ $1 -eq 1 ]; then
        # Package install, not upgrade
        /bin/systemctl daemon-reload >/dev/null 2>&1 || :
fi


%preun
= Packaging =
if [ $1 -eq 0 ] ; then
        # Package removal, not upgrade
        /bin/systemctl disable httpd.service > /dev/null 2>&1 || :
        /bin/systemctl stop httpd.service > /dev/null 2>&1 || :
fi


%postun
== Filesystem locations ==
/bin/systemctl daemon-reload >/dev/null 2>&1 || :
Packages with systemd unit files '''must''' put them into <code>%{_unitdir}</code>. <code>%{_unitdir}</code> evaluates to /lib/systemd/system on all Fedora systems (F-15+). Unit files are architecture independent (hence, not <code>%{_lib}</code>) and needed early in the boot process.
if [ $1 -ge 1 ] ; then
 
        # Package upgrade, not uninstall
Please note that in order for the <code>%{_unitdir}</code> macro to exist, your package must have:
        /bin/systemctl try-restart httpd.service >/dev/null 2>&1 || :
<pre>
fi
BuildRequires: systemd
</pre>
</pre>


Note that /bin/systemctl daemon-reload will automatically detect new systemd unit .service files placed into %{_unitdir}. There is no equivalent to 'chkconfig --add <service>', because it is unnecessary.
== %files section ==
Systemd unit <code>.service</code> files must not be marked as <code>%config</code> files.


== Why don't we.... ==
== Unit files in spec file scriptlets ==
Information on proper handling of unit files in spec file scriptlets can be found here: [[:Packaging:Scriptlets#Systemd]]


* Enable most services by default?
== Tmpfiles.d ==
tmpfiles.d is a service provided systemd in Fedora 15 and later for managing temporary files and directories for daemons. For more information on how to use Tmpfiles.d in Fedora Packages, please see: [[:Packaging:Tmpfiles.d]]


Some core services must be enabled by default for a functional system, but the default for most network-listening scripts is
== Why don't we.... ==
off. This is done for better security. We have multiple tools that can enable services, including GUIs.


* Start the service after installation?
* Start the service after installation?


Installations can be in changeroots, in an installer context, or in other situations where you don't want the services autostarted.
Installations can be in changeroots, in an installer context, or in other situations where you don't want the services autostarted.

Latest revision as of 18:24, 25 January 2018

Fedora systemd Services

This document describes the guidelines for systemd services, for use and inclusion in Fedora packages.

Definitions

Since systemd includes some concepts which are extensions of previous concepts, the following definitions may be useful:

Service: A process or task executed and controlled by the init system (e.g. systemd).
Traditional Service: A service which is explicitly started or stopped, either by the init system at boot or manually by a superuser. In systemd, one of several types of service controlled by a .service file.
Activated service: A service that is not (or not necessarily) started explicitly by the user but start when certain other events happen or certain state becomes true.
Socket-activated Service: A service which is waiting for traffic across a socket before activating. In systemd, controlled by a .socket file.
D-Bus service: A service which activates in response to a message from the D-Bus system bus.
Unit file: The systemd equivalent of a SysV initscript.

Unit Files

Each package that contains software that wants/needs to start a traditional service at boot MUST have a systemd unit file.

Ideally, systemd unit files are reusable across distributions and shipped with the upstream packages. Please consider working with upstream to integrate the systemd files you prepare in the upstream sources. Information for developers on how to integrate systemd support best with their build system you may find on http://0pointer.de/public/systemd-man/daemon.html

Note.png
Migrating from SysV Initscripts with non-standard service commands
Packages which have SysV initscripts that contain 'non-standard service commands' (commands besides start, stop, reload, force-reload, status, restart, or try-restart) must convert those commands into standalone helper scripts. Systemd does not support non-standard unit commands.

Naming

Unit files for traditional services have a naming scheme of foobar.service. When considering what basename to use, keep in mind that we'd like to use the same service names for software across distributions. We'd also like to ship the .service files in the upstream packages. These desires create a few guides for naming a unit file:

  • Follow upstream if they're already distributing a .service file and it's not likely to conflict with other packages.
  • Look at packages in other distros or talk with the maintainers of those packages and upstream to try to come up with a common name.
  • Unit files should be named after the software implementation that they support as opposed to the generic type of software. So, a good name would be apache-httpd.service and bad names would be httpd.service or apache.service as there are multiple httpd implementations and multiple projects produced by the apache foundation.

For backwards compatibility you may also want to create a symlink from an older, name to the new name. In the above example, for instance, Fedora has always used httpd for the service. When creating the new apache-httpd.service file, also create a symlink named httpd.service that points at apache-httpd.service. Then end users that are used to using service httpd will have it continue to work.

Basic format

Note.png
Case Sensitivity
All fields in a unit file are case sensitive.

[Unit]

Every .service file must begin with a [Unit] section:

[Unit]
Description=A brief human readable string describing the service (not the .service file!)
Documentation=man:foo.service(8) man:foo.conf(5) http://www.foo.org/docs/

The Description= line must not exceed 80 characters, and must describe the service, and not the .service file. For example, "Apache Web Server" is a good description, but "Starts and Stops the Apache Web Server" is a bad one.

Documentation field

Systemd in Fedora 17+ has support for defining documentation in unit files via the Documentation= field (it is ignored in older releases, so it is safe to keep one systemd unit file across all branches). System administrators will be looking at the contents of the Documentation= field to determine what the service is, how to configure it, and where to locate additional documentation relating to the service. Accordingly, packagers are strongly encouraged to include any available sources in the Documentation= field which provide this information. If a man page or info page is present in the package, refer to it using "man:manpage" or "info:infofile" respectively. If the documentation is in plaintext, use "​file://path/to/file". Lastly, if no local documentation exists in the package, but it exists at a url, use the URL (with ​http://) in this field. Multiple URIs can be added to the Documentation= field, as a space separated list. For details on URI definitions and formatting, please refer to the uri(7) manpage (man uri).

[Service]

Next, the .service file must have a [Service] section:

[Service]
Type=...
ExecStart=...
ExecReload=...

The Type= setting is very important. For D-Bus services this should be "dbus", for traditional services "forking" is usually a good idea, for services not offering any interfaces to other services "simple" is best. For "one-shot" scripts "oneshot" is ideal, often combined with RemainAfterExit=. See http://0pointer.de/public/systemd-man/systemd.service.html for further discussion on the topic. Since "simple" is the default type, .service files which would normally set Type=simple may simply omit the Type line altogether.

BusName= should be set for all services connecting to D-Bus. (i.e. it is a must for those where Type=dbus, but might make sense otherwise, too) Omit this option if your service does not take a name on the bus.

ExecStart= is necessary for all services. This line defines the string that you would run to start the daemon, along with any necessary options.

ExecReload= should be specified for all services supporting reload. It is highly recommended to add code here that synchronously reloads the configuration file here (i.e. /bin/kill -HUP $MAINPID is usually a poor choice, due to its asynchronous nature). Omit this option if your service does not support reloading.


[Install]

Finally, the .service file should have an [Install] section:

[Install]
WantedBy=...

The recommended parameters for WantedBy= are either graphical.target (services related to the graphical user interface) or multi-user.target (for everything else). When the user (or our scriptlets) invoke systemctl enable the service will be set to start in these targets.

For more information regarding these options see http://0pointer.de/public/systemd-man/systemd.unit.html and http://0pointer.de/public/systemd-man/systemd.service.html

EnvironmentFiles and support for /etc/sysconfig files

The EnvironmentFiles= line in the [Service] section of .service files is used to support loading environment variables that can be used in unit files. For instance, if your sysv-initscript used a file in /etc/sysconfig to set command line options, you can use EnvironmentFiles= like so:

Example:

[Service]
Type=forking
EnvironmentFile=-/etc/sysconfig/httpd
ExecStart=/usr/sbin/httpd $OPTIONS
ExecReload=/usr/sbin/httpd $OPTIONS -k restart

You may then refer to variables set in the /etc/sysconfig/httpd file with ${FOOBAR} and $FOOBAR, in the ExecStart= lines (and related lines). (${FOOBAR} expands the variable into one word, $FOOBAR splits up the variable value at whitespace into multiple words)

The "-" on the EnvironmentFile= line ensures that no error messages is generated if the environment file does not exist. Since many of these files were optional in sysvinit, you should include the "-" when using this directive.

Fields to avoid

For most services, we do not want to use requirement dependencies in the [Unit] section, such as Requires= or Wants=. Instead exclusively use ordering dependencies: Before= and After=. This is used to implement loose coupling: if someone asks two services to start at the same time, systemd will properly order their startup but not make it strictly necessary to run one if the other is started.

If you use a requirement dependency, use Wants= rather than Requires=, to make things a little bit more robust. If you use a requirement dependency in almost all cases you should also add an ordering dependency, as ordering and requirement dependencies are orthogonal in systemd.

Here's an example of this common case:

  1. A web application needs postgresql to store its data.
  2. It is set to start After postgresql. On startup, the web application does not start until postgresql does.
  3. Once running, the system administrator needs to restart postgresql due to a config tweak.
  4. Since only After was used, the web application may be temporarily unable to serve some requests but it does not need to restart in order to serve pages after the database comes back up.

Avoid referring to runlevelX.target units in all lines taking unit names (such as WantedBy), these are legacy names existing for compatibility with SysV only.

Avoid Names= (in the [Unit] section). Usually it is a better idea to symlink an additional name in the file system. Note that a name listed in Names= is only useful when a service file is already loaded. However, systemd loads only the service files actually referred to in another loaded service, and uses the filenames during the search. Hence a name in Names= is not useful as a search key, but a symlink in the file system is. Also do not put a (redundant) Names=foobar.service line into a file called foobar.service. We want to keep our service files short.

Unit files should avoid using StandardOutput= or StandardError=. The default is the right choice for almost all cases, and using the default allows users to change global defaults in /etc/systemd/system.conf.

Example Unit file

This is an example systemd unit .service file for ABRT:

[Unit]
Description=ABRT Automated Bug Reporting Tool

[Service]
Type=dbus
BusName=com.redhat.abrt
ExecStart=/usr/sbin/abrtd -d -s

[Install]
WantedBy=multi-user.target

Activation

Systemd allows for three forms of activated services: #Hardware activation, #Socket activation, and #DBus activation.

Hardware activation

Hardware activation occurs when a service is installed but only turns on if a certain type of hardware is installed. Enabling of the service is normally done with a udev rule. At this time we do not have further guidance on how to write those udev rules. The service itself installs its .service files in the normal places and are installed by the normal systemd scriptlets. These services should never be enabled by the package as they will be enabled by udev.

Socket activation

Socket activation occurs when a service allows systemd to listen for connections to a specific socket and, when systemd receives a connection on that socket, it starts the service. To do this, the upstream source needs to have some minor coding work to let systemd listen for connections on the socket and there needs to be a .socket file in %{_lib}/systemd/system/ that tells systemd to listen to that socket and what to start when a connection is received. This is similar in function to inetd and some, but not all, services coded to work with inetd will work with socket activation.

Note.png
Currently we do not have guidance on how to write socket files as this is something that needs upstream code and they can add a proper .socket file at the same time.

However, socket activation can also be used to allow parallel startup of services. If a service supports systemd socket activation as described above and we additionally start it explicitly on boot, then systemd will start it but allow things that depend on it to startup at the same time. If the dependent service makes a request to the socket activatable service before it has come up, then systemd will cause the request to wait until the socket activatable service has come up and can process the request. To achieve this effect, the service must be socket activatable as described above, the .service file for the service needs to have a Wants= line for the .socket, and the service must autostart.

Note that certain socket activated services (notably network listening ones) require FESCo approval - see Packaging:DefaultServices for details. Once you have permission, you can package the .socket file and use the systemd scriptlets that enable the service by default. You need to also check the .service file to make sure it has a Wants= entry on the .socket file as that ensures that starting the service will also inform systemd of the socket.

Timer activation

All packages with timed execution which already depend on systemd (for example because they contain systemd units) must use timer units instead of cron jobs, with no dependency or requirements on a crontab.

Packages which do not already depend or require systemd must not use timer units but instead depend and have requirement on crontabs, to avoid introducing unnecessary new dependencies on systemd directly.

DBus activation

In order to allow parallel startup of a D-Bus service and its consumers it is essential that D-Bus services can be bus activated and the D-Bus activation request is forwarded from the D-Bus system bus to systemd so that you end up with only a single instance of the service, even if a service is triggered by both boot-up and activation. If historically your D-Bus service was not bus-activated but started via a SysV init script, it should be updated to use bus activation. This may be implemented by dropping a D-Bus .service file in /usr/share/dbus-1/system-services/ and use the SystemdService= directive therein to redirect the activation to systemd.

Note.png
.service
systemd and D-Bus both use the .service file

suffix but they are different things. In a systemd driven init process, the D-Bus .service file will often refer to the systemd .service file for the same

program with the SystemdService directive.

Here's an example for a D-Bus bus-activable service. The ConsoleKit bus activation file /usr/share/dbus-1/system-services/org.freedesktop.ConsoleKit.service:

[D-BUS Service]
Name=org.freedesktop.ConsoleKit
Exec=/usr/sbin/console-kit-daemon --no-daemon
User=root
SystemdService=console-kit-daemon.service

And the matching systemd unit file /lib/systemd/system/console-kit-daemon.service:

[Unit]
Description=Console Manager

[Service]
Type=dbus
BusName=org.freedesktop.ConsoleKit
ExecStart=/usr/sbin/console-kit-daemon --no-daemon

As you can see SystemdService= is used in the D-Bus activation file to bind the systemd service to the D-Bus service.

Traditionally, bus activated D-Bus services could not be disabled without uninstalling them entirely. systemd allows you to disable services by making D-Bus invoke an alias systemd service name (that can be created or removed to enable/disable activation) as an intermediary for the real service.

You can easily implement disabling by directing the D-Bus service to an alias name of the real service file (in the filesystem this shows up as a symlink placed in /etc/systemd/system to the real service file). This alias is then controlled via "systemctl enable" and "systemctl disable". It is a good idea (though technically not necessary) to name this alias name after the D-Bus bus name of the service, prefixed with "dbus-". Example for Avahi, a service that the admin might need to disable: set SystemdService=dbus-org.freedesktop.Avahi.service instead of SystemdService=avahi-daemon.service in the D-Bus activation file, and then make dbus-org.freedesktop.Avahi.service an optional alias of avahi-daemon.service that can be controlled via the Alias= directive in the [Install] section of the systemd service file. This directive is then read by "systemctl enable" and "systemctl disable" to create resp. remove a symlink to make the service available resp. unavailable under this additional name. A full example for the Avahi case:

Here is the D-Bus .service file for Avahi (/usr/share/dbus-1/system-services/org.freedesktop.Avahi.service):

[D-BUS Service]
Name=org.freedesktop.Avahi
SystemdService=dbus-org.freedesktop.Avahi.service

# This service should not be bus activated if systemd isn't running,
# so that activation won't conflict with the init script startup.
Exec=/bin/false

Here is the Avahi systemd unit .service file (/lib/systemd/system/avahi-daemon.service):

[Unit]
Description=Avahi mDNS/DNS-SD Stack
Requires=avahi-daemon.socket

[Service]
Type=dbus
BusName=org.freedesktop.Avahi
ExecStart=/usr/sbin/avahi-daemon -s
ExecReload=/usr/sbin/avahi-daemon -r
NotifyAccess=main

[Install]
WantedBy=multi-user.target
Also=avahi-daemon.socket
Alias=dbus-org.freedesktop.Avahi.service

The Alias= line ensures that the existance of the /etc/systemd/system/dbus-org.freedesktop.Avahi.service symlink can be controlled by "systemctl enable" and "systemctl disable".

Note that the creation/removal of the alias symlinks should be done with "systemctl enable" and "systemctl disable" only. You should not create these symlinks manually.

In general, it is also recommended to supply native systemd units for all services that are already bus activatable, so that these services can be controlled and supervised centrally like any other service with tools such as systemctl. A similar logic like the one shown above should apply.

See the D-Bus documentation for more information about bus activation: http://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-starting-services

Automatic restarting

If you package a long-running service, please consider enabling systemd's automatic restart feature for it, to improve reliability by making sure the system automatically attempts recovering a failing daemon. Please use

[Service]
...
Restart=on-failure

or

[Service]
...
Restart=on-abnormal

in your unit's .service file for this.

The former will tell systemd to restart the daemon as soon as it fails regardless of the precise reason. It's a good choice for most long-running services. Some daemons require a way to escape constant restarting by exiting with any non-zero exit code. For those services use Restart=on-abnormal, which will still restart the daemon when it fails "abnormally", on unclean signal, core dump, timeout or watchdog exits, but not on unclean exit codes. It is recommended to to enable automatic restarts for all long-running services, but which setting is the right one, and whether it is useful at all depends on the specific service. Please consult the systemd.service(5) man page for more information on the various settings.

Private devices and networking

If you package a long-running system service, please consider enabling systemd's PrivateDevices= and PrivateNetwork= settings for it, in order to improve security and minimize the attack surface.

When PrivateDevices=yes is set in the [Service] section of a systemd service unit file, the processes run for the service will run in a private file system namespace where /dev is replaced by a minimal version that only includes the device nodes /dev/null, /dev/zero, /dev/full, /dev/urandom, /dev/random, /dev/tty as well as the submounts /dev/shm, /dev/pts, /dev/mqueue, /dev/hugepages, and the /dev/stdout, /dev/stderr, /dev/stdin symlinks. No device nodes for physical devices will be included, however. Furthermore, the CAP_MKNOD capability is removed. Finally, the "devices" cgroup controller is used to ensure that no access to device nodes except the listed ones is possible. This is an efficient way to take away physical device access for services, thus minimizing the attack surface.

When PrivateNetwork=yes is set in the [Service] section of a systemd service unit file, the processes run for the service will run in a private network namespace whith a private loopback network interface, and no other network devices. Network communication between host and service can not be initiated. This is an efficient way to take away network access for services, thus minimizing the attack surface.

By default both switches default to "no".

Note that PrivateDevices=yes should not be used for:

  • Services that actually require physical device access
  • Services which may be used to execute arbitrary user or administrator supplied programs (such as cron, ...). We shouldn't limit what people can do with these services.
  • This option creates a new file system namespace where mount/umount propagation is turned off back into the host. This means that mounts made by the service will stay private to the service. Thus this option should not be used by services which shall be able to establish mounts in the host.

Note that PrivateNetwork=yes should not be used for:

  • Services that actually require network access (with the exception of daemons only needing socket activation)
  • Services which may be used to execute arbitrary user or administrator supplied programs. (see above)
  • Services which might need to resolve non-system user and group names. Since on some setups resolving non-system users might require network access to an LDAP or NIS server, enabling this option on might break resolving of these user names. Note however that system users/groups are always resolvable even without network access. Hence it is safe to enable this option for daemons which just need to resolve their own system user or group name.
  • This also disconnects the AF_UNIX abstract namespace from the host (In case you wonder what this refers to: sockets listed in /proc/net/unix that start with an @ are in the abstract namespace, those which start in / are in the file system namespace). This means that services which listen or connect to AF_UNIX sockets in the abstract namespaces might break. AF_UNIX sockets in the file system continue to work correctly even with PrivateNetwork?=yes. We strongly recommend anyway to stop using abstract namespace AF_UNIX sockets, as they bring very little benefit these days. If your package uses them please consider moving them into the file system into a subdirectory in /run (system services) or $XDG_RUNTIME_DIR (user services).
  • This also disconnects the AF_NETLINK and AF_AUDIT socket families from the host. For services requiring auditing, that need to subscribe to network configuration changes, or want to subscribe to hardware devices coming and going (udev) PrivateNetwork?=yes cannot be used hence.

For further details see the systemd.exec(5) man page.

Packaging

Filesystem locations

Packages with systemd unit files must put them into %{_unitdir}. %{_unitdir} evaluates to /lib/systemd/system on all Fedora systems (F-15+). Unit files are architecture independent (hence, not %{_lib}) and needed early in the boot process.

Please note that in order for the %{_unitdir} macro to exist, your package must have:

BuildRequires: systemd

%files section

Systemd unit .service files must not be marked as %config files.

Unit files in spec file scriptlets

Information on proper handling of unit files in spec file scriptlets can be found here: Packaging:Scriptlets#Systemd

Tmpfiles.d

tmpfiles.d is a service provided systemd in Fedora 15 and later for managing temporary files and directories for daemons. For more information on how to use Tmpfiles.d in Fedora Packages, please see: Packaging:Tmpfiles.d

Why don't we....

  • Start the service after installation?

Installations can be in changeroots, in an installer context, or in other situations where you don't want the services autostarted.