Unit handling
To figure out what units need to be
started/stopped/restarted/reloaded, the script first checks the
current state of the system, similar to what
systemctl list-units shows. For each of the
units, the script goes through the following checks:
Is the unit file still in the new system? If not,
stop the service unless it
sets X-StopOnRemoval in the
[Unit] section to false.
Is it a .target unit? If so,
start it unless it sets
RefuseManualStart in the
[Unit] section to true or
X-OnlyManualStart in the
[Unit] section to true.
Also stop the unit again
unless it sets X-StopOnReconfiguration to
false.
Are the contents of the unit files different? They are compared
by parsing them and comparing their contents. If they are
different but only X-Reload-Triggers in the
[Unit] section is changed,
reload the unit. The NixOS
module system allows setting these triggers with the option
systemd.services.<name>.reloadTriggers.
There are some additional keys in the [Unit]
section that are ignored as well. If the unit files differ in
any way, the following actions are performed:
.path and .slice units
are ignored. There is no need to restart them since changes
in their values are applied by systemd when systemd is
reloaded.
.mount units are
reloaded. These mostly
come from the /etc/fstab parser.
.socket units are currently ignored. This
is to be fixed at a later point.
The rest of the units (mostly .service
units) are then reloaded
if X-ReloadIfChanged in the
[Service] section is set to
true (exposed via
systemd.services.<name>.reloadIfChanged).
A little exception is done for units that were deactivated
in the meantime, for example because they require a unit
that got stopped before. These are
started instead of
reloaded.
If the reload flag is not set, some more flags decide if the
unit is skipped. These flags are
X-RestartIfChanged in the
[Service] section (exposed via
systemd.services.<name>.restartIfChanged),
RefuseManualStop in the
[Unit] section, and
X-OnlyManualStart in the
[Unit] section.
Further behavior depends on the unit having
X-StopIfChanged in the
[Service] section set to
true (exposed via
systemd.services.<name>.stopIfChanged).
This is set to true by default and must
be explicitly turned off if not wanted. If the flag is
enabled, the unit is
stopped and then
started. If not, the unit
is restarted. The goal of
the flag is to make sure that the new unit never runs in the
old environment which is still in place before the
activation script is run. This behavior is different when
the service is socket-activated, as outlined in the
following steps.
The last thing that is taken into account is whether the
unit is a service and socket-activated. If
X-StopIfChanged is
not set, the service is
restarted with the
others. If it is set, both the service and the socket are
stopped and the socket is
started, leaving socket
activation to start the service when it’s needed.