refactor(nginx): yt updates

This commit is contained in:
arcnmx 2024-03-21 15:02:41 -07:00
parent b7d63fc296
commit 41d030658d
5 changed files with 84 additions and 62 deletions

View file

@ -10,7 +10,7 @@
mkAlmostOptionDefault = mkOverride 1250; mkAlmostOptionDefault = mkOverride 1250;
forceRedirectConfig = virtualHost: '' forceRedirectConfig = virtualHost: ''
if ($x_scheme = http) { if ($x_scheme = http) {
return ${toString virtualHost.redirectCode} https://$host$request_uri; return ${toString virtualHost.redirectCode} https://$x_forwarded_host$request_uri;
} }
''; '';
locationModule = { config, virtualHost, ... }: let locationModule = { config, virtualHost, ... }: let

View file

@ -3,83 +3,109 @@
lib, lib,
... ...
}: let }: let
inherit (lib.options) mkOption; inherit (lib.modules) mkIf mkMerge mkBefore mkDefault;
inherit (lib.modules) mkIf mkMerge mkDefault mkOptionDefault; inherit (lib.strings) replaceStrings concatStringsSep concatMapStringsSep escapeRegex;
inherit (lib.lists) optional;
inherit (lib.strings) replaceStrings concatStringsSep;
inherit (config.services.nginx) virtualHosts; inherit (config.services.nginx) virtualHosts;
inherit (config.services) tailscale;
cfg = config.services.invidious; cfg = config.services.invidious;
access = config.services.nginx.access.invidious;
in { in {
options.services.nginx.access.invidious = with lib.types; {
url = mkOption {
type = str;
};
domain = mkOption {
type = str;
default = "yt.${config.networking.domain}";
};
localDomain = mkOption {
type = str;
default = "yt.local.${config.networking.domain}";
};
tailDomain = mkOption {
type = str;
default = "yt.tail.${config.networking.domain}";
};
};
config.services.nginx = { config.services.nginx = {
access.invidious = mkIf cfg.enable {
url = mkOptionDefault "http://localhost:${toString cfg.port}";
};
virtualHosts = let virtualHosts = let
invidiousDomains = invidiousDomains =
[ virtualHosts.invidious.allServerNames
access.domain ++ virtualHosts.invidious'local.allServerNames;
access.localDomain
]
++ optional tailscale.enable access.tailDomain;
contentSecurityPolicy' = "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; manifest-src 'self'; media-src 'self' blob: https://*.googlevideo.com:443 https://*.youtube.com:443; child-src 'self' blob:; frame-src 'self'; frame-ancestors 'none'"; contentSecurityPolicy' = "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; manifest-src 'self'; media-src 'self' blob: https://*.googlevideo.com:443 https://*.youtube.com:443; child-src 'self' blob:; frame-src 'self'; frame-ancestors 'none'";
contentSecurityPolicy = replaceStrings ["'self'"] ["'self' ${concatStringsSep " " invidiousDomains}"] contentSecurityPolicy'; contentSecurityPolicy = replaceStrings ["'self'"] ["'self' ${concatStringsSep " " invidiousDomains}"] contentSecurityPolicy';
extraConfig = '' extraConfig = mkBefore ''
# Some players don't reopen a socket and playback stops totally instead of resuming after an extended pause # Some players don't reopen a socket and playback stops totally instead of resuming after an extended pause
send_timeout 100m; send_timeout 100m;
# Buffering off send to the client as soon as the data is received from invidious. # Buffering off send to the client as soon as the data is received from invidious.
proxy_redirect off; proxy_redirect off;
proxy_buffering off; proxy_buffering off;
set $x_proxy_host $x_forwarded_host;
''; '';
location = { location = {
proxy.websocket.enable = true; proxy.websocket.enable = true;
proxyPass = access.url; proxy.headers.enableRecommended = true;
extraConfig = '' extraConfig = ''
proxy_hide_header content-security-policy; proxy_hide_header content-security-policy;
add_header content-security-policy "${contentSecurityPolicy}"; add_header content-security-policy "${contentSecurityPolicy}";
proxy_cookie_domain ${virtualHosts.invidious.serverName} $x_forwarded_host;
''; '';
}; };
name.shortServer = mkDefault "yt";
kTLS = mkDefault true;
localDomains = virtualHosts.invidious'local.allServerNames;
in { in {
${access.domain} = {config, ...}: { invidious = {
vouch.enable = true; # lua can't handle HTTP 2.0 requests, so layer it behind another proxy...
locations."/" = location; inherit name extraConfig kTLS;
kTLS = mkDefault true; locations."/" = {
proxyPass = "http://localhost:${toString config.services.nginx.defaultHTTPListenPort}";
proxy.headers.enableRecommended = true;
extraConfig = ''
proxy_http_version 1.1;
set $x_proxy_host ${virtualHosts.invidious'int.serverName};
set $invidious_req_check $x_scheme:$request_uri;
if ($invidious_req_check = "http:/") {
return ${toString virtualHosts.invidious.redirectCode} https://$x_forwarded_host$request_uri;
}
'';
};
};
invidious'int = { config, ... }: {
serverName = "invidious_internal";
proxied.enable = true;
local.denyGlobal = true;
# TODO: consider disabling registration then redirecting to login if `SID` cookie is unset instead of using vouch
vouch = {
enable = true;
requireAuth = false;
auth.lua = {
enable = true;
accessRequest = ''
local invidious_auth = ngx.var["http_authentication"]
local invidious_agent = ngx.var["http_user_agent"]
local invidious_app_auth = invidious_auth ~= nil and ngx.re.match(invidious_auth, [[":]])
local invidious_app = invidious_agent ~= nil and ngx.re.match(invidious_agent, [[Dart/\d\.\d \(dart:io\)]])
local invidious_api_request = ngx.re.match(ngx.var.request_uri, [[^/(api/v\d|vi/)]])
local is_local_request = ngx.re.match(ngx.var["http_referer"], [[^https?://(${concatMapStringsSep "|" escapeRegex localDomains})/]])
if invidious_app_auth or (invidious_app and invidious_api_request) or is_local_request then
-- bypass vouch if the app is using token auth...
ngx.ctx.auth_res = {
status = ngx.HTTP_OK,
header = { },
}
else
ngx.ctx.auth_res = ngx.location.capture("${config.vouch.auth.requestLocation}")
end
'';
};
};
locations = {
"/" = mkMerge [
location
{
vouch.requireAuth = true;
proxyPass = mkIf cfg.enable (
mkDefault "http://localhost:${toString cfg.port}"
);
}
];
};
inherit extraConfig; inherit extraConfig;
}; };
${access.localDomain} = {config, ...}: { invidious'local = {
serverAliases = mkIf tailscale.enable [access.tailDomain];
local.enable = true; local.enable = true;
ssl.cert.copyFromVhost = "invidious";
locations."/" = mkMerge [ locations."/" = mkMerge [
location location
{ {
extraConfig = '' proxyPass = mkDefault virtualHosts.invidious'int.locations."/".proxyPass;
proxy_cookie_domain ${access.domain} $host;
'';
} }
]; ];
useACMEHost = mkDefault virtualHosts.${access.domain}.useACMEHost; inherit name extraConfig kTLS;
addSSL = mkIf (config.useACMEHost != null) (mkDefault true);
kTLS = mkDefault true;
inherit extraConfig;
}; };
}; };
lua.http.enable = true;
}; };
} }

View file

@ -55,7 +55,7 @@ in {
extraConfig = '' extraConfig = ''
client_max_body_size 16384M; client_max_body_size 16384M;
''; '';
name.shortServer = "prox"; name.shortServer = mkDefault "prox";
in { in {
prox = { prox = {
inherit name locations extraConfig; inherit name locations extraConfig;

View file

@ -36,7 +36,7 @@ in {
locations."/" = { locations."/" = {
proxyPass = mkDefault access.url; proxyPass = mkDefault access.url;
}; };
name.shortServer = "unifi"; name.shortServer = mkDefault "unifi";
kTLS = mkDefault true; kTLS = mkDefault true;
in { in {
unifi'management = mkIf access.global.management { unifi'management = mkIf access.global.management {

View file

@ -170,15 +170,12 @@ in {
virtualHosts.kitchencam'local.allServerNames virtualHosts.kitchencam'local.allServerNames
]; ];
}; };
${access.invidious.domain} = { yt = {
inherit (nginx) group; inherit (nginx) group;
domain = virtualHosts.invidious.serverName;
extraDomainNames = mkMerge [ extraDomainNames = mkMerge [
[ virtualHosts.invidious.serverAliases
access.invidious.localDomain virtualHosts.invidious'local.allServerNames
]
(mkIf tailscale.enable [
access.invidious.tailDomain
])
]; ];
}; };
}; };
@ -207,9 +204,6 @@ in {
access.kitchencam = { access.kitchencam = {
streamPort = 41081; streamPort = 41081;
}; };
access.invidious = {
url = "http://${mediabox.lib.access.hostnameForNetwork.local}:${toString mediabox.services.invidious.port}";
};
virtualHosts = { virtualHosts = {
gensokyoZone.proxied.enable = "cloudflared"; gensokyoZone.proxied.enable = "cloudflared";
keycloak = { keycloak = {
@ -250,9 +244,11 @@ in {
}; };
plex.ssl.cert.enable = true; plex.ssl.cert.enable = true;
kitchencam.ssl.cert.enable = true; kitchencam.ssl.cert.enable = true;
${access.invidious.domain} = { invidious = {
useACMEHost = access.invidious.domain; ssl.cert.enable = true;
forceSSL = true; };
invidious'int = {
locations."/".proxyPass = "http://${mediabox.lib.access.hostnameForNetwork.local}:${toString mediabox.services.invidious.port}";
}; };
}; };
}; };