diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index 2b7fcb314041..c1a51fbf8b42 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -162,6 +162,10 @@ let
${cfg.appendConfig}
'';
+ configPath = if cfg.enableReload
+ then "/etc/nginx/nginx.conf"
+ else configFile;
+
vhosts = concatStringsSep "\n" (mapAttrsToList (vhostName: vhost:
let
onlySSL = vhost.onlySSL || vhost.enableSSL;
@@ -431,6 +435,16 @@ in
";
};
+ enableReload = mkOption {
+ default = false;
+ type = types.bool;
+ description = ''
+ Reload nginx when configuration file changes (instead of restart).
+ The configuration file is exposed at /etc/nginx/nginx.conf.
+ See also systemd.services.*.restartIfChanged.
+ '';
+ };
+
stateDir = mkOption {
default = "/var/spool/nginx";
description = "
@@ -638,10 +652,10 @@ in
preStart =
''
${cfg.preStart}
- ${cfg.package}/bin/nginx -c ${configFile} -p ${cfg.stateDir} -t
+ ${cfg.package}/bin/nginx -c ${configPath} -p ${cfg.stateDir} -t
'';
serviceConfig = {
- ExecStart = "${cfg.package}/bin/nginx -c ${configFile} -p ${cfg.stateDir}";
+ ExecStart = "${cfg.package}/bin/nginx -c ${configPath} -p ${cfg.stateDir}";
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
Restart = "always";
RestartSec = "10s";
@@ -649,6 +663,21 @@ in
};
};
+ environment.etc."nginx/nginx.conf" = mkIf cfg.enableReload {
+ source = configFile;
+ };
+
+ systemd.services.nginx-config-reload = mkIf cfg.enableReload {
+ wantedBy = [ "nginx.service" ];
+ restartTriggers = [ configFile ];
+ script = ''
+ if ${pkgs.systemd}/bin/systemctl -q is-active nginx.service ; then
+ ${pkgs.systemd}/bin/systemctl reload nginx.service
+ fi
+ '';
+ serviceConfig.RemainAfterExit = true;
+ };
+
security.acme.certs = filterAttrs (n: v: v != {}) (
let
vhostsConfigs = mapAttrsToList (vhostName: vhostConfig: vhostConfig) virtualHosts;
diff --git a/nixos/tests/nginx.nix b/nixos/tests/nginx.nix
index d66d99821c11..d0b7306ae83b 100644
--- a/nixos/tests/nginx.nix
+++ b/nixos/tests/nginx.nix
@@ -3,15 +3,15 @@
# generated virtual hosts config.
# 2. whether the ETag header is properly generated whenever we're serving
# files in Nix store paths
-
+# 3. nginx doesn't restart on configuration changes (only reloads)
import ./make-test.nix ({ pkgs, ... }: {
name = "nginx";
meta = with pkgs.stdenv.lib.maintainers; {
maintainers = [ mbbx6spp ];
};
- nodes = let
- commonConfig = { pkgs, ... }: {
+ nodes = {
+ webserver = { pkgs, lib, ... }: {
services.nginx.enable = true;
services.nginx.commonHttpConfig = ''
log_format ceeformat '@cee: {"status":"$status",'
@@ -32,30 +32,42 @@ import ./make-test.nix ({ pkgs, ... }: {
location /favicon.ico { allow all; access_log off; log_not_found off; }
'';
};
+
services.nginx.virtualHosts.localhost = {
root = pkgs.runCommand "testdir" {} ''
mkdir "$out"
echo hello world > "$out/index.html"
'';
};
- };
- in {
- webserver = commonConfig;
- newwebserver = { pkgs, lib, ... }: {
- imports = [ commonConfig ];
- services.nginx.virtualHosts.localhost = {
- root = lib.mkForce (pkgs.runCommand "testdir2" {} ''
- mkdir "$out"
- echo hello world > "$out/index.html"
- '');
- };
+ services.nginx.enableReload = true;
+
+ nesting.clone = [
+ {
+ services.nginx.virtualHosts.localhost = {
+ root = lib.mkForce (pkgs.runCommand "testdir2" {} ''
+ mkdir "$out"
+ echo content changed > "$out/index.html"
+ '');
+ };
+ }
+
+ {
+ services.nginx.virtualHosts."1.my.test".listen = [ { addr = "127.0.0.1"; port = 8080; }];
+ }
+
+ {
+ services.nginx.package = pkgs.nginxUnstable;
+ }
+ ];
};
+
};
testScript = { nodes, ... }: let
- newServerSystem = nodes.newwebserver.config.system.build.toplevel;
- switch = "${newServerSystem}/bin/switch-to-configuration test";
+ etagSystem = "${nodes.webserver.config.system.build.toplevel}/fine-tune/child-1";
+ justReloadSystem = "${nodes.webserver.config.system.build.toplevel}/fine-tune/child-2";
+ reloadRestartSystem = "${nodes.webserver.config.system.build.toplevel}/fine-tune/child-3";
in ''
my $url = 'http://localhost/index.html';
@@ -77,9 +89,23 @@ import ./make-test.nix ({ pkgs, ... }: {
subtest "check ETag if serving Nix store paths", sub {
my $oldEtag = checkEtag;
- $webserver->succeed('${switch}');
+ $webserver->succeed("${etagSystem}/bin/switch-to-configuration test >&2");
+ $webserver->sleep(1); # race condition
my $newEtag = checkEtag;
die "Old ETag $oldEtag is the same as $newEtag" if $oldEtag eq $newEtag;
};
+
+ subtest "config is reloaded on nixos-rebuild switch", sub {
+ $webserver->succeed("${justReloadSystem}/bin/switch-to-configuration test >&2");
+ $webserver->waitForOpenPort("8080");
+ $webserver->fail("journalctl -u nginx | grep -q -i stopped");
+ $webserver->succeed("journalctl -u nginx | grep -q -i reloaded");
+ };
+
+ subtest "restart when nginx package changes", sub {
+ $webserver->succeed("${reloadRestartSystem}/bin/switch-to-configuration test >&2");
+ $webserver->waitForUnit("nginx");
+ $webserver->succeed("journalctl -u nginx | grep -q -i stopped");
+ };
'';
})