From: Ismaƫl Bouya Date: Fri, 31 May 2019 22:01:46 +0000 (+0200) Subject: Add a filesWatcher service to restart them when secrets change X-Git-Url: https://git.immae.eu/?p=perso%2FImmae%2FConfig%2FNix.git;a=commitdiff_plain;h=17f6eae9907a122d4472da727ae8b1ac1c40c027 Add a filesWatcher service to restart them when secrets change --- diff --git a/modules/default.nix b/modules/default.nix index acb0bb5..e36f1a0 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 0000000..4444027 --- /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/private/buildbot/default.nix b/modules/private/buildbot/default.nix index fa6a6f2..d023a83 100644 --- a/modules/private/buildbot/default.nix +++ b/modules/private/buildbot/default.nix @@ -37,6 +37,10 @@ in extraGroups = [ "keys" ]; }; + services.websites.tools.watchPaths = lib.attrsets.mapAttrsToList + (k: project: "/var/secrets/buildbot/${project.name}/webhook-httpd-include") + myconfig.env.buildbot.projects; + services.websites.tools.vhostConfs.git.extraConfig = lib.attrsets.mapAttrsToList (k: project: '' RedirectMatch permanent "^/buildbot/${project.name}$" "/buildbot/${project.name}/" RewriteEngine On @@ -106,6 +110,14 @@ in } ]; + services.filesWatcher = lib.attrsets.mapAttrs' (k: project: lib.attrsets.nameValuePair "buildbot-${project.name}" { + restart = true; + paths = [ + "/var/secrets/buildbot/ldap" + "/var/secrets/buildbot/ssh_key" + ] ++ lib.attrsets.mapAttrsToList (k: v: "/var/secrets/buildbot/${project.name}/${k}") project.secrets; + }) myconfig.env.buildbot.projects; + systemd.services = lib.attrsets.mapAttrs' (k: project: lib.attrsets.nameValuePair "buildbot-${project.name}" { description = "Buildbot Continuous Integration Server ${project.name}."; after = [ "network-online.target" ]; diff --git a/modules/private/databases/openldap/default.nix b/modules/private/databases/openldap/default.nix index e048d56..f09113a 100644 --- a/modules/private/databases/openldap/default.nix +++ b/modules/private/databases/openldap/default.nix @@ -144,6 +144,11 @@ in ''; }; + services.filesWatcher.openldap = { + restart = true; + paths = [ "${config.secrets.location}/ldap/" ]; + }; + services.openldap = { enable = true; dataDir = cfg.dataDir; diff --git a/modules/private/ftp.nix b/modules/private/ftp.nix index ada5f41..59cae59 100644 --- a/modules/private/ftp.nix +++ b/modules/private/ftp.nix @@ -72,6 +72,11 @@ in ''; }]; + services.filesWatcher.pure-ftpd = { + restart = true; + paths = [ "/var/secrets/pure-ftpd-ldap" ]; + }; + systemd.services.pure-ftpd = let configFile = pkgs.writeText "pure-ftpd.conf" '' PassivePortRange 40000 50000 diff --git a/modules/private/mpd.nix b/modules/private/mpd.nix index 9903bdf..17454d7 100644 --- a/modules/private/mpd.nix +++ b/modules/private/mpd.nix @@ -20,6 +20,11 @@ networking.firewall.allowedTCPPorts = [ 6600 ]; users.users.mpd.extraGroups = [ "wwwrun" "keys" ]; systemd.services.mpd.serviceConfig.RuntimeDirectory = "mpd"; + services.filesWatcher.mpd = { + restart = true; + paths = [ "/var/secrets/mpd-config" ]; + }; + services.mpd = { enable = true; network.listenAddress = "any"; diff --git a/modules/private/tasks/default.nix b/modules/private/tasks/default.nix index 30f49ee..83a1b61 100644 --- a/modules/private/tasks/default.nix +++ b/modules/private/tasks/default.nix @@ -101,6 +101,7 @@ in { SetEnv TASKD_LDAP_FILTER "${env.ldap.search}" ''; }]; + services.websites.tools.watchPaths = [ "/var/secrets/webapps/tools-taskwarrior-web" ]; services.websites.tools.modules = [ "proxy_fcgi" "sed" ]; services.websites.tools.vhostConfs.task = { certName = "eldiron"; diff --git a/modules/private/websites/aten/integration.nix b/modules/private/websites/aten/integration.nix index 748e388..384b324 100644 --- a/modules/private/websites/aten/integration.nix +++ b/modules/private/websites/aten/integration.nix @@ -27,6 +27,9 @@ in { root = aten.apache.root; extraConfig = [ aten.apache.vhostConf ]; }; + services.websites.integration.watchPaths = [ + "/var/secrets/webapps/${aten.app.environment}-aten" + ]; }; } diff --git a/modules/private/websites/aten/production.nix b/modules/private/websites/aten/production.nix index 7a4adb5..1a55e8a 100644 --- a/modules/private/websites/aten/production.nix +++ b/modules/private/websites/aten/production.nix @@ -29,6 +29,8 @@ in { root = aten.apache.root; extraConfig = [ aten.apache.vhostConf ]; }; + services.websites.production.watchPaths = [ + "/var/secrets/webapps/${aten.app.environment}-aten" + ]; }; } - diff --git a/modules/private/websites/chloe/integration.nix b/modules/private/websites/chloe/integration.nix index c42a428..25ec4db 100644 --- a/modules/private/websites/chloe/integration.nix +++ b/modules/private/websites/chloe/integration.nix @@ -32,5 +32,8 @@ in { root = chloe.apache.root; extraConfig = [ chloe.apache.vhostConf ]; }; + services.websites.integration.watchPaths = [ + "/var/secrets/webapps/${chloe.app.environment}-chloe" + ]; }; } diff --git a/modules/private/websites/chloe/production.nix b/modules/private/websites/chloe/production.nix index 0bf2d8f..6e0c34d 100644 --- a/modules/private/websites/chloe/production.nix +++ b/modules/private/websites/chloe/production.nix @@ -34,5 +34,8 @@ in { root = chloe.apache.root; extraConfig = [ chloe.apache.vhostConf ]; }; + services.websites.production.watchPaths = [ + "/var/secrets/webapps/${chloe.app.environment}-chloe" + ]; }; } diff --git a/modules/private/websites/connexionswing/integration.nix b/modules/private/websites/connexionswing/integration.nix index 1d8488a..7d77ac7 100644 --- a/modules/private/websites/connexionswing/integration.nix +++ b/modules/private/websites/connexionswing/integration.nix @@ -31,6 +31,10 @@ in { root = connexionswing.apache.root; extraConfig = [ connexionswing.apache.vhostConf ]; }; + services.filesWatcher.phpfpm-connexionswing_dev = { + restart = true; + paths = [ "/var/secrets/webapps/${connexionswing.app.environment}-connexionswing" ]; + }; }; } diff --git a/modules/private/websites/connexionswing/production.nix b/modules/private/websites/connexionswing/production.nix index 555f129..f4cb377 100644 --- a/modules/private/websites/connexionswing/production.nix +++ b/modules/private/websites/connexionswing/production.nix @@ -33,6 +33,10 @@ in { root = connexionswing.apache.root; extraConfig = [ connexionswing.apache.vhostConf ]; }; + services.filesWatcher.phpfpm-connexionswing_prod = { + restart = true; + paths = [ "/var/secrets/webapps/${connexionswing.app.environment}-connexionswing" ]; + }; }; } diff --git a/modules/private/websites/default.nix b/modules/private/websites/default.nix index 8b02977..c3d941c 100644 --- a/modules/private/websites/default.nix +++ b/modules/private/websites/default.nix @@ -138,6 +138,10 @@ in ''; }; + services.filesWatcher.httpdProd.paths = [ "/var/secrets/apache-ldap" ]; + services.filesWatcher.httpdInte.paths = [ "/var/secrets/apache-ldap" ]; + services.filesWatcher.httpdTools.paths = [ "/var/secrets/apache-ldap" ]; + services.websites.production = { enable = true; adminAddr = "httpd@immae.eu"; diff --git a/modules/private/websites/florian/app.nix b/modules/private/websites/florian/app.nix index 3a6d152..55fb3cb 100644 --- a/modules/private/websites/florian/app.nix +++ b/modules/private/websites/florian/app.nix @@ -32,5 +32,9 @@ in { adminer.apache.vhostConf ]; }; + services.filesWatcher.phpfpm-tellesflorian_dev = { + restart = true; + paths = [ "/var/secrets/webapps/${tellesflorian.app.environment}-tellesflorian" ]; + }; }; } diff --git a/modules/private/websites/ludivinecassal/integration.nix b/modules/private/websites/ludivinecassal/integration.nix index ed0dc9f..f0ef3a6 100644 --- a/modules/private/websites/ludivinecassal/integration.nix +++ b/modules/private/websites/ludivinecassal/integration.nix @@ -28,5 +28,9 @@ in { root = ludivinecassal.apache.root; extraConfig = [ ludivinecassal.apache.vhostConf ]; }; + services.filesWatcher.phpfpm-ludivinecassal_dev = { + restart = true; + paths = [ "/var/secrets/webapps/${ludivinecassal.app.environment}-ludivinecassal" ]; + }; }; } diff --git a/modules/private/websites/ludivinecassal/production.nix b/modules/private/websites/ludivinecassal/production.nix index 3df5613..6a22d98 100644 --- a/modules/private/websites/ludivinecassal/production.nix +++ b/modules/private/websites/ludivinecassal/production.nix @@ -29,5 +29,9 @@ in { root = ludivinecassal.apache.root; extraConfig = [ ludivinecassal.apache.vhostConf ]; }; + services.filesWatcher.phpfpm-ludivinecassal_prod = { + restart = true; + paths = [ "/var/secrets/webapps/${ludivinecassal.app.environment}-ludivinecassal" ]; + }; }; } diff --git a/modules/private/websites/tools/diaspora/default.nix b/modules/private/websites/tools/diaspora/default.nix index efa1fab..6742a81 100644 --- a/modules/private/websites/tools/diaspora/default.nix +++ b/modules/private/websites/tools/diaspora/default.nix @@ -145,6 +145,11 @@ in { configDir = "/var/secrets/webapps/diaspora"; }; + services.filesWatcher.diaspora = { + restart = true; + paths = [ dcfg.configDir ]; + }; + services.websites.tools.modules = [ "headers" "proxy" "proxy_http" ]; diff --git a/modules/private/websites/tools/ether/default.nix b/modules/private/websites/tools/ether/default.nix index ebcbf61..3e68d54 100644 --- a/modules/private/websites/tools/ether/default.nix +++ b/modules/private/websites/tools/ether/default.nix @@ -133,6 +133,11 @@ in { systemd.services.etherpad-lite.serviceConfig.SupplementaryGroups = "keys"; + services.filesWatcher.etherpad-lite = { + restart = true; + paths = [ ecfg.sessionKeyFile ecfg.apiKeyFile ecfg.configFile ]; + }; + services.websites.tools.modules = [ "headers" "proxy" "proxy_http" "proxy_wstunnel" ]; diff --git a/modules/private/websites/tools/mastodon/default.nix b/modules/private/websites/tools/mastodon/default.nix index d742a33..1a4b387 100644 --- a/modules/private/websites/tools/mastodon/default.nix +++ b/modules/private/websites/tools/mastodon/default.nix @@ -63,6 +63,19 @@ in { socketsPrefix = "live_immae"; dataDir = "/var/lib/mastodon_immae"; }; + services.filesWatcher.mastodon-streaming = { + restart = true; + paths = [ mcfg.configFile ]; + }; + services.filesWatcher.mastodon-web = { + restart = true; + paths = [ mcfg.configFile ]; + }; + services.filesWatcher.mastodon-sidekiq = { + restart = true; + paths = [ mcfg.configFile ]; + }; + services.websites.tools.modules = [ "headers" "proxy" "proxy_wstunnel" "proxy_http" diff --git a/modules/private/websites/tools/mgoblin/default.nix b/modules/private/websites/tools/mgoblin/default.nix index 5da81f6..1d398db 100644 --- a/modules/private/websites/tools/mgoblin/default.nix +++ b/modules/private/websites/tools/mgoblin/default.nix @@ -78,6 +78,14 @@ in { plugins = builtins.attrValues pkgs.webapps.mediagoblin-plugins; configFile = "/var/secrets/webapps/tools-mediagoblin"; }; + services.filesWatcher.mediagoblin-web = { + restart = true; + paths = [ mcfg.configFile ]; + }; + services.filesWatcher.mediagoblin-celeryd = { + restart = true; + paths = [ mcfg.configFile ]; + }; services.websites.tools.modules = [ "proxy" "proxy_http" diff --git a/modules/private/websites/tools/peertube/default.nix b/modules/private/websites/tools/peertube/default.nix index dee1b81..dd28530 100644 --- a/modules/private/websites/tools/peertube/default.nix +++ b/modules/private/websites/tools/peertube/default.nix @@ -153,6 +153,11 @@ in { services.websites.tools.modules = [ "headers" "proxy" "proxy_http" "proxy_wstunnel" ]; + services.filesWatcher.peertube = { + restart = true; + paths = [ pcfg.configFile ]; + }; + services.websites.tools.vhostConfs.peertube = { certName = "eldiron"; addToCerts = true; diff --git a/modules/private/websites/tools/tools/default.nix b/modules/private/websites/tools/tools/default.nix index 94a2be1..d75def4 100644 --- a/modules/private/websites/tools/tools/default.nix +++ b/modules/private/websites/tools/tools/default.nix @@ -212,6 +212,11 @@ in { }; }; + services.filesWatcher.ympd = { + restart = true; + paths = [ "/var/secrets/mpd" ]; + }; + services.phpfpm.pools.roundcubemail = { listen = roundcubemail.phpFpm.socket; extraConfig = roundcubemail.phpFpm.pool; @@ -297,6 +302,13 @@ in { "${kanboard.apache.webappName}" = kanboard.webRoot; }; + services.websites.tools.watchPaths = [ + "/var/secrets/webapps/tools-wallabag" + ]; + services.filesWatcher.phpfpm-wallabag = { + restart = true; + paths = [ "/var/secrets/webapps/tools-wallabag" ]; + }; }; } diff --git a/modules/secrets.nix b/modules/secrets.nix index b282e56..808b15c 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 e57f505..4b21efb 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: