From a4175381e77291c8896ff390c7c5f275142ec066 Mon Sep 17 00:00:00 2001 From: Defelo Date: Wed, 1 Jan 2025 16:08:25 +0100 Subject: [PATCH] nixos/ytdl-sub: init module --- .../manual/release-notes/rl-2505.section.md | 2 + nixos/modules/module-list.nix | 1 + nixos/modules/services/misc/ytdl-sub.nix | 155 ++++++++++++++++++ 3 files changed, 158 insertions(+) create mode 100644 nixos/modules/services/misc/ytdl-sub.nix diff --git a/nixos/doc/manual/release-notes/rl-2505.section.md b/nixos/doc/manual/release-notes/rl-2505.section.md index 1fbd5aad9230..98963cd7761e 100644 --- a/nixos/doc/manual/release-notes/rl-2505.section.md +++ b/nixos/doc/manual/release-notes/rl-2505.section.md @@ -47,6 +47,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. diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 06979a4df508..faf45b5ccb8d 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -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 diff --git a/nixos/modules/services/misc/ytdl-sub.nix b/nixos/modules/services/misc/ytdl-sub.nix new file mode 100644 index 000000000000..ef1165b8019d --- /dev/null +++ b/nixos/modules/services/misc/ytdl-sub.nix @@ -0,0 +1,155 @@ +{ + 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 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 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 = { }; + }; + }; +}