1# Unit handling {#sec-unit-handling}
2
3To figure out what units need to be started/stopped/restarted/reloaded, the
4script first checks the current state of the system, similar to what `systemctl
5list-units` shows. For each of the units, the script goes through the following
6checks:
7
8- Is the unit file still in the new system? If not, **stop** the service unless
9 it sets `X-StopOnRemoval` in the `[Unit]` section to `false`.
10
11- Is it a `.target` unit? If so, **start** it unless it sets
12 `RefuseManualStart` in the `[Unit]` section to `true` or `X-OnlyManualStart`
13 in the `[Unit]` section to `true`. Also **stop** the unit again unless it
14 sets `X-StopOnReconfiguration` to `false`.
15
16- Are the contents of the unit files different? They are compared by parsing
17 them and comparing their contents. If they are different but only
18 `X-Reload-Triggers` in the `[Unit]` section is changed, **reload** the unit.
19 The NixOS module system allows setting these triggers with the option
20 [systemd.services.\<name\>.reloadTriggers](#opt-systemd.services). There are
21 some additional keys in the `[Unit]` section that are ignored as well. If the
22 unit files differ in any way, the following actions are performed:
23
24 - `.path` and `.slice` units are ignored. There is no need to restart them
25 since changes in their values are applied by systemd when systemd is
26 reloaded.
27
28 - `.mount` units are **reload**ed if only their `Options` changed. If anything
29 else changed (like `What`), they are **restart**ed unless they are the mount
30 unit for `/` or `/nix` in which case they are reloaded to prevent the system
31 from crashing. Note that this is the case for `.mount` units and not for
32 mounts from `/etc/fstab`. These are explained in [](#sec-switching-systems).
33
34 - `.socket` units are currently ignored. This is to be fixed at a later
35 point.
36
37 - The rest of the units (mostly `.service` units) are then **reload**ed if
38 `X-ReloadIfChanged` in the `[Service]` section is set to `true` (exposed
39 via [systemd.services.\<name\>.reloadIfChanged](#opt-systemd.services)).
40 A little exception is done for units that were deactivated in the meantime,
41 for example because they require a unit that got stopped before. These
42 are **start**ed instead of reloaded.
43
44 - If the reload flag is not set, some more flags decide if the unit is
45 skipped. These flags are `X-RestartIfChanged` in the `[Service]` section
46 (exposed via
47 [systemd.services.\<name\>.restartIfChanged](#opt-systemd.services)),
48 `RefuseManualStop` in the `[Unit]` section, and `X-OnlyManualStart` in the
49 `[Unit]` section.
50
51 - Further behavior depends on the unit having `X-StopIfChanged` in the
52 `[Service]` section set to `true` (exposed via
53 [systemd.services.\<name\>.stopIfChanged](#opt-systemd.services)). This is
54 set to `true` by default and must be explicitly turned off if not wanted.
55 If the flag is enabled, the unit is **stop**ped and then **start**ed. If
56 not, the unit is **restart**ed. The goal of the flag is to make sure that
57 the new unit never runs in the old environment which is still in place
58 before the activation script is run. This behavior is different when the
59 service is socket-activated, as outlined in the following steps.
60
61 - The last thing that is taken into account is whether the unit is a service
62 and socket-activated. If `X-StopIfChanged` is **not** set, the service
63 is **restart**ed with the others. If it is set, both the service and the
64 socket are **stop**ped and the socket is **start**ed, leaving socket
65 activation to start the service when it's needed.
66
67## Sysinit reactivation {#sec-sysinit-reactivation}
68
69[`sysinit.target`](https://www.freedesktop.org/software/systemd/man/latest/systemd.special.html#sysinit.target)
70is a systemd target that encodes system initialization (i.e. early startup). A
71few units that need to run very early in the bootup process are ordered to
72finish before this target is reached. Probably the most notable one of these is
73`systemd-tmpfiles-setup.service`. We will refer to these units as "sysinit
74units".
75
76"Normal" systemd units, by default, are ordered AFTER `sysinit.target`. In
77other words, these "normal" units expect all services ordered before
78`sysinit.target` to have finished without explicity declaring this dependency
79relationship for each dependency. See the [systemd
80bootup](https://www.freedesktop.org/software/systemd/man/latest/bootup.html)
81for more details on the bootup process.
82
83When restarting both a unit ordered before `sysinit.target` as well as one
84after, this presents a problem because they would be started at the same time
85as they do not explicitly declare their dependency relations.
86
87To solve this, NixOS has an artificial `sysinit-reactivation.target` which
88allows you to ensure that services ordered before `sysinit.target` are
89restarted correctly. This applies both to the ordering between these sysinit
90services as well as ensuring that sysinit units are restarted before "normal"
91units.
92
93To make an existing sysinit service restart correctly during system switch, you
94have to declare:
95
96```nix
97{
98 systemd.services.my-sysinit = {
99 requiredBy = [ "sysinit-reactivation.target" ];
100 before = [ "sysinit-reactivation.target" ];
101 restartTriggers = [ config.environment.etc."my-sysinit.d".source ];
102 };
103}
104```
105
106You need to configure appropriate `restartTriggers` specific to your service.