Unverified Commit ab9b445d authored by Sandro Jäckel's avatar Sandro Jäckel Committed by GitHub
Browse files

nixos/ytdl-sub: init module (#369990)

parents 641122c4 a4175381
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -49,6 +49,8 @@

- [Zenoh](https://zenoh.io/), a pub/sub/query protocol with low overhead. The Zenoh router daemon is available as [services.zenohd](options.html#opt-services.zenohd.enable)

- [ytdl-sub](https://github.com/jmbannon/ytdl-sub), a tool that downloads media via yt-dlp and prepares it for your favorite media player, including Kodi, Jellyfin, Plex, Emby, and modern music players. Available as [services.ytdl-sub](options.html#opt-services.ytdl-sub.instances).

- [MaryTTS](https://github.com/marytts/marytts), an open-source, multilingual text-to-speech synthesis system written in pure Java. Available as [services.marytts](options.html#opt-services.marytts).

- [networking.modemmanager](options.html#opt-networking.modemmanager) has been split out of [networking.networkmanager](options.html#opt-networking.networkmanager). NetworkManager still enables ModemManager by default, but options exist now to run NetworkManager without ModemManager.
+1 −0
Original line number Diff line number Diff line
@@ -893,6 +893,7 @@
  ./services/misc/workout-tracker.nix
  ./services/misc/whisparr.nix
  ./services/misc/xmrig.nix
  ./services/misc/ytdl-sub.nix
  ./services/misc/zoneminder.nix
  ./services/misc/zookeeper.nix
  ./services/monitoring/alerta.nix
+155 −0
Original line number Diff line number Diff line
{
  config,
  lib,
  pkgs,
  utils,
  ...
}:

let
  cfg = config.services.ytdl-sub;

  settingsFormat = pkgs.formats.yaml { };
in
{
  meta.maintainers = with lib.maintainers; [ defelo ];

  options.services.ytdl-sub = {
    package = lib.mkPackageOption pkgs "ytdl-sub" { };

    user = lib.mkOption {
      type = lib.types.str;
      default = "ytdl-sub";
      description = "User account under which ytdl-sub runs.";
    };

    group = lib.mkOption {
      type = lib.types.str;
      default = "ytdl-sub";
      description = "Group under which ytdl-sub runs.";
    };

    instances = lib.mkOption {
      default = { };
      description = "Configuration for ytdl-sub instances.";
      type = lib.types.attrsOf (
        lib.types.submodule (
          { name, ... }:
          {
            options = {
              enable = lib.mkEnableOption "ytdl-sub instance";

              schedule = lib.mkOption {
                type = lib.types.nullOr lib.types.str;
                description = "How often to run ytdl-sub. See {manpage}`systemd.time(7)` for the format.";
                default = null;
                example = "0/6:0";
              };

              config = lib.mkOption {
                type = settingsFormat.type;
                description = "Configuration for ytdl-sub. See <https://ytdl-sub.readthedocs.io/en/latest/config_reference/config_yaml.html> for more information.";
                default = { };
                example = {
                  presets."YouTube Playlist" = {
                    download = "{subscription_value}";
                    output_options = {
                      output_directory = "YouTube";
                      file_name = "{channel}/{playlist_title}/{playlist_index_padded}_{title}.{ext}";
                      maintain_download_archive = true;
                    };
                  };
                };
              };

              subscriptions = lib.mkOption {
                type = settingsFormat.type;
                description = "Subscriptions for ytdl-sub. See <https://ytdl-sub.readthedocs.io/en/latest/config_reference/subscription_yaml.html> for more information.";
                default = { };
                example = {
                  "YouTube Playlist" = {
                    "Some Playlist" = "https://www.youtube.com/playlist?list=...";
                  };
                };
              };
            };

            config = {
              config.configuration.working_directory = "/run/ytdl-sub/${utils.escapeSystemdPath name}";
            };
          }
        )
      );
    };
  };

  config = lib.mkIf (cfg.instances != { }) {
    systemd.services =
      let
        mkService =
          name: instance:
          let
            configFile = settingsFormat.generate "config.yaml" instance.config;
            subscriptionsFile = settingsFormat.generate "subscriptions.yaml" instance.subscriptions;
          in
          lib.nameValuePair "ytdl-sub-${utils.escapeSystemdPath name}" {
            inherit (instance) enable;

            wants = [ "network-online.target" ];
            after = [ "network-online.target" ];

            startAt = lib.optional (instance.schedule != null) instance.schedule;

            serviceConfig = {
              User = cfg.user;
              Group = cfg.group;

              RuntimeDirectory = "ytdl-sub/${utils.escapeSystemdPath name}";
              StateDirectory = "ytdl-sub/${utils.escapeSystemdPath name}";
              WorkingDirectory = "/var/lib/ytdl-sub/${utils.escapeSystemdPath name}";

              ExecStart = "${lib.getExe cfg.package} --config ${configFile} sub ${subscriptionsFile}";

              # Hardening
              CapabilityBoundingSet = [ "" ];
              DeviceAllow = [ "" ];
              LockPersonality = true;
              PrivateDevices = true;
              PrivateTmp = true;
              PrivateUsers = true;
              ProcSubset = "pid";
              ProtectClock = true;
              ProtectControlGroups = true;
              ProtectHome = true;
              ProtectHostname = true;
              ProtectKernelLogs = true;
              ProtectKernelModules = true;
              ProtectKernelTunables = true;
              ProtectProc = "invisible";
              ProtectSystem = "strict";
              RestrictAddressFamilies = [
                "AF_INET"
                "AF_INET6"
                "AF_UNIX"
              ];
              RestrictNamespaces = true;
              RestrictRealtime = true;
              RestrictSUIDSGID = true;
              SystemCallArchitectures = "native";
            };
          };
      in
      lib.mapAttrs' mkService cfg.instances;

    users.users = lib.mkIf (cfg.user == "ytdl-sub") {
      ytdl-sub = {
        isSystemUser = true;
        group = cfg.group;
      };
    };

    users.groups = lib.mkIf (cfg.group == "ytdl-sub") {
      ytdl-sub = { };
    };
  };
}