diff --git a/nixos/modules/services/web-apps/invidious.nix b/nixos/modules/services/web-apps/invidious.nix index f0e860383a62c..a2e3246fc5cf8 100644 --- a/nixos/modules/services/web-apps/invidious.nix +++ b/nixos/modules/services/web-apps/invidious.nix @@ -199,6 +199,41 @@ let }; }; + sigHelperConfig = lib.mkIf cfg.sig-helper.enable { + services.invidious.settings.signature_server = "tcp://${cfg.sig-helper.listenAddress}"; + systemd.services.invidious-sig-helper = { + script = '' + exec ${lib.getExe cfg.sig-helper.package} --tcp "${cfg.sig-helper.listenAddress}" + ''; + wantedBy = [ "multi-user.target" ]; + before = [ "invidious.service" ]; + wants = [ "network-online.target" ]; + after = [ "network-online.target" ]; + serviceConfig = { + User = "invidious-sig-helper"; + DynamicUser = true; + Restart = "always"; + + PrivateTmp = true; + PrivateUsers = true; + ProtectSystem = true; + ProtectProc = "invisible"; + ProtectHome = true; + PrivateDevices = true; + NoNewPrivileges = true; + ProtectKernelTunables = true; + ProtectKernelModules = true; + ProtectControlGroups = true; + ProtectKernelLogs = true; + CapabilityBoundingSet = ""; + SystemCallArchitectures = "native"; + SystemCallFilter = [ "@system-service" "~@privileged" "~@resources" "@network-io" ]; + RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ]; + RestrictNamespaces = true; + }; + }; + }; + nginxConfig = lib.mkIf cfg.nginx.enable { services.invidious.settings = { https_only = config.services.nginx.virtualHosts.${cfg.domain}.forceSSL; @@ -392,6 +427,30 @@ in package = lib.mkPackageOptionMD pkgs "http3-ytproxy" { }; }; + + sig-helper = { + enable = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Whether to enable and configure inv-sig-helper to emulate the youtube client's javascript. This is required + to make certain videos playable. + + This will download and run completely untrusted javascript from youtube! While this service is sandboxed, + this may still be an issue! + ''; + }; + + package = lib.mkPackageOption pkgs "inv-sig-helper" { }; + + listenAddress = lib.mkOption { + type = lib.types.str; + default = "127.0.0.1:2999"; + description = '' + The IP address/port where inv-sig-helper should listen. + ''; + }; + }; }; config = lib.mkIf cfg.enable (lib.mkMerge [ @@ -399,5 +458,6 @@ in localDatabaseConfig nginxConfig ytproxyConfig + sigHelperConfig ]); } diff --git a/nixos/tests/invidious.nix b/nixos/tests/invidious.nix index c042b1065c261..05b43c5556060 100644 --- a/nixos/tests/invidious.nix +++ b/nixos/tests/invidious.nix @@ -37,6 +37,19 @@ import ./make-test-python.nix ({ pkgs, ... }: { }; networking.hosts."127.0.0.1" = [ "invidious.example.com" ]; }; + nginx-sig-helper.configuration = { + services.invidious = { + nginx.enable = true; + domain = "invidious.example.com"; + sig-helper.enable = true; + settings.log_level = "Trace"; + }; + services.nginx.virtualHosts."invidious.example.com" = { + forceSSL = false; + enableACME = false; + }; + networking.hosts."127.0.0.1" = [ "invidious.example.com" ]; + }; nginx-scale.configuration = { services.invidious = { nginx.enable = true; @@ -116,6 +129,14 @@ import ./make-test-python.nix ({ pkgs, ... }: { curl_assert_status_code("http://invidious.example.com/vi/dQw4w9WgXcQ/mqdefault.jpg", 502) machine.succeed("journalctl -eu http3-ytproxy.service | grep -o 'dQw4w9WgXcQ'") + activate_specialisation("nginx-sig-helper") + machine.wait_for_unit("invidious-sig-helper.service") + # we can't really test the sig helper that well without internet connection... + # invidious does connect to the sig helper though and crashes when the sig helper is not available + machine.wait_for_open_port(80) + curl_assert_status_code("http://invidious.example.com/search", 200) + machine.succeed("journalctl -eu invidious.service | grep -o \"SigHelper: Using helper at 'tcp://127.0.0.1:2999'\"") + postgres_tcp.wait_for_unit("postgresql.service") activate_specialisation("postgres-tcp") machine.wait_for_open_port(port)