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;
forceRedirectConfig = virtualHost: ''
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

View file

@ -3,83 +3,109 @@
lib,
...
}: let
inherit (lib.options) mkOption;
inherit (lib.modules) mkIf mkMerge mkDefault mkOptionDefault;
inherit (lib.lists) optional;
inherit (lib.strings) replaceStrings concatStringsSep;
inherit (lib.modules) mkIf mkMerge mkBefore mkDefault;
inherit (lib.strings) replaceStrings concatStringsSep concatMapStringsSep escapeRegex;
inherit (config.services.nginx) virtualHosts;
inherit (config.services) tailscale;
cfg = config.services.invidious;
access = config.services.nginx.access.invidious;
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 = {
access.invidious = mkIf cfg.enable {
url = mkOptionDefault "http://localhost:${toString cfg.port}";
};
virtualHosts = let
invidiousDomains =
[
access.domain
access.localDomain
]
++ optional tailscale.enable access.tailDomain;
virtualHosts.invidious.allServerNames
++ virtualHosts.invidious'local.allServerNames;
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';
extraConfig = ''
extraConfig = mkBefore ''
# Some players don't reopen a socket and playback stops totally instead of resuming after an extended pause
send_timeout 100m;
# 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;
proxyPass = access.url;
proxy.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;
'';
};
name.shortServer = mkDefault "yt";
kTLS = mkDefault true;
localDomains = virtualHosts.invidious'local.allServerNames;
in {
${access.domain} = {config, ...}: {
vouch.enable = true;
locations."/" = location;
kTLS = mkDefault true;
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;
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;
};
${access.localDomain} = {config, ...}: {
serverAliases = mkIf tailscale.enable [access.tailDomain];
invidious'local = {
local.enable = true;
ssl.cert.copyFromVhost = "invidious";
locations."/" = mkMerge [
location
{
extraConfig = ''
proxy_cookie_domain ${access.domain} $host;
'';
proxyPass = mkDefault virtualHosts.invidious'int.locations."/".proxyPass;
}
];
useACMEHost = mkDefault virtualHosts.${access.domain}.useACMEHost;
addSSL = mkIf (config.useACMEHost != null) (mkDefault true);
kTLS = mkDefault true;
inherit extraConfig;
inherit name extraConfig kTLS;
};
};
lua.http.enable = true;
};
}

View file

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

View file

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

View file

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