Merge pull request #98661 from doronbehar/doc/nixos/systemd-nixos-specific

doc/nixos: Explain better NixOS specific Systemd stuff
This commit is contained in:
Michele Guerini Rocco 2020-11-06 11:52:58 +01:00 committed by GitHub
commit 25d15ebffb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -6,7 +6,7 @@
<title>Service Management</title> <title>Service Management</title>
<para> <para>
In NixOS, all system services are started and monitored using the systemd In NixOS, all system services are started and monitored using the systemd
program. Systemd is the “init” process of the system (i.e. PID 1), the program. systemd is the “init” process of the system (i.e. PID 1), the
parent of all other processes. It manages a set of so-called “units”, parent of all other processes. It manages a set of so-called “units”,
which can be things like system services (programs), but also mount points, which can be things like system services (programs), but also mount points,
swap files, devices, targets (groups of units) and more. Units can have swap files, devices, targets (groups of units) and more. Units can have
@ -16,10 +16,17 @@
dependencies of this unit cause all system services to be started, file dependencies of this unit cause all system services to be started, file
systems to be mounted, swap files to be activated, and so on. systems to be mounted, swap files to be activated, and so on.
</para> </para>
<para> <section xml:id="sect-nixos-systemd-general">
The command <command>systemctl</command> is the main way to interact with <title>Interacting with a running systemd</title>
<command>systemd</command>. Without any arguments, it shows the status of <para>
active units: The command <command>systemctl</command> is the main way to interact with
<command>systemd</command>. The following paragraphs demonstrate ways to
interact with any OS running systemd as init system. NixOS is of no
exception. The <link xlink:href="#sect-nixos-systemd-nixos">next section
</link> explains NixOS specific things worth knowing.
</para>
<para>
Without any arguments, <literal>systmctl</literal> the status of active units:
<screen> <screen>
<prompt>$ </prompt>systemctl <prompt>$ </prompt>systemctl
-.mount loaded active mounted / -.mount loaded active mounted /
@ -28,10 +35,10 @@ sshd.service loaded active running SSH Daemon
graphical.target loaded active active Graphical Interface graphical.target loaded active active Graphical Interface
<replaceable>...</replaceable> <replaceable>...</replaceable>
</screen> </screen>
</para> </para>
<para> <para>
You can ask for detailed status information about a unit, for instance, the You can ask for detailed status information about a unit, for instance, the
PostgreSQL database service: PostgreSQL database service:
<screen> <screen>
<prompt>$ </prompt>systemctl status postgresql.service <prompt>$ </prompt>systemctl status postgresql.service
postgresql.service - PostgreSQL Server postgresql.service - PostgreSQL Server
@ -62,11 +69,72 @@ Jan 07 15:55:57 hagbard systemd[1]: Started PostgreSQL Server.
<prompt># </prompt>systemctl start postgresql.service <prompt># </prompt>systemctl start postgresql.service
<prompt># </prompt>systemctl restart postgresql.service <prompt># </prompt>systemctl restart postgresql.service
</screen> </screen>
These operations are synchronous: they wait until the service has finished These operations are synchronous: they wait until the service has finished
starting or stopping (or has failed). Starting a unit will cause the starting or stopping (or has failed). Starting a unit will cause the
dependencies of that unit to be started as well (if necessary). dependencies of that unit to be started as well (if necessary).
</para> </para>
<!-- - cgroups: each service and user session is a cgroup <!-- TODO: document cgroups, draft:
each service and user session is a cgroup
- cgroup resource management --> - cgroup resource management -->
</section>
<section xml:id="sect-nixos-systemd-nixos">
<title>systemd in NixOS</title>
<para>
Packages in Nixpkgs sometimes provide systemd units with them, usually in
e.g <literal>#pkg-out#/lib/systemd/</literal>. Putting such a package in
<literal>environment.systemPackages</literal> doesn't make the service
available to users or the system.
</para>
<para>
In order to enable a systemd <emphasis>system</emphasis> service with
provided upstream package, use (e.g):
<programlisting>
<xref linkend="opt-systemd.packages"/> = [ pkgs.packagekit ];
</programlisting>
</para>
<para>
Usually NixOS modules written by the community do the above, plus take care of
other details. If a module was written for a service you are interested in,
you'd probably need only to use
<literal>services.#name#.enable = true;</literal>. These services are defined
in Nixpkgs'
<link xlink:href="https://github.com/NixOS/nixpkgs/tree/master/nixos/modules">
<literal>nixos/modules/</literal> directory </link>. In case the service is
simple enough, the above method should work, and start the service on boot.
</para>
<para>
<emphasis>User</emphasis> systemd services on the other hand, should be
treated differently. Given a package that has a systemd unit file at
<literal>#pkg-out#/lib/systemd/user/</literal>, using
<xref linkend="opt-systemd.packages"/> will make you able to start the service via
<literal>systemctl --user start</literal>, but it won't start automatically on login.
<!-- TODO: Document why systemd.packages doesn't work for user services or fix this.
https://github.com/NixOS/nixpkgs/blob/2cd6594a8710a801038af2b72348658f732ce84a/nixos/modules/system/boot/systemd-lib.nix#L177-L198
This has been talked over at https://discourse.nixos.org/t/how-to-enable-upstream-systemd-user-services-declaratively/7649/5
-->
However, You can imperatively enable it by adding the package's attribute to
<link linkend="opt-environment.systemPackages">
<literal>systemd.packages</literal></link> and then do this (e.g):
<screen>
<prompt>$ </prompt>mkdir -p ~/.config/systemd/user/default.target.wants
<prompt>$ </prompt>ln -s /run/current-system/sw/lib/systemd/user/syncthing.service ~/.config/systemd/user/default.target.wants/
<prompt>$ </prompt>systemctl --user daemon-reload
<prompt>$ </prompt>systemctl --user enable syncthing.service
</screen>
If you are interested in a timer file, use <literal>timers.target.wants</literal>
instead of <literal>default.target.wants</literal> in the 1st and 2nd command.
</para>
<para>
Using <literal>systemctl --user enable syncthing.service</literal> instead of
the above, will work, but it'll use the absolute path of
<literal>syncthing.service</literal> for the symlink, and this path is in
<literal>/nix/store/.../lib/systemd/user/</literal>. Hence
<link xlink:href="#sec-nix-gc">garbage collection</link> will remove that file
and you will wind up with a broken symlink in your systemd configuration, which
in turn will not make the service / timer start on login.
</para>
</section>
</chapter> </chapter>