84 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			84 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
| # | Build a script to install and start a set of systemd units on any
 | |
| # systemd-based system.
 | |
| #
 | |
| # Creates a symlink at /etc/systemd-static/${namespace} for slightly
 | |
| # improved atomicity.
 | |
| { writeScriptBin
 | |
| , bash
 | |
| , coreutils
 | |
| , systemd
 | |
| , runCommand
 | |
| , lib
 | |
| }:
 | |
|   { units     # : AttrSet String (Either Path { path : Path, wanted-by : [ String ] })
 | |
|               # ^ A set whose names are unit names and values are
 | |
|               # either paths to the corresponding unit files or a set
 | |
|               # containing the path and the list of units this unit
 | |
|               # should be wanted-by (none by default).
 | |
|               #
 | |
|               # The names should include the unit suffix
 | |
|               # (e.g. ".service")
 | |
|   , namespace # : String
 | |
|               # The namespace for the unit files, to allow for
 | |
|               # multiple independent unit sets managed by
 | |
|               # `setupSystemdUnits`.
 | |
|   }:
 | |
|     let static = runCommand "systemd-static" {}
 | |
|           ''
 | |
|             mkdir -p $out
 | |
|             ${lib.concatStringsSep "\n" (lib.mapAttrsToList (nm: file:
 | |
|                 "ln -sv ${file.path or file} $out/${nm}"
 | |
|              ) units)}
 | |
|           '';
 | |
|         add-unit-snippet = name: file:
 | |
|           ''
 | |
|             oldUnit=$(readlink -f "$unitDir/${name}" || echo "$unitDir/${name}")
 | |
|             if [ -f "$oldUnit" -a "$oldUnit" != "${file.path or file}" ]; then
 | |
|               unitsToStop+=("${name}")
 | |
|             fi
 | |
|             ln -sf "/etc/systemd-static/${namespace}/${name}" \
 | |
|               "$unitDir/.${name}.tmp"
 | |
|             mv -T "$unitDir/.${name}.tmp" "$unitDir/${name}"
 | |
|             ${lib.concatStringsSep "\n" (map (unit:
 | |
|                 ''
 | |
|                   mkdir -p "$unitDir/${unit}.wants"
 | |
|                   ln -sf "../${name}" \
 | |
|                     "$unitDir/${unit}.wants/.${name}.tmp"
 | |
|                   mv -T "$unitDir/${unit}.wants/.${name}.tmp" \
 | |
|                     "$unitDir/${unit}.wants/${name}"
 | |
|                 ''
 | |
|               ) file.wanted-by or [])}
 | |
|             unitsToStart+=("${name}")
 | |
|           '';
 | |
|     in
 | |
|       writeScriptBin "setup-systemd-units"
 | |
|         ''
 | |
|           #!${bash}/bin/bash -e
 | |
|           export PATH=${coreutils}/bin:${systemd}/bin
 | |
| 
 | |
|           unitDir=/etc/systemd/system
 | |
|           if [ ! -w "$unitDir" ]; then
 | |
|             unitDir=/etc/systemd-mutable/system
 | |
|             mkdir -p "$unitDir"
 | |
|           fi
 | |
|           declare -a unitsToStop unitsToStart
 | |
| 
 | |
|           oldStatic=$(readlink -f /etc/systemd-static/${namespace} || true)
 | |
|           if [ "$oldStatic" != "${static}" ]; then
 | |
|             ${lib.concatStringsSep "\n"
 | |
|                 (lib.mapAttrsToList add-unit-snippet units)}
 | |
|             if [ ''${#unitsToStop[@]} -ne 0 ]; then
 | |
|               echo "Stopping unit(s) ''${unitsToStop[@]}" >&2
 | |
|               systemctl stop "''${unitsToStop[@]}"
 | |
|             fi
 | |
|             mkdir -p /etc/systemd-static
 | |
|             ln -sfT ${static} /etc/systemd-static/.${namespace}.tmp
 | |
|             mv -T /etc/systemd-static/.${namespace}.tmp /etc/systemd-static/${namespace}
 | |
|             systemctl daemon-reload
 | |
|             echo "Starting unit(s) ''${unitsToStart[@]}" >&2
 | |
|             systemctl start "''${unitsToStart[@]}"
 | |
|           else
 | |
|             echo "Units unchanged, doing nothing" >&2
 | |
|           fi
 | |
|         ''
 | 
