# Shared shell steps for a host oneshot that fetches a credential into a # file a service inside a container loads at start (`LoadCredential`, or a # config file expanded once while parsing). Such a service never sees a # value that lands after it started — a late fetch or a rotation — until it # is restarted, so the fetch restarts it, and only when the value changed: # a routine re-fetch of the same value leaves it alone. # # secret_differs # True when is missing or holds something other than . # Call it BEFORE `atomic_write_secret` writes . Compares with # `$(< path)`, a bash builtin, so the value never becomes an argument in # /proc; both sides lose their trailing newlines, which is how # `atomic_write_secret` writes and `$(bao …)` reads. # # refresh_consumer # Nothing while `container@` is not active: a container that # starts later loads the file as it starts. Otherwise a running # consumer is restarted, and a failed one — # a consumer that found no credential may have hit its start limit — is # reset and started. A consumer stopped on purpose stays stopped. # `--no-block` throughout: a caller ordered `Before=` its consumer must # not wait on a job that waits on the caller (the deadlock stated at # `swarm-services-cert`'s propagation in ../hive-tls.nix). # # Pure function — NOT a NixOS module. Call it from a module's `let`: # # refreshConsumer = import ./lib/refresh-consumer.nix { }; # script = '' # ${refreshConsumer} # changed=0 # if secret_differs "$path" "$secret"; then changed=1; fi # atomic_write_secret 0400 root:root "$path" "$secret" # if [ "$changed" = 1 ]; then refresh_consumer my-machine my.service; fi # ''; # # Requires `systemd` on the caller's `path`. { }: '' secret_differs() { [ ! -f "$1" ] || [ "$(< "$1")" != "$2" ] } refresh_consumer() { local machine="$1" unit="$2" if ! systemctl is-active --quiet "container@$machine.service"; then return 0 fi if systemctl --machine="$machine" is-failed --quiet "$unit"; then echo "the credential for $unit in $machine changed and $unit had failed — starting it" systemctl --machine="$machine" reset-failed "$unit" systemctl --machine="$machine" start --no-block "$unit" else echo "the credential for $unit in $machine changed — restarting it if it runs" systemctl --machine="$machine" try-restart --no-block "$unit" fi } ''