refactor(nginx): proxy options

This commit is contained in:
arcnmx 2024-04-18 10:40:35 -07:00
parent c3f3fe1fed
commit 02508ecbd3
18 changed files with 638 additions and 424 deletions

30
lib.nix
View file

@ -8,7 +8,7 @@
inherit (nixlib.strings) splitString toLower;
inherit (nixlib.lists) imap0 elemAt findFirst;
inherit (nixlib.attrsets) mapAttrs listToAttrs nameValuePair;
inherit (nixlib.strings) hasPrefix hasInfix substring fixedWidthString replaceStrings concatMapStringsSep;
inherit (nixlib.strings) hasPrefix hasInfix removePrefix substring fixedWidthString replaceStrings concatMapStringsSep match toInt;
inherit (nixlib.trivial) flip toHexString bitOr;
toHexStringLower = v: toLower (toHexString v);
@ -31,6 +31,18 @@
nibble0 + (fixedWidthString 1 "0" (toHexStringLower nibble1));
in "${part0 (part 0)}${part 1}:${part 2}ff:fe${part 3}:${part 4}${part 5}";
parseUrl = url: let
parts = match ''^([^:]+)://(\[[0-9a-fA-F:]+]|[^/:\[]+)(|:[0-9]+)(|/.*)$'' url;
port' = elemAt parts 2;
in assert parts != null; rec {
inherit url parts;
scheme = elemAt parts 0;
host = elemAt parts 1;
port = if port' != "" then toInt (removePrefix ":" port') else null;
hostport = host + port';
path = elemAt parts 3;
};
userIs = group: user: builtins.elem group (user.extraGroups ++ [user.group]);
mkWinPath = replaceStrings ["/"] ["\\"];
@ -51,11 +63,17 @@
mkAlmostOptionDefault = mkOverride overrideAlmostOptionDefault;
mkAlmostDefault = mkOverride overrideAlmostDefault;
mkAlmostForce = mkOverride overrideAlmostForce;
orderJustBefore = 400;
orderBefore = 500;
orderAlmostBefore = 600;
orderNone = 1000;
orderAfter = 1500;
orderAlmostAfter = 1400;
mkAlmostAfter = mkOrder 1400;
orderAfter = 1500;
orderJustAfter = 1600;
mkJustBefore = mkOrder orderJustBefore;
mkAlmostBefore = mkOrder orderAlmostBefore;
mkAlmostAfter = mkOrder orderAlmostAfter;
mkJustAfter = mkOrder orderJustAfter;
mapOverride = priority: mapAttrs (_: mkOverride priority);
mapOptionDefaults = mapOverride overrideOptionDefault;
mapAlmostOptionDefaults = mapOverride overrideAlmostOptionDefault;
@ -79,13 +97,13 @@ in {
lib = {
domain = "gensokyo.zone";
inherit treeToModulesOutput userIs
eui64 mkWinPath mkBaseDn mkAddress6
eui64 parseUrl mkWinPath mkBaseDn mkAddress6
toHexStringLower hexCharToInt
mapListToAttrs coalesce
mkAlmostOptionDefault mkAlmostDefault mkAlmostForce mapOverride mapOptionDefaults mapAlmostOptionDefaults mapDefaults
overrideOptionDefault overrideAlmostOptionDefault overrideDefault overrideAlmostDefault overrideNone overrideAlmostForce overrideForce overrideVM
orderBefore orderNone orderAfter orderAlmostAfter
mkAlmostAfter;
orderJustBefore orderBefore orderAlmostBefore orderNone orderAfter orderAlmostAfter orderJustAfter
mkJustBefore mkAlmostBefore mkAlmostAfter mkJustAfter;
inherit (inputs.arcexprs.lib) unmerged json;
};
gensokyo-zone = {

View file

@ -56,7 +56,7 @@
set ${varPrefix}client 1;
}
'';
localModule = {config, ...}: let
localModule = {config, xvars, ...}: let
cfg = config.local;
in {
options.local = with lib.types; {
@ -100,7 +100,7 @@
in mkMerge [
(mkIf cfg.emitDenyGlobal (mkBefore allowDirectives))
(mkIf cfg.emitVars (mkBefore (mkAddrVar "$remote_addr" "$local_")))
(mkIf cfg.emitVars (mkBefore (mkAddrVar "$x_remote_addr" "$x_local_")))
(mkIf (cfg.emitVars && config.xvars.enable) (mkBefore (mkAddrVar (xvars.remote_addr.get) "$x_local_")))
];
};
};
@ -130,13 +130,7 @@
options = with lib.types; {
locations = mkOption {
type = attrsOf (submoduleWith {
modules = [locationModule];
shorthandOnlyDefinesConfig = true;
specialArgs = {
virtualHost = config;
};
});
type = attrsOf (submodule [locationModule]);
};
};
@ -149,13 +143,7 @@
in {
options = with lib.types; {
services.nginx.virtualHosts = mkOption {
type = attrsOf (submoduleWith {
modules = [hostModule];
shorthandOnlyDefinesConfig = true;
specialArgs = {
nixosConfig = config;
};
});
type = attrsOf (submodule [hostModule]);
};
};
}

View file

@ -1,57 +1,27 @@
{
config,
lib,
inputs,
...
}: let
inherit (inputs.self.lib.lib) mkAlmostAfter mkAlmostOptionDefault;
inherit (lib.options) mkOption mkEnableOption;
inherit (lib.modules) mkIf mkMerge mkBefore mkDefault mkOptionDefault;
inherit (lib.strings) optionalString splitString match;
inherit (lib.attrsets) attrValues;
inherit (lib.lists) length head /*optional*/ any;
inherit (lib.trivial) mapNullable;
#inherit (config) networking;
inherit (config.services) nginx;
schemeForUrl = url: let
parts = splitString ":" url;
in if length parts == 1 then null else head parts;
pathForUrl = url: let
parts = match ''[^:]+://[^/]+(.*)'' url;
in if parts == null then null else head parts;
hostForUrl = url: let
parts = match ''[^:]+://([^/]+).*'' url;
in if parts == null then null else head parts;
xHeadersDefaults = ''
set $x_scheme $scheme;
set $x_forwarded_for $remote_addr;
set $x_remote_addr $remote_addr;
set $x_forwarded_host $host;
set $x_forwarded_server $host;
set $x_host $host;
set $x_referer $http_referer;
set $x_proxy_host $x_host;
'';
xHeadersProxied = ''
set $x_forwarded_for $proxy_add_x_forwarded_for;
inherit (inputs.self.lib.lib) mkJustBefore mkAlmostOptionDefault orderJustBefore;
inherit (lib.options) mkOption;
inherit (lib.modules) mkIf mkMerge mkOrder mkDefault mkOptionDefault;
xHeadersProxied = { xvars }: ''
${xvars.init "forwarded_for" "$proxy_add_x_forwarded_for"}
if ($http_x_forwarded_proto) {
set $x_scheme $http_x_forwarded_proto;
${xvars.init "scheme" "$http_x_forwarded_proto"}
}
if ($http_x_real_ip) {
set $x_remote_addr $http_x_real_ip;
${xvars.init "remote_addr" "$http_x_real_ip"}
}
if ($http_x_forwarded_host) {
set $x_forwarded_host $http_x_forwarded_host;
${xvars.init "host" "$http_x_forwarded_host"}
}
if ($http_x_forwarded_server) {
set $x_forwarded_server $http_x_forwarded_server;
}
if ($x_referer ~ "^https?://([^/]*)/(.*)$") {
set $x_referer_host $1;
set $x_referer_path $2;
${xvars.init "forwarded_server" "$http_x_forwarded_server"}
}
'';
locationModule = { config, virtualHost, ... }: let
locationModule = { config, virtualHost, xvars, ... }: let
cfg = config.proxied;
in {
options = with lib.types; {
@ -64,94 +34,30 @@
type = bool;
readOnly = true;
};
xvars.enable = mkEnableOption "$x_variables";
redirectScheme = mkEnableOption "redirect to X-Forwarded-Proto" // {
default = cfg.enabled;
};
rewriteReferer = mkEnableOption "rewrite Referer header" // {
default = cfg.enabled;
};
};
proxy = {
enabled = mkOption {
type = bool;
readOnly = true;
};
scheme = mkOption {
type = nullOr str;
};
path = mkOption {
type = nullOr str;
};
host = mkOption {
type = nullOr str;
};
headers.enableRecommended = mkOption {
type = enum [ true false "nixpkgs" ];
};
};
};
config = let
emitVars = cfg.enabled && !virtualHost.proxied.enabled;
emitRedirectScheme = config.proxy.enabled && cfg.redirectScheme;
emitRefererRewrite = config.proxy.enabled && cfg.rewriteReferer;
emitHeaders = config.proxy.enabled && config.proxy.headers.enableRecommended == true;
in {
proxied = {
enabled = mkOptionDefault (virtualHost.proxied.enabled || cfg.enable != false);
xvars.enable = mkIf (cfg.enabled || emitRedirectScheme || emitHeaders) true;
};
proxy = {
enabled = mkOptionDefault (config.proxyPass != null);
headers.enableRecommended = mkOptionDefault (
if !virtualHost.recommendedProxySettings then false
else if cfg.enabled then true
else "nixpkgs"
);
scheme = mkOptionDefault (
mapNullable schemeForUrl config.proxyPass
);
path = mkOptionDefault (
mapNullable pathForUrl config.proxyPass
);
host = mkOptionDefault (
mapNullable hostForUrl config.proxyPass
);
headers = {
enableRecommended = mkIf cfg.enabled (mkAlmostOptionDefault true);
rewriteReferer.enable = mkIf cfg.enabled (mkAlmostOptionDefault true);
};
recommendedProxySettings = mkMerge [
(mkAlmostOptionDefault (config.proxy.headers.enableRecommended == "nixpkgs"))
];
redirect.enable = mkIf cfg.enabled (mkAlmostOptionDefault true);
};
xvars.enable = mkIf cfg.enabled true;
extraConfig = mkMerge [
(mkIf emitVars (
mkBefore xHeadersProxied
mkJustBefore (xHeadersProxied { inherit xvars; })
))
(mkIf emitRedirectScheme ''
proxy_redirect ${config.proxy.scheme}://$host/ $x_scheme://$host/;
'')
(mkIf emitRefererRewrite ''
if ($x_referer_host = $host) {
set $x_referer "${config.proxy.scheme}://${config.proxy.host}/$x_referer_path";
}
'')
(mkIf emitHeaders (mkAlmostAfter ''
if ($x_proxy_host = "") {
set $x_proxy_host $proxy_host;
}
if ($x_proxy_host = "") {
set $x_proxy_host ${config.proxy.host};
}
proxy_set_header Host $x_proxy_host;
proxy_set_header Referer $x_referer;
proxy_set_header X-Real-IP $x_remote_addr;
proxy_set_header X-Forwarded-For $x_forwarded_for;
proxy_set_header X-Forwarded-Proto $x_scheme;
proxy_set_header X-Forwarded-Host $x_forwarded_host;
proxy_set_header X-Forwarded-Server $x_forwarded_server;
''))
];
};
};
hostModule = { config, ... }: let
hostModule = { config, xvars, ... }: let
cfg = config.proxied;
in {
options = with lib.types; {
@ -164,13 +70,6 @@
type = bool;
default = cfg.enable != false;
};
xvars.enable = mkEnableOption "$x_variables" // {
default = cfg.enabled;
};
};
recommendedProxySettings = mkOption {
type = bool;
default = nginx.recommendedProxySettings;
};
locations = mkOption {
type = attrsOf (submoduleWith {
@ -181,23 +80,17 @@
};
config = {
proxied = {
xvars.enable = mkIf (any (loc: loc.proxied.xvars.enable) (attrValues config.locations)) true;
};
xvars.enable = mkIf cfg.enabled true;
local.denyGlobal = mkIf (cfg.enable == "cloudflared") (mkDefault true);
extraConfig = mkIf cfg.xvars.enable (mkBefore ''
${xHeadersDefaults}
${optionalString cfg.enabled xHeadersProxied}
'');
extraConfig = mkIf (cfg.enabled && config.xvars.enable) (
mkOrder (orderJustBefore + 25) (xHeadersProxied { inherit xvars; })
);
};
};
in {
options = with lib.types; {
services.nginx.virtualHosts = mkOption {
type = attrsOf (submoduleWith {
modules = [ hostModule ];
shorthandOnlyDefinesConfig = true;
});
type = attrsOf (submodule [hostModule]);
};
};
}

View file

@ -0,0 +1,214 @@
let
locationModule = { config, name, virtualHost, xvars, gensokyo-zone, lib, ... }: let
inherit (gensokyo-zone.lib) mkJustBefore mkJustAfter mkAlmostOptionDefault mapOptionDefaults coalesce parseUrl;
inherit (lib.options) mkOption mkEnableOption;
inherit (lib.modules) mkIf mkMerge mkBefore mkOptionDefault;
inherit (lib.attrsets) filterAttrs mapAttrsToList;
inherit (lib.strings) hasPrefix removeSuffix concatStringsSep;
inherit (lib.trivial) mapNullable;
cfg = config.proxy;
in {
options = with lib.types; {
proxy = {
enable = mkEnableOption "proxy";
enabled = mkOption {
type = bool;
readOnly = true;
};
url = mkOption {
type = str;
};
path = mkOption {
type = str;
};
host = mkOption {
type = nullOr str;
};
websocket.enable = mkEnableOption "websocket proxy" // {
default = virtualHost.proxy.websocket.enable;
};
parsed = {
scheme = mkOption {
type = nullOr str;
};
path = mkOption {
type = nullOr str;
};
host = mkOption {
type = nullOr str;
};
hostport = mkOption {
type = nullOr str;
};
port = mkOption {
type = nullOr int;
};
};
headers = {
enableRecommended = mkOption {
type = enum [ true false "nixpkgs" ];
};
rewriteReferer.enable = mkEnableOption "rewrite referer host";
set = mkOption {
type = attrsOf (nullOr str);
};
};
redirect = {
enable = mkEnableOption "proxy_redirect";
fromHost = mkOption {
type = str;
default = xvars.get.host;
example = "xvars.get.proxy_host";
};
fromScheme = mkOption {
type = str;
default = xvars.get.scheme;
example = "xvars.get.proxy_scheme";
};
};
};
};
config = let
emitHeaders = setHeaders' != { };
url = parseUrl config.proxyPass;
recommendedHeaders = {
Host = if cfg.host == null then xvars.get.proxy_host else cfg.host;
Referer = xvars.get.referer;
X-Real-IP = xvars.get.remote_addr;
X-Forwarded-For = xvars.get.forwarded_for;
X-Forwarded-Proto = xvars.get.scheme;
X-Forwarded-Host = xvars.get.host;
X-Forwarded-Server = xvars.get.forwarded_server;
};
initProxyVars = ''
${xvars.init "proxy_scheme" cfg.parsed.scheme}
${xvars.init "proxy_host" "$proxy_host"}
if (${xvars.get.proxy_host} = "") {
${xvars.init "proxy_host" cfg.parsed.hostport}
}
'';
hostHeader = coalesce [
cfg.headers.set.Host or null
cfg.host
xvars.get.proxy_host
];
rewriteReferer = ''
set $x_set_referer ${xvars.get.referer};
if (${xvars.get.referer_host} = $host) {
set $x_set_referer ${config.proxy.parsed.scheme}://${hostHeader}${xvars.get.referer_path};
}
'';
redirect = ''
proxy_redirect ${cfg.redirect.fromScheme}://${cfg.redirect.fromHost}/ ${xvars.get.scheme}://${xvars.get.host}/;
'';
setHeaders' = filterAttrs (_: header: header != null) cfg.headers.set;
setHeaders = concatStringsSep "\n" (mapAttrsToList (
name: value: "proxy_set_header ${name} ${xvars.escapeString value};"
) setHeaders');
in {
proxy = {
enabled = mkOptionDefault (config.proxyPass != null);
path = mkIf (hasPrefix "/" name) (mkOptionDefault name);
url = mkIf (virtualHost.proxy.url != null) (mkOptionDefault virtualHost.proxy.url);
headers = {
enableRecommended = mkOptionDefault (
if cfg.enable && virtualHost.proxy.headers.enableRecommended != false then true
else virtualHost.proxy.headers.enableRecommended
);
set = mkMerge [
(mkOptionDefault { })
(mkIf (cfg.headers.enableRecommended == true) (mapOptionDefaults recommendedHeaders))
(mkIf (cfg.host != null) {
Host = mkIf (cfg.headers.enableRecommended != "nixpkgs") (mkAlmostOptionDefault cfg.host);
})
(mkIf cfg.headers.rewriteReferer.enable {
Referer = mkAlmostOptionDefault "$x_set_referer";
})
(mkIf cfg.websocket.enable (mapOptionDefaults {
Upgrade = "$http_upgrade";
Connection = "upgrade";
}))
];
};
host = mkOptionDefault (
if virtualHost.proxy.host != null then virtualHost.proxy.host
else if cfg.headers.enableRecommended == false then null
else xvars.get.host
);
parsed = {
scheme = mkOptionDefault (
mapNullable (_: url.scheme) config.proxyPass
);
path = mkOptionDefault (
mapNullable (_: url.path) config.proxyPass
);
host = mkOptionDefault (
mapNullable (_: url.host) config.proxyPass
);
hostport = mkOptionDefault (
mapNullable (_: url.hostport) config.proxyPass
);
port = mkOptionDefault (
mapNullable (_: url.port) config.proxyPass
);
};
};
proxyPass = mkIf cfg.enable (mkAlmostOptionDefault (removeSuffix "/" cfg.url + cfg.path));
recommendedProxySettings = mkAlmostOptionDefault (cfg.headers.enableRecommended == "nixpkgs");
extraConfig = mkMerge [
(mkIf (cfg.enabled && virtualHost.xvars.enable) (mkJustBefore initProxyVars))
(mkIf (cfg.enabled && cfg.headers.rewriteReferer.enable) (mkJustBefore rewriteReferer))
(mkIf (cfg.enabled && cfg.redirect.enable) (mkBefore redirect))
(mkIf (cfg.enabled && emitHeaders) (mkJustAfter setHeaders))
];
};
};
hostModule = { config, nixosConfig, lib, ... }: let
inherit (lib.options) mkOption mkEnableOption;
inherit (lib.modules) mkIf;
inherit (lib.attrsets) attrValues;
inherit (lib.lists) any;
inherit (nixosConfig.services) nginx;
cfg = config.proxy;
in {
options = with lib.types; {
proxy = {
host = mkOption {
type = nullOr str;
default = null;
};
url = mkOption {
type = nullOr str;
default = null;
};
websocket.enable = mkEnableOption "websocket proxy";
headers.enableRecommended = mkOption {
type = enum [ true false "nixpkgs" ];
default = if nginx.recommendedProxySettings then "nixpkgs" else false;
};
};
locations = mkOption {
type = attrsOf (submoduleWith {
modules = [ locationModule ];
shorthandOnlyDefinesConfig = true;
});
};
};
config = let
needsReferer = loc: loc.proxy.enabled && loc.proxy.headers.rewriteReferer.enable;
in {
xvars.parseReferer = mkIf (any needsReferer (attrValues config.locations)) true;
};
};
in {
lib,
...
}: let
inherit (lib.options) mkOption;
in {
options = with lib.types; {
services.nginx.virtualHosts = mkOption {
type = attrsOf (submodule [hostModule]);
};
};
}

View file

@ -10,9 +10,11 @@
inherit (lib.attrsets) mapAttrsToList;
inherit (lib.trivial) warnIf;
inherit (config.services) nginx;
forceRedirectConfig = virtualHost: ''
if ($x_scheme = http) {
return ${toString virtualHost.redirectCode} https://$x_forwarded_host$request_uri;
forceRedirectConfig = virtualHost: let
xvars = virtualHost.xvars.lib;
in ''
if (${xvars.get.scheme} = http) {
return ${toString virtualHost.redirectCode} https://${xvars.get.host}$request_uri;
}
'';
locationModule = { config, virtualHost, ... }: let
@ -23,7 +25,7 @@
force = mkEnableOption "redirect to SSL";
};
config = {
proxied.xvars.enable = mkIf emitForce true;
xvars.enable = mkIf emitForce true;
extraConfig = mkIf emitForce (forceRedirectConfig virtualHost);
};
};
@ -119,7 +121,7 @@
sslCertificate = mkIf (cfg.cert.path != null) (mkAlmostOptionDefault cfg.cert.path);
sslCertificateKey = mkIf (cfg.cert.keyPath != null) (mkAlmostOptionDefault cfg.cert.keyPath);
proxied.xvars.enable = mkIf emitForce true;
xvars.enable = mkIf emitForce true;
extraConfig = mkIf emitForce (forceRedirectConfig config);
};
};

View file

@ -8,11 +8,11 @@
inherit (lib.options) mkOption mkEnableOption;
inherit (lib.modules) mkIf mkMerge mkBefore mkAfter mkOptionDefault;
inherit (lib.attrsets) mapAttrsToList;
inherit (lib.strings) toLower replaceStrings;
inherit (lib.strings) toLower replaceStrings removePrefix;
inherit (config) networking;
inherit (config.services) vouch-proxy nginx tailscale;
inherit (nginx) vouch;
locationModule = {config, virtualHost, ...}: {
locationModule = {config, virtualHost, xvars, ...}: {
options.vouch = with lib.types; {
requireAuth = mkEnableOption "require auth to access this location";
setProxyHeader = mkOption {
@ -33,20 +33,19 @@
(mkBefore virtualHost.vouch.auth.lua.accessLogic)
];
};
proxied.xvars.enable = mkIf (enableVouchTail || virtualHost.vouch.auth.lua.enable) true;
xvars.enable = mkIf (enableVouchTail || virtualHost.vouch.auth.lua.enable) true;
proxy.headers.set.X-Vouch-User = mkOptionDefault "$auth_resp_x_vouch_user";
extraConfig = assert virtualHost.vouch.enable; mkMerge [
(mkIf (!virtualHost.vouch.requireAuth) virtualHost.vouch.auth.requestDirective)
(allowOrigin vouch.url)
(allowOrigin vouch.authUrl)
(mkIf enableVouchLocal (allowOrigin vouch.localUrl))
(mkIf enableVouchTail (allowOrigin "$x_scheme://${vouch.tailDomain}"))
(mkIf config.vouch.setProxyHeader ''
proxy_set_header X-Vouch-User $auth_resp_x_vouch_user;
'')
(mkIf enableVouchLocal (allowOrigin "sso.local.${networking.domain}"))
(mkIf enableVouchTail (allowOrigin "${xvars.get.scheme}://${vouch.tailDomain}"))
];
};
};
hostModule = {config, ...}: let
hostModule = {config, xvars, ...}: let
cfg = config.vouch;
mkHeaderVar = header: toLower (replaceStrings [ "-" ] [ "_" ] header);
mkUpstreamVar = header: "\$upstream_http_${mkHeaderVar header}";
@ -113,7 +112,7 @@
if ngx.ctx.auth_res ~= nil and ngx.ctx.auth_res.status == ngx.HTTP_UNAUTHORIZED then
local vouch_url = ngx.var["vouch_url"] or "${vouch.url}"
local query_args = ngx.encode_args {
url = string.format("%s://%s%s", ngx.var.x_scheme, ngx.var.x_forwarded_host, ngx.var.request_uri),
url = string.format("%s://%s%s", ngx.var.${removePrefix "$" xvars.get.scheme}, ngx.var.${removePrefix "$" xvars.get.host}, ngx.var.request_uri),
["X-Vouch-Token"] = ngx.ctx.auth_res.header["X-Vouch-Token"] or "",
error = ngx.ctx.auth_res.header["X-Vouch-Error"] or "",
-- ["vouch-failcount"] is now a session variable and shouldn't be needed anymore
@ -145,13 +144,13 @@
};
extraConfig = let
localVouchUrl = ''
if ($x_forwarded_host ~ "\.local\.${networking.domain}$") {
if (${xvars.get.host} ~ "\.local\.${networking.domain}$") {
set $vouch_url ${vouch.localUrl};
}
'';
tailVouchUrl = ''
if ($x_forwarded_host ~ "\.tail\.${networking.domain}$") {
set $vouch_url $x_scheme://${vouch.tailDomain};
if (${xvars.get.host} ~ "\.tail\.${networking.domain}$") {
set $vouch_url ${xvars.get.scheme}://${vouch.tailDomain};
}
'';
setVouchUrl = [
@ -170,33 +169,32 @@
mkBefore "auth_request_set \$${authVar} ${mkUpstreamVar header};"
)) cfg.auth.variables
));
proxied.xvars.enable = mkIf cfg.enable true;
xvars.enable = mkIf cfg.enable true;
locations = mkIf cfg.enable {
"/" = mkIf cfg.requireAuth {
vouch.requireAuth = mkAlmostOptionDefault true;
};
${cfg.auth.errorLocation} = mkIf (cfg.auth.errorLocation != null) {
proxied.xvars.enable = true;
xvars.enable = true;
extraConfig = ''
return 302 $vouch_url/login?url=$x_scheme://$x_forwarded_host$request_uri&X-Vouch-Token=$auth_resp_jwt&error=$auth_resp_err;
return 302 $vouch_url/login?url=${xvars.get.scheme}://${xvars.get.host}$request_uri&X-Vouch-Token=$auth_resp_jwt&error=$auth_resp_err;
'';
};
${cfg.auth.requestLocation} = { config, ... }: {
proxyPass = "${vouch.proxyOrigin}/validate";
proxy.headers.enableRecommended = false;
proxied.rewriteReferer = false;
extraConfig = let
${cfg.auth.requestLocation} = { config, xvars, ... }: {
proxy = {
enable = true;
url = vouch.proxyOrigin;
# nginx-proxied vouch must use X-Forwarded-Host, but vanilla vouch requires Host
vouchProxyHost = if vouch.doubleProxy.enable
host = if vouch.doubleProxy.enable
then (if cfg.localSso.enable then vouch.doubleProxy.localServerName else vouch.doubleProxy.serverName)
else "$x_forwarded_host";
in ''
proxy_set_header Host ${vouchProxyHost};
proxy_set_header X-Forwarded-Host $x_forwarded_host;
proxy_set_header Referer $x_referer;
proxy_set_header X-Forwarded-Proto $x_scheme;
else xvars.get.host;
headers = {
set.Content-Length = "";
rewriteReferer.enable = false;
};
};
extraConfig = ''
proxy_pass_request_body off;
proxy_set_header Content-Length "";
'';
};
};

View file

@ -1,30 +0,0 @@
{lib, ...}: let
inherit (lib.modules) mkIf;
inherit (lib.options) mkOption mkEnableOption;
wsModule = {config, ...}: {
options = with lib.types; {
proxy.websocket.enable = mkEnableOption "websocket proxy";
};
config = mkIf config.proxy.websocket.enable {
extraConfig = ''
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
'';
};
};
hostModule = {config, ...}: {
imports = [wsModule];
options = with lib.types; {
locations = mkOption {
type = attrsOf (submodule wsModule);
};
};
};
in {
options = with lib.types; {
services.nginx.virtualHosts = mkOption {
type = attrsOf (submodule hostModule);
};
};
}

View file

@ -0,0 +1,110 @@
let
locationModule = { config, virtualHost, lib, ... }: let
inherit (lib.options) mkEnableOption;
cfg = config.xvars;
in {
options.xvars = with lib.types; {
enable = mkEnableOption "$x_variables";
};
config = let
in {
};
};
hostModule = { config, nixosConfig, gensokyo-zone, xvars, lib, ... }: let
inherit (gensokyo-zone.lib) mkJustBefore;
inherit (lib.options) mkOption mkEnableOption;
inherit (lib.modules) mkIf mkMerge mkOptionDefault;
inherit (lib.strings) concatStringsSep;
inherit (lib.attrsets) attrValues filterAttrs mapAttrs mapAttrsToList;
inherit (lib.lists) any;
cfg = config.xvars;
escapeString = value: if value == "" then ''""'' else value;
in {
options = with lib.types; {
xvars = {
enable = mkEnableOption "$x_variables";
parseReferer = mkEnableOption "$x_referer_{scheme,host,path}";
defaults = mkOption {
type = attrsOf (nullOr str);
default = rec {
scheme = "$scheme";
forwarded_for = remote_addr;
remote_addr = "$remote_addr";
forwarded_server = host;
host = "$host";
referer = "$http_referer";
proxy_host = null;
proxy_scheme = null;
};
};
lib = mkOption {
type = attrs;
};
};
locations = mkOption {
type = attrsOf (submoduleWith {
modules = [ locationModule ];
shorthandOnlyDefinesConfig = true;
specialArgs = {
inherit nixosConfig gensokyo-zone xvars;
virtualHost = config;
};
});
};
};
config = let
defaults = concatStringsSep "\n" (mapAttrsToList (
name: value: "set $x_${name} ${escapeString value};"
) (filterAttrs (_: value: value != null) cfg.defaults));
parseReferer = ''
if (${xvars.get.referer} ~ "^(https?)://([^/]*)(/.*)$") {
${xvars.init "referer_scheme" "$1"}
${xvars.init "referer_host" "$2"}
${xvars.init "referer_path" "$3"}
}
'';
in {
xvars = {
enable = mkMerge [
(mkIf (any (loc: loc.xvars.enable) (attrValues config.locations)) true)
(mkIf cfg.parseReferer true)
];
defaults = mkIf cfg.parseReferer (mkOptionDefault {
referer_scheme = null;
referer_host = null;
referer_path = null;
});
lib = {
get = mapAttrs (name: default: if cfg.enable then "$x_${name}" else assert default != null; default) cfg.defaults;
init = name: value: assert cfg.enable && cfg.defaults ? ${name}; "set $x_${name} ${escapeString value};";
inherit escapeString;
};
};
extraConfig = mkMerge [
(mkIf cfg.enable (mkJustBefore defaults))
(mkIf (cfg.enable && cfg.parseReferer) (mkJustBefore parseReferer))
];
_module.args.xvars = config.xvars.lib;
};
};
in {
config,
lib,
gensokyo-zone,
...
}: let
inherit (lib.options) mkOption;
in {
options = with lib.types; {
services.nginx.virtualHosts = mkOption {
type = attrsOf (submoduleWith {
modules = [ hostModule ];
shorthandOnlyDefinesConfig = true;
specialArgs = {
inherit gensokyo-zone;
nixosConfig = config;
};
});
};
};
}

View file

@ -7,9 +7,6 @@
inherit (config.services) barcodebuddy nginx;
name.shortServer = mkDefault "bbuddy";
serverName = "@bbuddy_internal";
extraConfig = ''
set $x_proxy_host ${serverName};
'';
in {
config.services.nginx.virtualHosts = {
barcodebuddy'php = mkIf barcodebuddy.enable {
@ -18,35 +15,44 @@ in {
local.denyGlobal = true;
};
barcodebuddy = {
inherit name extraConfig;
inherit name;
vouch = {
enable = true;
requireAuth = false;
};
locations = {
"/api/" = {
proxy.headers.enableRecommended = true;
proxyPass = mkDefault "${nginx.virtualHosts.barcodebuddy.locations."/".proxyPass}/api/";
};
"/" = {
proxy.headers.enableRecommended = true;
vouch.requireAuth = true;
proxyPass = mkIf barcodebuddy.enable (mkDefault
proxy = {
url = mkIf barcodebuddy.enable (mkDefault
"http://localhost:${toString nginx.defaultHTTPListenPort}"
);
host = mkDefault serverName;
};
locations = {
"/api/" = {
proxy.enable = true;
};
"/" = {
proxy.enable = true;
vouch.requireAuth = true;
};
};
};
barcodebuddy'local = {
inherit name extraConfig;
inherit name;
ssl.cert.copyFromVhost = "barcodebuddy";
local.enable = mkDefault true;
locations."/" = {
proxy.headers.enableRecommended = true;
proxy = {
url = mkDefault nginx.virtualHosts.barcodebuddy.proxy.url;
host = mkDefault nginx.virtualHosts.barcodebuddy.proxy.host;
};
locations."/" = { config, ... }: {
proxy = {
headers.enableRecommended = true;
redirect = {
enable = true;
fromHost = config.proxy.host;
};
};
proxyPass = mkDefault nginx.virtualHosts.barcodebuddy.locations."/".proxyPass;
extraConfig = ''
proxy_redirect $x_scheme://${serverName}/ $x_scheme://$x_host/;
'';
};
};
};

View file

@ -18,31 +18,28 @@ let
ssl_verify_client optional_no_ca;
'';
locations' = domain: {
"/" = {
"/" = { config, xvars, ... }: {
proxy = {
enable = true;
url = mkDefault access.proxyPass;
host = mkDefault domain;
headers = {
rewriteReferer.enable = true;
set = {
X-SSL-CERT = "$ssl_client_escaped_cert";
};
};
redirect = {
enable = true;
fromHost = config.proxy.host;
fromScheme = xvars.get.proxy_scheme;
};
};
proxyPass = mkDefault access.proxyPass;
recommendedProxySettings = false;
extraConfig = ''
proxy_set_header Host ${domain};
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-SSL-CERT $ssl_client_escaped_cert;
proxy_redirect https://${domain}/ $scheme://$host/;
proxy_ssl_server_name on;
proxy_ssl_name ${domain};
set $x_referer $http_referer;
if ($x_referer ~ "^https://([^/]*)/(.*)$") {
set $x_referer_host $1;
set $x_referer_path $2;
}
if ($x_referer_host = $host) {
set $x_referer "https://${domain}/$x_referer_path";
}
proxy_set_header Referer $x_referer;
'';
};
};

View file

@ -4,7 +4,7 @@
lib,
...
}: let
inherit (lib.modules) mkIf mkDefault;
inherit (lib.modules) mkIf mkMerge mkDefault;
inherit (lib.lists) optional;
inherit (config.services) nginx;
system = access.systemForService "freepbx";
@ -15,38 +15,50 @@ in {
proxyScheme = "https";
url = access.proxyUrlFor { serviceName = "freepbx"; portName = proxyScheme; };
ucpUrl = access.proxyUrlFor { serviceName = "freepbx"; portName = "ucp-ssl"; };
ucpPath = "/socket.io";
# TODO: ports.asterisk/asterisk-ssl?
extraConfig = ''
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
set $pbx_scheme $scheme;
if ($http_x_forwarded_proto) {
set $pbx_scheme $http_x_forwarded_proto;
}
proxy_redirect ${proxyScheme}://$host/ $pbx_scheme://$host/;
'';
locations = {
"/" = {
proxyPass = mkDefault url;
"/" = { xvars, ... }: {
xvars.enable = true;
proxy = {
enable = true;
redirect = {
enable = true;
fromScheme = xvars.get.proxy_scheme;
};
};
};
${ucpPath} = { xvars, virtualHost, ... }: {
proxy = {
enable = true;
websocket.enable = true;
};
"/socket.io" = {
proxy.websocket.enable = true;
proxyPass = mkDefault "${ucpUrl}/socket.io";
extraConfig = ''
proxy_hide_header Access-Control-Allow-Origin;
add_header Access-Control-Allow-Origin $pbx_scheme://$host;
add_header Access-Control-Allow-Origin ${xvars.get.scheme}://${virtualHost.serverName};
'';
};
};
allLocations = mkMerge [
locations
{
${ucpPath}.proxy.url = mkDefault nginx.virtualHosts.freepbx'ucp.proxy.url;
}
];
name.shortServer = mkDefault "pbx";
kTLS = mkDefault true;
in {
freepbx = {
vouch.enable = mkDefault true;
ssl.force = true;
inherit name locations extraConfig kTLS;
proxy.url = mkDefault url;
locations = allLocations;
inherit name extraConfig kTLS;
};
freepbx'ucp = {
serverName = mkDefault nginx.virtualHosts.freepbx.serverName;
@ -62,12 +74,14 @@ in {
extraParameters = [ "default_server" ];
};
};
proxy.websocket.enable = true;
proxy = {
url = mkDefault ucpUrl;
websocket.enable = true;
};
vouch.enable = mkDefault true;
local.denyGlobal = mkDefault nginx.virtualHosts.freepbx.local.denyGlobal;
locations."/socket.io" = {
inherit (locations."/socket.io") proxy extraConfig;
proxyPass = mkDefault nginx.virtualHosts.freepbx.locations."/socket.io".proxyPass;
locations = {
inherit (locations) "/socket.io";
};
inherit extraConfig kTLS;
};
@ -84,16 +98,9 @@ in {
};
};
ssl.cert.copyFromVhost = "freepbx";
proxy.url = mkDefault nginx.virtualHosts.freepbx.proxy.url;
local.enable = true;
locations = {
"/" = {
proxyPass = mkDefault nginx.virtualHosts.freepbx.locations."/".proxyPass;
};
"/socket.io" = {
inherit (locations."/socket.io") proxy extraConfig;
proxyPass = mkDefault nginx.virtualHosts.freepbx.locations."/socket.io".proxyPass;
};
};
locations = allLocations;
inherit name extraConfig kTLS;
};
};

View file

@ -3,25 +3,24 @@
lib,
...
}: let
inherit (lib.modules) mkIf mkMerge mkDefault;
inherit (lib.strings) escapeRegex;
inherit (lib.modules) mkIf mkMerge mkDefault mkOptionDefault;
inherit (lib.strings) removePrefix escapeRegex;
inherit (config.services) grocy nginx;
inherit (config) networking;
name.shortServer = mkDefault "grocy";
serverName = "@grocy_internal";
serverName'local = "@grocy_internal_local";
extraConfig = ''
set $x_proxy_host ${serverName};
set $grocy_user "";
'';
location = {
locations."/" = {
vouch.setProxyHeader = true;
proxy.headers.enableRecommended = true;
extraConfig = ''
proxy_set_header X-Grocy-User $grocy_user;
'';
proxy = {
enable = true;
headers.set.X-Grocy-User = mkOptionDefault "$grocy_user";
};
luaAuthHost = { config, ... }: {
};
luaAuthHost = { config, xvars, ... }: {
vouch.auth.lua = {
enable = true;
accessRequest = ''
@ -34,7 +33,7 @@
status = ngx.HTTP_OK,
header = { },
}
-- elseif ngx.re.match(ngx.var["x_forwarded_host"], [[grocy\.(local|tail)\.${escapeRegex networking.domain}$]]) then
-- elseif ngx.re.match(ngx.var["${removePrefix "$" (xvars.get.host)}"], [[grocy\.(local|tail)\.${escapeRegex networking.domain}$]]) then
-- ngx.ctx.auth_res = {
-- status = ngx.HTTP_OK,
-- header = { },
@ -54,35 +53,40 @@ in {
inherit serverName;
};
grocy = mkMerge [ luaAuthHost {
inherit name extraConfig;
inherit name extraConfig locations;
vouch.enable = true;
locations."/" = mkMerge [ location {
proxyPass = mkIf (grocy.enable) (mkDefault
proxy = {
url = mkIf grocy.enable (mkDefault
"http://localhost:${toString nginx.defaultHTTPListenPort}"
);
} ];
host = mkDefault serverName;
};
} ];
grocy'local = {
inherit name;
local.enable = mkDefault true;
ssl.cert.copyFromVhost = "grocy";
locations."/" = {
proxy.headers.enableRecommended = true;
proxyPass = mkDefault "http://localhost:${toString nginx.defaultHTTPListenPort}";
proxy = {
url = mkDefault "http://localhost:${toString nginx.defaultHTTPListenPort}";
host = nginx.virtualHosts.grocy'local'int.serverName;
};
locations."/" = {
proxy.enable = true;
};
extraConfig = ''
set $x_proxy_host ${serverName'local};
'';
};
grocy'local'int = mkMerge [ luaAuthHost {
# internal proxy workaround for http2 lua compat issues
serverName = serverName'local;
inherit name extraConfig;
inherit name extraConfig locations;
proxy = {
url = mkDefault nginx.virtualHosts.grocy.proxy.url;
host = mkDefault nginx.virtualHosts.grocy.proxy.host;
};
proxied.enable = true;
vouch.enable = true;
locations."/" = mkMerge [ location {
proxyPass = mkDefault nginx.virtualHosts.grocy.locations."/".proxyPass;
} ];
vouch = {
enable = true;
localSso.enable = true;
};
} ];
};
};

View file

@ -22,15 +22,17 @@ in {
# Buffering off send to the client as soon as the data is received from invidious.
proxy_redirect off;
proxy_buffering off;
set $x_proxy_host $x_forwarded_host;
'';
location = {
proxy.websocket.enable = true;
proxy.headers.enableRecommended = true;
location = { xvars, ... }: {
proxy = {
enable = true;
websocket.enable = true;
headers.enableRecommended = true;
};
extraConfig = ''
proxy_hide_header content-security-policy;
add_header content-security-policy "${contentSecurityPolicy}";
proxy_cookie_domain ${virtualHosts.invidious.serverName} $x_forwarded_host;
proxy_cookie_domain ${virtualHosts.invidious.serverName} ${xvars.get.host};
'';
};
name.shortServer = mkDefault "yt";
@ -40,20 +42,22 @@ in {
invidious = {
# lua can't handle HTTP 2.0 requests, so layer it behind another proxy...
inherit name extraConfig kTLS;
locations."/" = {
proxyPass = "http://localhost:${toString config.services.nginx.defaultHTTPListenPort}";
proxy.headers.enableRecommended = true;
proxy = {
url = mkDefault "http://localhost:${toString config.services.nginx.defaultHTTPListenPort}";
host = mkDefault virtualHosts.invidious'int.serverName;
};
locations."/" = { xvars, ... }: {
proxy.enable = true;
extraConfig = ''
proxy_http_version 1.1;
set $x_proxy_host ${virtualHosts.invidious'int.serverName};
set $invidious_req_check $x_scheme:$request_uri;
set $invidious_req_check ${xvars.get.scheme}:$request_uri;
if ($invidious_req_check = "http:/") {
return ${toString virtualHosts.invidious.redirectCode} https://$x_forwarded_host$request_uri;
return ${toString virtualHosts.invidious.redirectCode} https://${xvars.get.host}$request_uri;
}
'';
};
};
invidious'int = { config, ... }: {
invidious'int = { config, xvars, ... }: {
serverName = "@invidious_internal";
proxied.enable = true;
local.denyGlobal = true;
@ -82,29 +86,31 @@ in {
'';
};
};
proxy = {
host = mkDefault xvars.get.host;
url = mkDefault (if cfg.enable
then "http://localhost:${toString cfg.port}"
else access.proxyUrlFor { serviceName = "invidious"; }
);
};
locations = {
"/" = mkMerge [
location
{
vouch.requireAuth = true;
proxyPass = mkDefault (if cfg.enable
then "http://localhost:${toString cfg.port}"
else access.proxyUrlFor { serviceName = "invidious"; }
);
}
];
};
inherit extraConfig;
};
invidious'local = {
invidious'local = { xvars, ... }: {
local.enable = true;
ssl.cert.copyFromVhost = "invidious";
locations."/" = mkMerge [
location
{
proxyPass = mkDefault virtualHosts.invidious'int.locations."/".proxyPass;
}
];
proxy = {
host = mkDefault xvars.get.host;
url = mkDefault virtualHosts.invidious'int.proxy.url;
};
locations."/" = location;
inherit name extraConfig kTLS;
};
};

View file

@ -6,6 +6,7 @@
}: let
inherit (lib.modules) mkDefault;
inherit (config.services) nginx;
cfg = config.services.unifi;
in {
config.services.nginx = {
virtualHosts = let
@ -13,24 +14,34 @@ in {
proxy_redirect off;
proxy_buffering off;
'';
locations = {
"/" = {
proxy.enable = true;
};
"/wss/" = {
proxy = {
enable = true;
websocket.enable = true;
};
};
};
name.shortServer = mkDefault "unifi";
kTLS = mkDefault true;
in {
unifi = {
inherit name extraConfig kTLS;
inherit name extraConfig kTLS locations;
vouch.enable = mkDefault true;
ssl.force = mkDefault true;
locations."/" = {
proxyPass = mkDefault (access.proxyUrlFor { serviceName = "unifi"; portName = "management"; });
};
proxy.url = mkDefault (if cfg.enable
then "https://localhost:8443"
else access.proxyUrlFor { serviceName = "unifi"; portName = "management"; }
);
};
unifi'local = {
inherit name extraConfig kTLS;
inherit name extraConfig kTLS locations;
ssl.cert.copyFromVhost = "unifi";
local.enable = true;
locations."/" = {
proxyPass = mkDefault nginx.virtualHosts.unifi.locations."/".proxyPass;
};
proxy.url = mkDefault nginx.virtualHosts.unifi.proxy.url;
};
};
};

View file

@ -14,52 +14,51 @@ in {
locations = {
"/" = {
ssl.force = true;
proxy.enable = true;
extraConfig = ''
proxy_redirect default;
set $x_proxy_host $x_forwarded_host;
'';
};
"/validate" = {config, virtualHost, ...}: {
proxied.enable = true;
proxyPass = mkDefault (virtualHost.locations."/".proxyPass + "/validate");
proxy.headers.enableRecommended = true;
proxy.enable = true;
local.denyGlobal = true;
extraConfig = ''
set $x_proxy_host $x_forwarded_host;
'';
};
};
localLocations = kanidmDomain: mkIf (nginx.vouch.localSso.enable && false) {
"/" = {
proxied.xvars.enable = true;
"/" = { xvars, ... }: {
extraConfig = ''
proxy_redirect https://sso.${networking.domain}/ $x_scheme://${kanidmDomain}/;
proxy_redirect https://sso.${networking.domain}/ ${xvars.get.scheme}://${kanidmDomain}/;
'';
};
};
name.shortServer = mkDefault "login";
in {
vouch = {
inherit name;
vouch = { xvars, ... }: {
inherit name locations;
serverAliases = [ nginx.vouch.doubleProxy.serverName ];
proxied.enable = true;
local.denyGlobal = true;
locations = mkMerge [
locations
{
"/".proxyPass = mkDefault (
proxy = {
url = mkDefault (
access.proxyUrlFor { serviceName = "vouch-proxy"; serviceId = "login"; }
);
}
];
host = mkDefault xvars.get.host;
};
vouch'local = {
local.denyGlobal = true;
};
vouch'local = { xvars, ... }: {
name = {
inherit (name) shortServer;
includeTailscale = mkDefault false;
};
serverAliases = mkIf cfg.enable [ nginx.vouch.doubleProxy.localServerName ];
proxied.enable = true;
proxy = {
url = mkDefault (
access.proxyUrlFor { serviceName = "vouch-proxy"; serviceId = "login.local"; }
);
host = mkDefault xvars.get.host;
};
local.enable = true;
ssl = {
force = true;
@ -67,15 +66,10 @@ in {
};
locations = mkMerge [
locations
{
"/".proxyPass = mkDefault (
access.proxyUrlFor { serviceName = "vouch-proxy"; serviceId = "login.local"; }
);
}
(localLocations "sso.local.${networking.domain}")
];
};
vouch'tail = {
vouch'tail = { xvars, ... }: {
enable = mkDefault (tailscale.enable && !nginx.virtualHosts.vouch'local.name.includeTailscale);
ssl.cert.copyFromVhost = "vouch'local";
name = {
@ -83,11 +77,12 @@ in {
qualifier = mkDefault "tail";
};
local.enable = true;
proxy = {
url = mkDefault nginx.virtualHosts.vouch'local.locations."/".proxyPass;
host = mkDefault xvars.get.host;
};
locations = mkMerge [
locations
{
"/".proxyPass = mkDefault nginx.virtualHosts.vouch'local.locations."/".proxyPass;
}
(localLocations "sso.tail.${networking.domain}")
];
};

View file

@ -11,26 +11,25 @@ in {
EXTERNAL_GROCY_URL = "https://grocy.${config.networking.domain}";
DISABLE_AUTHENTICATION = true;
};
nginxConfig = mkMerge [
nginxConfig = let
xvars = nginx.virtualHosts.barcodebuddy'php.xvars.lib;
in mkMerge [
''
include ${config.sops.secrets.barcodebuddy-fastcgi-params.path};
''
(mkIf cfg.reverseProxy.enable (mkAfter ''
set $bbuddy_https "";
if ($x_scheme = https) {
if (${xvars.get.scheme} = https) {
set $bbuddy_https 1;
}
fastcgi_param HTTPS $bbuddy_https if_not_empty;
fastcgi_param REQUEST_SCHEME $x_scheme;
fastcgi_param HTTP_HOST $x_forwarded_host;
fastcgi_param REQUEST_SCHEME ${xvars.get.scheme};
fastcgi_param HTTP_HOST ${xvars.get.host};
''))
];
};
config.services.nginx.virtualHosts.barcodebuddy'php = mkIf cfg.enable {
proxied = {
enable = cfg.reverseProxy.enable;
xvars.enable = true;
};
proxied.enable = cfg.reverseProxy.enable;
name.shortServer = mkDefault "bbuddy";
};
config.users.users.barcodebuddy = mkIf cfg.enable {

View file

@ -11,7 +11,8 @@ in {
currency = mkDefault "CAD";
};
};
services.nginx = let
services.nginx.virtualHosts = {
grocy'php = mkIf cfg.enable ({config, xvars, ...}: let
extraConfig = mkAfter ''
set $grocy_user guest;
set $grocy_middleware Grocy\Middleware\ReverseProxyAuthMiddleware;
@ -42,28 +43,23 @@ in {
fastcgi_param GENSO_GROCY_USER $grocy_user;
set $grocy_https "";
if ($x_scheme = https) {
if (${xvars.get.scheme} = https) {
set $grocy_https 1;
}
fastcgi_param HTTP_HOST $x_forwarded_host;
fastcgi_param REQUEST_SCHEME $x_scheme;
fastcgi_param HTTP_HOST ${xvars.get.host};
fastcgi_param REQUEST_SCHEME ${xvars.get.scheme};
fastcgi_param HTTPS $grocy_https if_not_empty;
'';
in {
virtualHosts = {
grocy'php = mkIf cfg.enable ({config, ...}: {
name.shortServer = mkDefault "grocy";
proxied = {
enable = true;
proxied.enable = true;
xvars.enable = true;
};
local.denyGlobal = true;
locations."~ \\.php$" = {
inherit extraConfig;
};
});
};
};
users.users.grocy = mkIf cfg.enable {
uid = 911;
};

View file

@ -72,7 +72,7 @@ in {
services.vouch-proxy = {
authUrl = "https://${virtualHosts.keycloak'local.serverName}/realms/${config.networking.domain}";
domain = "login.local.${config.networking.domain}";
#cookie.domain = "local.${config.networking.domain}";
settings.cookie.domain = "local.${config.networking.domain}";
};
security.acme.certs = {
@ -257,13 +257,13 @@ in {
# not the real grocy record-holder, so don't respond globally..
local.denyGlobal = true;
ssl.cert.enable = true;
locations."/".proxyPass = "http://${mkAddress6 (access.getAddressFor "tei" "lan")}";
proxy.url = "http://${mkAddress6 (access.getAddressFor "tei" "lan")}";
};
barcodebuddy = {
# not the real bbuddy record-holder, so don't respond globally..
local.denyGlobal = true;
ssl.cert.enable = true;
locations."/".proxyPass = "http://${mkAddress6 (access.getAddressFor "tei" "lan")}";
proxy.url = "http://${mkAddress6 (access.getAddressFor "tei" "lan")}";
};
freepbx = {
ssl.cert.enable = true;