From 06782a203fa0ed5ab29a03c96294f138209211da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isma=C3=ABl=20Bouya?= Date: Sat, 1 Jun 2019 00:01:46 +0200 Subject: Add a filesWatcher service to restart them when secrets change --- modules/default.nix | 1 + modules/filesWatcher.nix | 61 ++++++++++++++++++++++++++++++++++++++++++++ modules/secrets.nix | 14 ++++++---- modules/websites/default.nix | 14 ++++++++++ 4 files changed, 85 insertions(+), 5 deletions(-) create mode 100644 modules/filesWatcher.nix diff --git a/modules/default.nix b/modules/default.nix index acb0bb51..e36f1a06 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -1,6 +1,7 @@ { myids = ./myids.nix; secrets = ./secrets.nix; + filesWatcher = ./filesWatcher.nix; webstats = ./webapps/webstats; diaspora = ./webapps/diaspora.nix; diff --git a/modules/filesWatcher.nix b/modules/filesWatcher.nix new file mode 100644 index 00000000..44440271 --- /dev/null +++ b/modules/filesWatcher.nix @@ -0,0 +1,61 @@ +{ lib, config, pkgs, ... }: +with lib; +let + cfg = config.services.filesWatcher; +in +{ + options = { + services.filesWatcher = with types; mkOption { + default = {}; + description = '' + Files to watch and trigger service reload or restart of service + when changed. + ''; + type = attrsOf (submodule { + options = { + restart = mkEnableOption "Restart service rather than reloading it"; + paths = mkOption { + type = listOf str; + description = '' + Paths to watch that should trigger a reload of the + service + ''; + }; + waitTime = mkOption { + type = int; + default = 5; + description = '' + Time to wait before reloading/restarting the service. + Set 0 to not wait. + ''; + }; + }; + }); + }; + }; + + config.systemd.services = attrsets.mapAttrs' (name: icfg: attrsets.nameValuePair + "${name}Watcher" { + description = "${name} reloader"; + after = [ "network.target" ]; + script = let + action = if icfg.restart then "restart" else "reload"; + in '' + # Service may be stopped during file modification (e.g. activationScripts) + if ${pkgs.systemd}/bin/systemctl --quiet is-active ${name}.service; then + ${pkgs.coreutils}/bin/sleep ${toString icfg.waitTime} + ${pkgs.systemd}/bin/systemctl ${action} ${name}.service + fi + ''; + serviceConfig = { + Type = "oneshot"; + }; + } + ) cfg; + config.systemd.paths = attrsets.mapAttrs' (name: icfg: attrsets.nameValuePair + "${name}Watcher" { + wantedBy = [ "multi-user.target" ]; + pathConfig.PathChanged = icfg.paths; + } + ) cfg; +} diff --git a/modules/secrets.nix b/modules/secrets.nix index b282e56e..808b15c5 100644 --- a/modules/secrets.nix +++ b/modules/secrets.nix @@ -39,11 +39,15 @@ if [ -f /run/keys/secrets.tar ]; then if [ ! -f ${location}/currentSecrets ] || ! sha512sum -c --status "${location}/currentSecrets"; then echo "rebuilding secrets" - rm -rf ${location} - install -m0750 -o root -g keys -d ${location} - ${pkgs.gnutar}/bin/tar --strip-components 1 -C ${location} -xf /run/keys/secrets.tar - sha512sum /run/keys/secrets.tar > ${location}/currentSecrets - find ${location} -type d -exec chown root:keys {} \; -exec chmod o-rx {} \; + TMP=$(${pkgs.coreutils}/bin/mktemp -d) + if [ -n "$TMP" ]; then + install -m0750 -o root -g keys -d $TMP + ${pkgs.gnutar}/bin/tar --strip-components 1 -C $TMP -xf /run/keys/secrets.tar + sha512sum /run/keys/secrets.tar > $TMP/currentSecrets + find $TMP -type d -exec chown root:keys {} \; -exec chmod o-rx {} \; + ${pkgs.rsync}/bin/rsync -O -c -av --delete $TMP/ ${location} + rm -rf $TMP + fi fi fi ''; diff --git a/modules/websites/default.nix b/modules/websites/default.nix index e57f505a..4b21efb7 100644 --- a/modules/websites/default.nix +++ b/modules/websites/default.nix @@ -91,6 +91,13 @@ in }; }); }; + watchPaths = mkOption { + type = listOf string; + default = []; + description = '' + Paths to watch that should trigger a reload of httpd + ''; + }; }; }); }; @@ -159,6 +166,13 @@ in }) ) cfg; + config.services.filesWatcher = attrsets.mapAttrs' (name: icfg: attrsets.nameValuePair + "httpd${icfg.httpdName}" { + paths = icfg.watchPaths; + waitTime = 5; + } + ) cfg; + config.security.acme.certs = let typesToManage = attrsets.filterAttrs (k: v: v.enable) cfg; flatVhosts = lists.flatten (attrsets.mapAttrsToList (k: v: -- cgit v1.2.3