mirror of
https://github.com/gensokyo-zone/infrastructure.git
synced 2026-02-09 12:29:19 -08:00
refactor(nginx): proxy.ssl options
This commit is contained in:
parent
12671b3539
commit
1f9e9acde4
3 changed files with 176 additions and 135 deletions
|
|
@ -1,16 +1,19 @@
|
||||||
let
|
let
|
||||||
serverModule = {config, name, options, gensokyo-zone, lib, ...}: let
|
proxyModule = {config, name, options, gensokyo-zone, lib, ...}: let
|
||||||
inherit (lib.options) mkOption mkEnableOption;
|
inherit (lib.options) mkOption mkEnableOption;
|
||||||
inherit (lib.modules) mkIf mkMerge mkAfter;
|
inherit (lib.modules) mkIf mkMerge mkAfter mkOptionDefault;
|
||||||
|
inherit (lib.strings) optionalString;
|
||||||
cfg = config.proxy;
|
cfg = config.proxy;
|
||||||
in {
|
in {
|
||||||
options = with lib.types; {
|
options = with lib.types; {
|
||||||
proxy = {
|
proxy = {
|
||||||
enable = mkEnableOption "proxy_pass";
|
enable = mkEnableOption "proxy_pass";
|
||||||
transparent.enable = mkEnableOption "proxy_bind transparent";
|
bind = {
|
||||||
ssl = {
|
enable = mkEnableOption "proxy_bind";
|
||||||
enable = mkEnableOption "ssl upstream";
|
transparent = mkEnableOption "proxy_bind transparent";
|
||||||
verify = mkEnableOption "proxy_ssl_verify";
|
address = mkOption {
|
||||||
|
type = str;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
url = mkOption {
|
url = mkOption {
|
||||||
type = str;
|
type = str;
|
||||||
|
|
@ -18,23 +21,29 @@ let
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
config = {
|
||||||
|
proxy = {
|
||||||
|
bind.address = mkIf cfg.bind.transparent (mkOptionDefault "$remote_addr");
|
||||||
|
};
|
||||||
|
extraConfig = mkIf cfg.enable (mkMerge [
|
||||||
|
(mkIf cfg.bind.enable (mkAfter (
|
||||||
|
"proxy_bind ${cfg.bind.address}" + optionalString cfg.bind.transparent " transparent" + ";"
|
||||||
|
)))
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
serverModule = {config, name, options, gensokyo-zone, lib, ...}: let
|
||||||
|
inherit (lib.modules) mkIf mkAfter;
|
||||||
|
cfg = config.proxy;
|
||||||
|
in {
|
||||||
|
imports = [ proxyModule ];
|
||||||
|
|
||||||
config = let
|
config = let
|
||||||
warnProxy = lib.warnIf (!cfg.enable && options.proxy.url.isDefined) "nginx.stream.servers.${name}.proxy.url set without proxy.enable";
|
warnProxy = lib.warnIf (!cfg.enable && options.proxy.url.isDefined) "nginx.stream.servers.${name}.proxy.url set without proxy.enable";
|
||||||
in {
|
in {
|
||||||
streamConfig = warnProxy (mkMerge [
|
streamConfig = warnProxy (mkIf cfg.enable (mkAfter
|
||||||
(mkIf cfg.transparent.enable ''
|
"proxy_pass ${cfg.url};"
|
||||||
proxy_bind $remote_addr transparent;
|
));
|
||||||
'')
|
|
||||||
(mkIf cfg.ssl.enable
|
|
||||||
"proxy_ssl on;"
|
|
||||||
)
|
|
||||||
(mkIf (cfg.ssl.enable && cfg.ssl.verify)
|
|
||||||
"proxy_ssl_verify on;"
|
|
||||||
)
|
|
||||||
(mkIf cfg.enable (mkAfter
|
|
||||||
"proxy_pass ${cfg.url};"
|
|
||||||
))
|
|
||||||
]);
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
locationModule = { config, nixosConfig, name, virtualHost, xvars, gensokyo-zone, lib, ... }: let
|
locationModule = { config, nixosConfig, name, virtualHost, xvars, gensokyo-zone, lib, ... }: let
|
||||||
|
|
@ -47,9 +56,10 @@ let
|
||||||
inherit (nixosConfig.services) nginx;
|
inherit (nixosConfig.services) nginx;
|
||||||
cfg = config.proxy;
|
cfg = config.proxy;
|
||||||
in {
|
in {
|
||||||
|
imports = [ proxyModule ];
|
||||||
|
|
||||||
options = with lib.types; {
|
options = with lib.types; {
|
||||||
proxy = {
|
proxy = {
|
||||||
enable = mkEnableOption "proxy";
|
|
||||||
enabled = mkOption {
|
enabled = mkOption {
|
||||||
type = bool;
|
type = bool;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
|
|
@ -58,9 +68,6 @@ let
|
||||||
type = bool;
|
type = bool;
|
||||||
default = true;
|
default = true;
|
||||||
};
|
};
|
||||||
url = mkOption {
|
|
||||||
type = str;
|
|
||||||
};
|
|
||||||
path = mkOption {
|
path = mkOption {
|
||||||
type = str;
|
type = str;
|
||||||
};
|
};
|
||||||
|
|
@ -70,21 +77,6 @@ let
|
||||||
websocket.enable = mkEnableOption "websocket proxy" // {
|
websocket.enable = mkEnableOption "websocket proxy" // {
|
||||||
default = cfg.inheritServerDefaults && virtualHost.proxy.websocket.enable;
|
default = cfg.inheritServerDefaults && virtualHost.proxy.websocket.enable;
|
||||||
};
|
};
|
||||||
ssl = {
|
|
||||||
enabled = mkOption {
|
|
||||||
type = bool;
|
|
||||||
};
|
|
||||||
verify = mkEnableOption "proxy_ssl_verify";
|
|
||||||
sni = mkEnableOption "proxy_ssl_server_name" // {
|
|
||||||
default = cfg.ssl.host != null;
|
|
||||||
};
|
|
||||||
host = mkOption {
|
|
||||||
type = nullOr str;
|
|
||||||
default = null;
|
|
||||||
example = "xvars.get.proxy_host";
|
|
||||||
# $upstream_last_server_name is commercial-only :<
|
|
||||||
};
|
|
||||||
};
|
|
||||||
parsed = {
|
parsed = {
|
||||||
scheme = mkOption {
|
scheme = mkOption {
|
||||||
type = nullOr str;
|
type = nullOr str;
|
||||||
|
|
@ -213,9 +205,6 @@ let
|
||||||
enabled = mkOptionDefault (config.proxyPass != null);
|
enabled = mkOptionDefault (config.proxyPass != null);
|
||||||
path = mkIf (hasPrefix "/" name) (mkOptionDefault name);
|
path = mkIf (hasPrefix "/" name) (mkOptionDefault name);
|
||||||
url = mkIf (cfg.inheritServerDefaults && virtualHost.proxy.url != null) (mkOptionDefault virtualHost.proxy.url);
|
url = mkIf (cfg.inheritServerDefaults && virtualHost.proxy.url != null) (mkOptionDefault virtualHost.proxy.url);
|
||||||
ssl = {
|
|
||||||
enabled = mkOptionDefault (cfg.parsed.scheme == "https");
|
|
||||||
};
|
|
||||||
headers = {
|
headers = {
|
||||||
enableRecommended = mkOptionDefault (
|
enableRecommended = mkOptionDefault (
|
||||||
if cfg.enable && (!cfg.inheritServerDefaults || virtualHost.proxy.headers.enableRecommended != false) then true
|
if cfg.enable && (!cfg.inheritServerDefaults || virtualHost.proxy.headers.enableRecommended != false) then true
|
||||||
|
|
@ -266,9 +255,6 @@ let
|
||||||
(mkIf (cfg.headers.rewriteReferer.enable) (mkJustBefore rewriteReferer))
|
(mkIf (cfg.headers.rewriteReferer.enable) (mkJustBefore rewriteReferer))
|
||||||
(mkIf (cfg.redirect.enable) (mkBefore redirect))
|
(mkIf (cfg.redirect.enable) (mkBefore redirect))
|
||||||
(mkIf (emitHeaders) (mkJustAfter setHeaders))
|
(mkIf (emitHeaders) (mkJustAfter setHeaders))
|
||||||
(mkIf (cfg.ssl.enabled && cfg.ssl.sni) "proxy_ssl_server_name on;")
|
|
||||||
(mkIf (cfg.ssl.enabled && cfg.ssl.host != null) "proxy_ssl_name ${cfg.ssl.host};")
|
|
||||||
(mkIf (cfg.ssl.enabled && cfg.ssl.verify) "proxy_ssl_verify on;")
|
|
||||||
(mkIf cfg.websocket.enable "proxy_cache_bypass $http_upgrade;")
|
(mkIf cfg.websocket.enable "proxy_cache_bypass $http_upgrade;")
|
||||||
] ++ hideHeaders));
|
] ++ hideHeaders));
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,68 +1,50 @@
|
||||||
{
|
let
|
||||||
config,
|
sslModule = { config, nixosConfig, gensokyo-zone, lib, ... }: let
|
||||||
lib,
|
inherit (lib.options) mkOption;
|
||||||
inputs,
|
inherit (lib.modules) mkIf mkMerge mkDefault mkOptionDefault;
|
||||||
...
|
inherit (nixosConfig.services) nginx;
|
||||||
}: let
|
|
||||||
inherit (inputs.self.lib.lib) mkAlmostOptionDefault mkAlmostDefault;
|
|
||||||
inherit (lib.options) mkOption mkEnableOption;
|
|
||||||
inherit (lib.modules) mkIf mkMerge mkDefault mkOptionDefault;
|
|
||||||
inherit (lib.attrsets) mapAttrsToList;
|
|
||||||
inherit (lib.trivial) warnIf;
|
|
||||||
inherit (config.services) nginx;
|
|
||||||
forceRedirectConfig = { virtualHost, xvars }: ''
|
|
||||||
if (${xvars.get.scheme} = http) {
|
|
||||||
return ${toString virtualHost.redirectCode} https://${xvars.get.host}$request_uri;
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
locationModule = { config, virtualHost, xvars, ... }: let
|
|
||||||
cfg = config.ssl;
|
|
||||||
emitForce = cfg.force && !virtualHost.ssl.forced;
|
|
||||||
in {
|
|
||||||
options.ssl = {
|
|
||||||
force = mkEnableOption "redirect to SSL";
|
|
||||||
};
|
|
||||||
config = {
|
|
||||||
xvars.enable = mkIf emitForce true;
|
|
||||||
extraConfig = mkIf emitForce (forceRedirectConfig { inherit xvars virtualHost; });
|
|
||||||
};
|
|
||||||
};
|
|
||||||
sslModule = { config, name, ... }: let
|
|
||||||
cfg = config.ssl;
|
cfg = config.ssl;
|
||||||
in {
|
in {
|
||||||
options.ssl = with lib.types; {
|
options = with lib.types; {
|
||||||
enable = mkOption {
|
ssl = {
|
||||||
type = bool;
|
enable = mkOption {
|
||||||
|
type = bool;
|
||||||
|
};
|
||||||
|
force = mkOption {
|
||||||
|
# TODO: "force-nonlocal"? exceptions for tailscale?
|
||||||
|
type = enum [ false true "only" "reject" ];
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
forced = mkOption {
|
||||||
|
type = bool;
|
||||||
|
readOnly = true;
|
||||||
|
};
|
||||||
|
cert = {
|
||||||
|
name = mkOption {
|
||||||
|
type = nullOr str;
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
|
keyPath = mkOption {
|
||||||
|
type = nullOr path;
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
|
path = mkOption {
|
||||||
|
type = nullOr path;
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
|
copyFromVhost = mkOption {
|
||||||
|
type = nullOr str;
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
|
copyFromStreamServer = mkOption {
|
||||||
|
type = nullOr str;
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
force = mkOption {
|
proxy.ssl = {
|
||||||
# TODO: "force-nonlocal"? exceptions for tailscale?
|
enabled = mkOption {
|
||||||
type = enum [ false true "only" "reject" ];
|
type = bool;
|
||||||
default = false;
|
|
||||||
};
|
|
||||||
forced = mkOption {
|
|
||||||
type = bool;
|
|
||||||
readOnly = true;
|
|
||||||
};
|
|
||||||
cert = {
|
|
||||||
name = mkOption {
|
|
||||||
type = nullOr str;
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
keyPath = mkOption {
|
|
||||||
type = nullOr path;
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
path = mkOption {
|
|
||||||
type = nullOr path;
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
copyFromVhost = mkOption {
|
|
||||||
type = nullOr str;
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
copyFromStreamServer = mkOption {
|
|
||||||
type = nullOr str;
|
|
||||||
default = null;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -85,7 +67,104 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
hostModule = { config, name, xvars, ... }: let
|
sslProxyModule = { config, lib, ... }: let
|
||||||
|
inherit (lib.options) mkOption mkEnableOption;
|
||||||
|
inherit (lib.modules) mkIf mkMerge mkAfter;
|
||||||
|
inherit (config) proxy;
|
||||||
|
cfg = proxy.ssl;
|
||||||
|
in {
|
||||||
|
options.proxy.ssl = with lib.types; {
|
||||||
|
enable = mkOption {
|
||||||
|
type = bool;
|
||||||
|
};
|
||||||
|
verify = mkEnableOption "proxy_ssl_verify";
|
||||||
|
sni = mkEnableOption "proxy_ssl_server_name" // {
|
||||||
|
default = cfg.host != null;
|
||||||
|
};
|
||||||
|
host = mkOption {
|
||||||
|
type = nullOr str;
|
||||||
|
default = null;
|
||||||
|
example = "xvars.get.proxy_host";
|
||||||
|
description = "proxy_ssl_name";
|
||||||
|
# $upstream_last_server_name is commercial-only :<
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config = {
|
||||||
|
extraConfig = mkIf (proxy.enable && cfg.enable) (mkMerge [
|
||||||
|
(mkIf cfg.verify "proxy_ssl_verify on;")
|
||||||
|
(mkIf cfg.sni "proxy_ssl_server_name on;")
|
||||||
|
(mkIf (cfg.host != null) (mkAfter "proxy_ssl_name ${cfg.host};"))
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
streamServerModule = { config, nixosConfig, gensokyo-zone, lib, ... }: let
|
||||||
|
inherit (gensokyo-zone.lib) mkAlmostDefault;
|
||||||
|
inherit (lib.options) mkEnableOption;
|
||||||
|
inherit (lib.modules) mkIf mkMerge mkOptionDefault;
|
||||||
|
cfg = config.ssl;
|
||||||
|
in {
|
||||||
|
imports = [ sslModule sslProxyModule ];
|
||||||
|
options = with lib.types; {
|
||||||
|
ssl = {
|
||||||
|
kTLS = mkEnableOption "kTLS support" // {
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config = let
|
||||||
|
inherit (config) proxy;
|
||||||
|
cert = nixosConfig.security.acme.certs.${cfg.cert.name};
|
||||||
|
conf.ssl.cert = {
|
||||||
|
path = mkIf (cfg.cert.name != null) (mkAlmostDefault "${cert.directory}/fullchain.pem");
|
||||||
|
keyPath = mkIf (cfg.cert.name != null) (mkAlmostDefault "${cert.directory}/key.pem");
|
||||||
|
};
|
||||||
|
conf.proxy.ssl.enable = mkOptionDefault false;
|
||||||
|
#confSsl.listen.ssl = { ssl = true; };
|
||||||
|
confSsl.extraConfig = mkMerge [
|
||||||
|
(mkIf (cfg.cert.path != null) "ssl_certificate ${cfg.cert.path};")
|
||||||
|
(mkIf (cfg.cert.keyPath != null) "ssl_certificate_key ${cfg.cert.keyPath};")
|
||||||
|
(mkIf cfg.kTLS "ssl_conf_command Options KTLS;")
|
||||||
|
];
|
||||||
|
confProxy.extraConfig = mkIf proxy.ssl.enable "proxy_ssl on;";
|
||||||
|
in mkMerge [
|
||||||
|
conf
|
||||||
|
(mkIf cfg.enable confSsl)
|
||||||
|
(mkIf proxy.enable confProxy)
|
||||||
|
];
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
config,
|
||||||
|
gensokyo-zone,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (gensokyo-zone.lib) mkAlmostOptionDefault;
|
||||||
|
inherit (lib.options) mkOption mkEnableOption;
|
||||||
|
inherit (lib.modules) mkIf mkMerge mkDefault mkOptionDefault;
|
||||||
|
inherit (lib.attrsets) mapAttrsToList;
|
||||||
|
inherit (lib.trivial) warnIf;
|
||||||
|
inherit (lib.strings) hasPrefix;
|
||||||
|
inherit (config.services) nginx;
|
||||||
|
forceRedirectConfig = { virtualHost, xvars }: ''
|
||||||
|
if (${xvars.get.scheme} = http) {
|
||||||
|
return ${toString virtualHost.redirectCode} https://${xvars.get.host}$request_uri;
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
locationModule = { config, virtualHost, xvars, ... }: let
|
||||||
|
cfg = config.ssl;
|
||||||
|
emitForce = cfg.force && !virtualHost.ssl.forced;
|
||||||
|
in {
|
||||||
|
imports = [ sslProxyModule ];
|
||||||
|
options.ssl = {
|
||||||
|
force = mkEnableOption "redirect to SSL";
|
||||||
|
};
|
||||||
|
config = {
|
||||||
|
proxy.ssl.enable = mkOptionDefault (hasPrefix "https://" config.proxyPass);
|
||||||
|
xvars.enable = mkIf emitForce true;
|
||||||
|
extraConfig = mkIf emitForce (forceRedirectConfig { inherit xvars virtualHost; });
|
||||||
|
};
|
||||||
|
};
|
||||||
|
hostModule = { config, xvars, ... }: let
|
||||||
cfg = config.ssl;
|
cfg = config.ssl;
|
||||||
emitForce = cfg.forced && config.proxied.enabled;
|
emitForce = cfg.forced && config.proxied.enabled;
|
||||||
in {
|
in {
|
||||||
|
|
@ -124,30 +203,6 @@
|
||||||
extraConfig = mkIf emitForce (forceRedirectConfig { virtualHost = config; inherit xvars; });
|
extraConfig = mkIf emitForce (forceRedirectConfig { virtualHost = config; inherit xvars; });
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
upstreamServerModule = { config, nixosConfig, ... }: let
|
|
||||||
cfg = config.ssl;
|
|
||||||
in {
|
|
||||||
imports = [ sslModule ];
|
|
||||||
options.ssl = with lib.types; {
|
|
||||||
kTLS = mkEnableOption "kTLS support" // {
|
|
||||||
default = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
config = {
|
|
||||||
ssl.cert = let
|
|
||||||
cert = nixosConfig.security.acme.certs.${cfg.cert.name};
|
|
||||||
in {
|
|
||||||
path = mkIf (cfg.cert.name != null) (mkAlmostDefault "${cert.directory}/fullchain.pem");
|
|
||||||
keyPath = mkIf (cfg.cert.name != null) (mkAlmostDefault "${cert.directory}/key.pem");
|
|
||||||
};
|
|
||||||
#listen.ssl = mkIf cfg.enable { ssl = true; };
|
|
||||||
extraConfig = mkIf cfg.enable (mkMerge [
|
|
||||||
(mkIf (cfg.cert.path != null) "ssl_certificate ${cfg.cert.path};")
|
|
||||||
(mkIf (cfg.cert.keyPath != null) "ssl_certificate_key ${cfg.cert.keyPath};")
|
|
||||||
(mkIf cfg.kTLS "ssl_conf_command Options KTLS;")
|
|
||||||
]);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
in {
|
in {
|
||||||
options.services.nginx = with lib.types; {
|
options.services.nginx = with lib.types; {
|
||||||
virtualHosts = mkOption {
|
virtualHosts = mkOption {
|
||||||
|
|
@ -158,7 +213,7 @@ in {
|
||||||
};
|
};
|
||||||
stream.servers = mkOption {
|
stream.servers = mkOption {
|
||||||
type = attrsOf (submoduleWith {
|
type = attrsOf (submoduleWith {
|
||||||
modules = [ upstreamServerModule ];
|
modules = [ streamServerModule ];
|
||||||
shorthandOnlyDefinesConfig = false;
|
shorthandOnlyDefinesConfig = false;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -252,7 +252,7 @@ let
|
||||||
|
|
||||||
config = let
|
config = let
|
||||||
proxyUpstream = nginx.upstreams'.${config.proxy.upstream};
|
proxyUpstream = nginx.upstreams'.${config.proxy.upstream};
|
||||||
proxyScheme = if config.proxy.ssl.enabled then "https" else "http";
|
proxyScheme = if config.proxy.ssl.enable then "https" else "http";
|
||||||
dynamicUpstream = hasPrefix "$" config.proxy.upstream;
|
dynamicUpstream = hasPrefix "$" config.proxy.upstream;
|
||||||
hasUpstream = config.proxy.upstream != null && !dynamicUpstream;
|
hasUpstream = config.proxy.upstream != null && !dynamicUpstream;
|
||||||
proxyHost =
|
proxyHost =
|
||||||
|
|
@ -265,7 +265,7 @@ let
|
||||||
url = mkIf (config.proxy.upstream != null) (mkAlmostOptionDefault
|
url = mkIf (config.proxy.upstream != null) (mkAlmostOptionDefault
|
||||||
"${proxyScheme}://${proxyHost}"
|
"${proxyScheme}://${proxyHost}"
|
||||||
);
|
);
|
||||||
ssl.enabled = mkAlmostOptionDefault (if hasUpstream then proxyUpstream.ssl.enable else false);
|
ssl.enable = mkAlmostOptionDefault (if hasUpstream then proxyUpstream.ssl.enable else false);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue