diff --git a/nixos/modules/services/web-apps/invidious.nix b/nixos/modules/services/web-apps/invidious.nix index 9c43679cd76d75d..c9c196bc06c275f 100644 --- a/nixos/modules/services/web-apps/invidious.nix +++ b/nixos/modules/services/web-apps/invidious.nix @@ -169,6 +169,34 @@ let }; }; + ytproxyConfig = lib.mkIf cfg.http3-ytproxy.enable { + systemd.services.http3-ytproxy = { + description = "HTTP3 ytproxy for Invidious"; + wants = [ "network-online.target" ]; + after = [ "network-online.target" ]; + wantedBy = [ "multi-user.target" ]; + + script = '' + mkdir -p socket + exec ${lib.getExe cfg.http3-ytproxy.package}; + ''; + + serviceConfig = { + RestartSec = "2s"; + DynamicUser = true; + User = lib.mkIf cfg.nginx.enable config.services.nginx.user; + RuntimeDirectory = "http3-ytproxy"; + WorkingDirectory = "/run/http3-ytproxy"; + }; + }; + + services.nginx.virtualHosts.${cfg.domain} = lib.mkIf cfg.nginx.enable { + locations."~ (^/videoplayback|^/vi/|^/ggpht/|^/sb/)" = { + proxyPass = "http://unix:/run/http3-ytproxy/socket/http-proxy.sock"; + }; + }; + }; + nginxConfig = lib.mkIf cfg.nginx.enable { services.invidious.settings = { https_only = config.services.nginx.virtualHosts.${cfg.domain}.forceSSL; @@ -351,11 +379,28 @@ in which can also be used to disable AMCE and TLS. ''; }; + + http3-ytproxy = { + enable = lib.mkOption { + type = lib.types.bool; + default = false; + description = lib.mdDoc '' + Whether to enable http3-ytproxy for faster loading of images and video playback. + + If {option}`services.invidious.nginx.enable` is used, nginx will be configured automatically. If not, you + need to configure a reverse proxy yourself according to + https://docs.invidious.io/improve-public-instance/#3-speed-up-video-playback-with-http3-ytproxy. + ''; + }; + + package = lib.mkPackageOptionMD pkgs "http3-ytproxy" { }; + }; }; config = lib.mkIf cfg.enable (lib.mkMerge [ serviceConfig localDatabaseConfig nginxConfig + ytproxyConfig ]); } diff --git a/nixos/tests/invidious.nix b/nixos/tests/invidious.nix index bd40b73242a3409..a6a11c1e42af084 100644 --- a/nixos/tests/invidious.nix +++ b/nixos/tests/invidious.nix @@ -52,6 +52,19 @@ import ./make-test-python.nix ({ pkgs, ... }: { }; networking.hosts."127.0.0.1" = [ "invidious.example.com" ]; }; + nginx-scale-ytproxy.configuration = { + services.invidious = { + nginx.enable = true; + http3-ytproxy.enable = true; + domain = "invidious.example.com"; + serviceScale = 3; + }; + services.nginx.virtualHosts."invidious.example.com" = { + forceSSL = false; + enableACME = false; + }; + networking.hosts."127.0.0.1" = [ "invidious.example.com" ]; + }; postgres-tcp.configuration = { services.invidious = { database = { @@ -97,6 +110,15 @@ import ./make-test-python.nix ({ pkgs, ... }: { machine.succeed("journalctl -eu invidious-1.service | grep -o '200 GET /search'") machine.succeed("journalctl -eu invidious-2.service | grep -o '200 GET /search'") + activate_specialisation("nginx-scale-ytproxy") + machine.wait_for_unit("http3-ytproxy.service") + machine.wait_for_open_port(80) + print(machine.wait_until_succeeds("ls -alh /run/http3-ytproxy/socket/")) + curl_assert_status_code("http://invidious.example.com/search", 200) + # this should error out as no internet connectivity is available in the test + curl_assert_status_code("http://invidious.example.com/vi/dQw4w9WgXcQ/mqdefault.jpg", 502) + machine.succeed("journalctl -eu http3-ytproxy.service | grep -o 'dQw4w9WgXcQ'") + postgres_tcp.wait_for_unit("postgresql.service") activate_specialisation("postgres-tcp") machine.wait_for_open_port(port)