From aa167819a976c5e659e62f9a64ac80f9e3b2bba6 Mon Sep 17 00:00:00 2001 From: Felix Buehler Date: Sun, 26 Jan 2025 20:11:30 +0100 Subject: [PATCH] nixos/caddy: validate at build-time --- .../services/web-servers/caddy/default.nix | 73 ++++++++++--------- 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/nixos/modules/services/web-servers/caddy/default.nix b/nixos/modules/services/web-servers/caddy/default.nix index d87a04e0f5f159..e58c919b74d57d 100644 --- a/nixos/modules/services/web-servers/caddy/default.nix +++ b/nixos/modules/services/web-servers/caddy/default.nix @@ -70,6 +70,10 @@ let configPath = "/etc/${etcConfigFile}"; mkCertOwnershipAssertion = import ../../../security/acme/mk-cert-ownership-assertion.nix lib; + + runOptions = ''--config ${configPath} ${ + optionalString (cfg.adapter != null) "--adapter ${cfg.adapter}" + }''; in { imports = [ @@ -389,6 +393,15 @@ in assertion = cfg.configFile == configFile -> cfg.adapter == "caddyfile" || cfg.adapter == null; message = "To specify an adapter other than 'caddyfile' please provide your own configuration via `services.caddy.configFile`"; } + { + assertion = + (builtins.tryEval ( + pkgs.runCommand "validate-caddy-config" { } '' + ${lib.getExe cfg.package} validate ${runOptions} + '' + )).success; + message = "Caddy configuration is invalid"; + } ] ++ map ( name: @@ -425,39 +438,33 @@ in reloadTriggers = optional cfg.enableReload cfg.configFile; restartTriggers = optional (!cfg.enableReload) cfg.configFile; - serviceConfig = - let - runOptions = ''--config ${configPath} ${ - optionalString (cfg.adapter != null) "--adapter ${cfg.adapter}" - }''; - in - { - # Override the `ExecStart` line from upstream's systemd unit file by our own: - # https://www.freedesktop.org/software/systemd/man/systemd.service.html#ExecStart= - # If the empty string is assigned to this option, the list of commands to start is reset, prior assignments of this option will have no effect. - ExecStart = [ - "" - ''${cfg.package}/bin/caddy run ${runOptions} ${optionalString cfg.resume "--resume"}'' - ]; - # Validating the configuration before applying it ensures we’ll get a proper error that will be reported when switching to the configuration - ExecReload = [ - "" - ] ++ lib.optional cfg.enableReload "${lib.getExe cfg.package} reload ${runOptions} --force"; - User = cfg.user; - Group = cfg.group; - ReadWritePaths = [ cfg.dataDir ]; - StateDirectory = mkIf (cfg.dataDir == "/var/lib/caddy") [ "caddy" ]; - LogsDirectory = mkIf (cfg.logDir == "/var/log/caddy") [ "caddy" ]; - Restart = "on-failure"; - RestartPreventExitStatus = 1; - RestartSec = "5s"; - EnvironmentFile = optional (cfg.environmentFile != null) cfg.environmentFile; - - # TODO: attempt to upstream these options - NoNewPrivileges = true; - PrivateDevices = true; - ProtectHome = true; - }; + serviceConfig = { + # Override the `ExecStart` line from upstream's systemd unit file by our own: + # https://www.freedesktop.org/software/systemd/man/systemd.service.html#ExecStart= + # If the empty string is assigned to this option, the list of commands to start is reset, prior assignments of this option will have no effect. + ExecStart = [ + "" + ''${lib.getExe cfg.package} run ${runOptions} ${optionalString cfg.resume "--resume"}'' + ]; + # Validating the configuration before applying it ensures we’ll get a proper error that will be reported when switching to the configuration + ExecReload = [ + "" + ] ++ lib.optional cfg.enableReload "${lib.getExe cfg.package} reload ${runOptions} --force"; + User = cfg.user; + Group = cfg.group; + ReadWritePaths = [ cfg.dataDir ]; + StateDirectory = mkIf (cfg.dataDir == "/var/lib/caddy") [ "caddy" ]; + LogsDirectory = mkIf (cfg.logDir == "/var/log/caddy") [ "caddy" ]; + Restart = "on-failure"; + RestartPreventExitStatus = 1; + RestartSec = "5s"; + EnvironmentFile = optional (cfg.environmentFile != null) cfg.environmentFile; + + # TODO: attempt to upstream these options + NoNewPrivileges = true; + PrivateDevices = true; + ProtectHome = true; + }; }; users.users = optionalAttrs (cfg.user == "caddy") {