nixos/nginx: make redirect status code configurable

Add an option to configure which code globalRedirect and forceSSL use.
It previously was always 301 with no easy way to override.

Changed files
+51 -8
nixos
doc
manual
release-notes
modules
services
web-servers
tests
+4
nixos/doc/manual/release-notes/rl-2405.section.md
···
existing process, but will need to start that process from gdb (so it is a
child). Or you can set `boot.kernel.sysctl."kernel.yama.ptrace_scope"` to 0.
+
- [Nginx virtual hosts](#opt-services.nginx.virtualHosts) using `forceSSL` or
+
`globalRedirect` can now have redirect codes other than 301 through
+
`redirectCode`.
+
- Gitea 1.21 upgrade has several breaking changes, including:
- Custom themes and other assets that were previously stored in `custom/public/*` now belong in `custom/public/assets/*`
- New instances of Gitea using MySQL now ignore the `[database].CHARSET` config option and always use the `utf8mb4` charset, existing instances should migrate via the `gitea doctor convert` CLI command.
+2 -2
nixos/modules/services/web-servers/nginx/default.nix
···
server_name ${vhost.serverName} ${concatStringsSep " " vhost.serverAliases};
${acmeLocation}
location / {
-
return 301 https://$host$request_uri;
+
return ${toString vhost.redirectCode} https://$host$request_uri;
}
}
''}
···
${optionalString (vhost.root != null) "root ${vhost.root};"}
${optionalString (vhost.globalRedirect != null) ''
location / {
-
return 301 http${optionalString hasSSL "s"}://${vhost.globalRedirect}$request_uri;
+
return ${toString vhost.redirectCode} http${optionalString hasSSL "s"}://${vhost.globalRedirect}$request_uri;
}
''}
${optionalString hasSSL ''
+19 -6
nixos/modules/services/web-servers/nginx/vhost-options.nix
···
type = types.bool;
default = false;
description = lib.mdDoc ''
-
Whether to add a separate nginx server block that permanently redirects (301)
-
all plain HTTP traffic to HTTPS. This will set defaults for
-
`listen` to listen on all interfaces on the respective default
-
ports (80, 443), where the non-SSL listens are used for the redirect vhosts.
+
Whether to add a separate nginx server block that redirects (defaults
+
to 301, configurable with `redirectCode`) all plain HTTP traffic to
+
HTTPS. This will set defaults for `listen` to listen on all interfaces
+
on the respective default ports (80, 443), where the non-SSL listens
+
are used for the redirect vhosts.
'';
};
···
default = null;
example = "newserver.example.org";
description = lib.mdDoc ''
-
If set, all requests for this host are redirected permanently to
-
the given hostname.
+
If set, all requests for this host are redirected (defaults to 301,
+
configurable with `redirectCode`) to the given hostname.
+
'';
+
};
+
+
redirectCode = mkOption {
+
type = types.ints.between 300 399;
+
default = 301;
+
example = 308;
+
description = lib.mdDoc ''
+
HTTP status used by `globalRedirect` and `forceSSL`. Possible usecases
+
include temporary (302, 307) redirects, keeping the request method and
+
body (307, 308), or explicitly resetting the method to GET (303).
+
See <https://developer.mozilla.org/en-US/docs/Web/HTTP/Redirections>.
'';
};
+1
nixos/tests/all-tests.nix
···
nginx-njs = handleTest ./nginx-njs.nix {};
nginx-proxyprotocol = handleTest ./nginx-proxyprotocol {};
nginx-pubhtml = handleTest ./nginx-pubhtml.nix {};
+
nginx-redirectcode = handleTest ./nginx-redirectcode.nix {};
nginx-sso = handleTest ./nginx-sso.nix {};
nginx-status-page = handleTest ./nginx-status-page.nix {};
nginx-tmpdir = handleTest ./nginx-tmpdir.nix {};
+25
nixos/tests/nginx-redirectcode.nix
···
+
import ./make-test-python.nix ({ pkgs, lib, ... }: {
+
name = "nginx-redirectcode";
+
meta.maintainers = with lib.maintainers; [ misterio77 ];
+
+
nodes = {
+
webserver = { pkgs, lib, ... }: {
+
services.nginx = {
+
enable = true;
+
virtualHosts.localhost = {
+
globalRedirect = "example.com/foo";
+
# With 308 (and 307), the method and body are to be kept when following it
+
redirectCode = 308;
+
};
+
};
+
};
+
};
+
+
testScript = ''
+
webserver.wait_for_unit("nginx")
+
webserver.wait_for_open_port(80)
+
+
# Check the status code
+
webserver.succeed("curl -si http://localhost | grep '^HTTP/[0-9.]\+ 308 Permanent Redirect'")
+
'';
+
})