diff --git a/nixos/modules/services/web-apps/invidious.nix b/nixos/modules/services/web-apps/invidious.nix index 8823da0100141..5603ef7392e82 100644 --- a/nixos/modules/services/web-apps/invidious.nix +++ b/nixos/modules/services/web-apps/invidious.nix @@ -7,6 +7,9 @@ let settingsFile = settingsFormat.generate "invidious-settings" cfg.settings; + generatedHmacKeyFile = "/var/lib/invidious/hmac_key"; + generateHmac = cfg.hmacKeyFile == null; + serviceConfig = { systemd.services.invidious = { description = "Invidious (An alternative YouTube front-end)"; @@ -14,22 +17,47 @@ let after = [ "network-online.target" ]; wantedBy = [ "multi-user.target" ]; - script = - let - jqFilter = "." - + lib.optionalString (cfg.database.host != null) "[0].db.password = \"'\"'\"$(cat ${lib.escapeShellArg cfg.database.passwordFile})\"'\"'\"" - + " | .[0]" - + lib.optionalString (cfg.extraSettingsFile != null) " * .[1]"; - jqFiles = [ settingsFile ] ++ lib.optional (cfg.extraSettingsFile != null) cfg.extraSettingsFile; - in - '' - export INVIDIOUS_CONFIG="$(${pkgs.jq}/bin/jq -s "${jqFilter}" ${lib.escapeShellArgs jqFiles})" - exec ${cfg.package}/bin/invidious - ''; + preStart = lib.optionalString generateHmac '' + if [[ ! -e "${generatedHmacKeyFile}" ]]; then + ${pkgs.pwgen}/bin/pwgen 20 1 > "${generatedHmacKeyFile}" + chmod 0600 "${generatedHmacKeyFile}" + fi + ''; + + script = '' + configParts=() + '' + # autogenerated hmac_key + + lib.optionalString generateHmac '' + configParts+=("$(${pkgs.jq}/bin/jq -R '{"hmac_key":.}' <"${generatedHmacKeyFile}")") + '' + # generated settings file + + '' + configParts+=("$(< ${lib.escapeShellArg settingsFile})") + '' + # optional database password file + + lib.optionalString (cfg.database.host != null) '' + configParts+=("$(${pkgs.jq}/bin/jq -R '{"db":{"password":.}}' ${lib.escapeShellArg cfg.database.passwordFile})") + '' + # optional extra settings file + + lib.optionalString (cfg.extraSettingsFile != null) '' + configParts+=("$(< ${lib.escapeShellArg cfg.extraSettingsFile})") + '' + # explicitly specified hmac key file + + lib.optionalString (cfg.hmacKeyFile != null) '' + configParts+=("$(< ${lib.escapeShellArg cfg.hmacKeyFile})") + '' + # merge all parts into a single configuration with later elements overriding previous elements + + '' + export INVIDIOUS_CONFIG="$(${pkgs.jq}/bin/jq -s 'reduce .[] as $item ({}; . * $item)' <<<"''${configParts[*]}")" + exec ${cfg.package}/bin/invidious + ''; serviceConfig = { RestartSec = "2s"; DynamicUser = true; + StateDirectory = "invidious"; + StateDirectoryMode = "0750"; CapabilityBoundingSet = ""; PrivateDevices = true; @@ -171,6 +199,18 @@ in ''; }; + hmacKeyFile = lib.mkOption { + type = types.nullOr types.path; + default = null; + description = lib.mdDoc '' + A path to a file containing the `hmac_key`. If `null`, a key will be generated automatically on first + start. + + If non-`null`, this option overrides any `hmac_key` specified in {option}`services.invidious.settings` or + via {option}`services.invidious.extraSettingsFile`. + ''; + }; + extraSettingsFile = lib.mkOption { type = types.nullOr types.str; default = null; diff --git a/pkgs/servers/invidious/default.nix b/pkgs/servers/invidious/default.nix index 7efeb5d9c39d9..0b1cea5fd689a 100644 --- a/pkgs/servers/invidious/default.nix +++ b/pkgs/servers/invidious/default.nix @@ -97,12 +97,16 @@ crystal.buildCrystalPackage rec { cp -r config/sql $out/share/invidious/config ''; - # Invidious tries to open config/config.yml and connect to the database, even - # when running --help. This specifies a minimal configuration in an - # environment variable. Even though the database is bogus, --help still - # works. + # Invidious tries to open and validate config/config.yml, even when + # running --help. This specifies a minimal configuration in an + # environment variable. Even though the database and hmac_key are + # bogus, --help still works. installCheckPhase = '' - INVIDIOUS_CONFIG="database_url: sqlite3:///dev/null" $out/bin/invidious --help + INVIDIOUS_CONFIG="$(cat <