Merge pull request #309460 from r-ryantm/auto-update/home-manager
[NixPkgs.git] / pkgs / build-support / setup-systemd-units.nix
blob4c7ee86669f587eca7673b65d869216480ac7a73
1 # | Build a script to install and start a set of systemd units on any
2 # systemd-based system.
4 # Creates a symlink at /etc/systemd-static/${namespace} for slightly
5 # improved atomicity.
6 { writeScriptBin
7 , bash
8 , coreutils
9 , systemd
10 , runCommand
11 , lib
13   { units     # : AttrSet String (Either Path { path : Path, wanted-by : [ String ] })
14               # ^ A set whose names are unit names and values are
15               # either paths to the corresponding unit files or a set
16               # containing the path and the list of units this unit
17               # should be wanted-by (none by default).
18               #
19               # The names should include the unit suffix
20               # (e.g. ".service")
21   , namespace # : String
22               # The namespace for the unit files, to allow for
23               # multiple independent unit sets managed by
24               # `setupSystemdUnits`.
25   }:
26     let static = runCommand "systemd-static" {}
27           ''
28             mkdir -p $out
29             ${lib.concatStringsSep "\n" (lib.mapAttrsToList (nm: file:
30                 "ln -sv ${file.path or file} $out/${nm}"
31              ) units)}
32           '';
33         add-unit-snippet = name: file:
34           ''
35             oldUnit=$(readlink -f "$unitDir/${name}" || echo "$unitDir/${name}")
36             if [ -f "$oldUnit" -a "$oldUnit" != "${file.path or file}" ]; then
37               unitsToStop+=("${name}")
38             fi
39             ln -sf "/etc/systemd-static/${namespace}/${name}" \
40               "$unitDir/.${name}.tmp"
41             mv -T "$unitDir/.${name}.tmp" "$unitDir/${name}"
42             ${lib.concatStringsSep "\n" (map (unit:
43                 ''
44                   mkdir -p "$unitDir/${unit}.wants"
45                   ln -sf "../${name}" \
46                     "$unitDir/${unit}.wants/.${name}.tmp"
47                   mv -T "$unitDir/${unit}.wants/.${name}.tmp" \
48                     "$unitDir/${unit}.wants/${name}"
49                 ''
50               ) file.wanted-by or [])}
51             unitsToStart+=("${name}")
52           '';
53     in
54       writeScriptBin "setup-systemd-units"
55         ''
56           #!${bash}/bin/bash -e
57           export PATH=${coreutils}/bin:${systemd}/bin
59           unitDir=/etc/systemd/system
60           if [ ! -w "$unitDir" ]; then
61             unitDir=/nix/var/nix/profiles/default/lib/systemd/system
62             mkdir -p "$unitDir"
63           fi
64           declare -a unitsToStop unitsToStart
66           oldStatic=$(readlink -f /etc/systemd-static/${namespace} || true)
67           if [ "$oldStatic" != "${static}" ]; then
68             ${lib.concatStringsSep "\n"
69                 (lib.mapAttrsToList add-unit-snippet units)}
70             if [ ''${#unitsToStop[@]} -ne 0 ]; then
71               echo "Stopping unit(s) ''${unitsToStop[@]}" >&2
72               systemctl stop "''${unitsToStop[@]}"
73             fi
74             mkdir -p /etc/systemd-static
75             ln -sfT ${static} /etc/systemd-static/.${namespace}.tmp
76             mv -T /etc/systemd-static/.${namespace}.tmp /etc/systemd-static/${namespace}
77             systemctl daemon-reload
78             echo "Starting unit(s) ''${unitsToStart[@]}" >&2
79             systemctl start "''${unitsToStart[@]}"
80           else
81             echo "Units unchanged, doing nothing" >&2
82           fi
83         ''