<chapter xmlns="http://docbook.org/ns/docbook"
         xmlns:xlink="http://www.w3.org/1999/xlink"
         xmlns:xi="http://www.w3.org/2001/XInclude"
         version="5.0"
         xml:id="sec-systemctl">
 <title>Service Management</title>
 <para>
  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
  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,
  swap files, devices, targets (groups of units) and more. Units can have
  complex dependencies; for instance, one unit can require that another unit
  must be successfully started before the first unit can be started. When the
  system boots, it starts a unit named <literal>default.target</literal>; the
  dependencies of this unit cause all system services to be started, file
  systems to be mounted, swap files to be activated, and so on.
 </para>
 <section xml:id="sect-nixos-systemd-general">
  <title>Interacting with a running systemd</title>
   <para>
    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>
<prompt>$ </prompt>systemctl
-.mount          loaded active mounted   /
swapfile.swap    loaded active active    /swapfile
sshd.service     loaded active running   SSH Daemon
graphical.target loaded active active    Graphical Interface
<replaceable>...</replaceable>
</screen>
  </para>
  <para>
   You can ask for detailed status information about a unit, for instance, the
   PostgreSQL database service:
<screen>
<prompt>$ </prompt>systemctl status postgresql.service
postgresql.service - PostgreSQL Server
          Loaded: loaded (/nix/store/pn3q73mvh75gsrl8w7fdlfk3fq5qm5mw-unit/postgresql.service)
          Active: active (running) since Mon, 2013-01-07 15:55:57 CET; 9h ago
        Main PID: 2390 (postgres)
          CGroup: name=systemd:/system/postgresql.service
                  ├─2390 postgres
                  ├─2418 postgres: writer process
                  ├─2419 postgres: wal writer process
                  ├─2420 postgres: autovacuum launcher process
                  ├─2421 postgres: stats collector process
                  └─2498 postgres: zabbix zabbix [local] idle

Jan 07 15:55:55 hagbard postgres[2394]: [1-1] LOG:  database system was shut down at 2013-01-07 15:55:05 CET
Jan 07 15:55:57 hagbard postgres[2390]: [1-1] LOG:  database system is ready to accept connections
Jan 07 15:55:57 hagbard postgres[2420]: [1-1] LOG:  autovacuum launcher started
Jan 07 15:55:57 hagbard systemd[1]: Started PostgreSQL Server.
</screen>
  Note that this shows the status of the unit (active and running), all the
  processes belonging to the service, as well as the most recent log messages
  from the service.
 </para>
 <para>
  Units can be stopped, started or restarted:
<screen>
<prompt># </prompt>systemctl stop postgresql.service
<prompt># </prompt>systemctl start postgresql.service
<prompt># </prompt>systemctl restart postgresql.service
</screen>
   These operations are synchronous: they wait until the service has finished
   starting or stopping (or has failed). Starting a unit will cause the
   dependencies of that unit to be started as well (if necessary).
  </para>
  <!-- TODO: document cgroups, draft:
   each service and user session is a cgroup

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

