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