From 26c5383fc9b7f41a084a7343fbbb67d920398d6b Mon Sep 17 00:00:00 2001 From: Gabriel Arazas Date: Thu, 22 Aug 2024 17:59:45 +0800 Subject: [PATCH] nixos/services/yt-dlp: update handling of download paths This also includes different paths for different metadata files. --- modules/nixos/services/yt-dlp.nix | 115 +++++++++++++++++++++++------- 1 file changed, 88 insertions(+), 27 deletions(-) diff --git a/modules/nixos/services/yt-dlp.nix b/modules/nixos/services/yt-dlp.nix index a53e84ae..3ade6a43 100644 --- a/modules/nixos/services/yt-dlp.nix +++ b/modules/nixos/services/yt-dlp.nix @@ -3,10 +3,32 @@ let cfg = config.services.yt-dlp; - serviceLevelArgs = lib.escapeShellArgs cfg.extraArgs; - jobUnitName = name: "yt-dlp-archive-service-${name}"; + metadataType = { lib, ... }: { + options = { + path = lib.mkOption { + type = with lib.types; nullOr path; + description = '' + Associated path of the metadata to be downloaded. This will be passed to + the appropriate `--paths` option of yt-dlp. + ''; + default = null; + example = "/var/yt-dlp/thumbnails"; + }; + + output = lib.mkOption { + type = with lib.types; nullOr str; + description = '' + Associated output name for the metadata. This is passed to the + appropriate `--output` option of yt-dlp. + ''; + default = null; + example = "%(title)s.%(ext)s"; + }; + }; + }; + jobType = { name, config, ... }: { options = { urls = lib.mkOption { @@ -35,14 +57,30 @@ let example = "*-*-3/4"; }; - extraArgs = options.services.yt-dlp.extraArgs // { - default = cfg.extraArgs; + extraArgs = options.services.yt-dlp.extraArgs; + + downloadPath = options.services.yt-dlp.downloadPath // { + default = cfg.downloadPath; + description = "Job-specific download path of the service."; }; - archivePath = options.services.yt-dlp.archivePath // { - default = cfg.archivePath; + metadata = options.services.yt-dlp.metadata // { + default = cfg.metadata; + description = '' + Per-job set of metadata with their associated options. + ''; }; }; + + config.extraArgs = + let + mkPathArg = n: v: + lib.optionals (v.output != null) [ "--output" "${n}:${v.output}" ] + ++ lib.optionals (v.path != null) [ "--paths" "${n}:${v.path}" ]; + in + cfg.extraArgs + ++ (lib.lists.flatten (lib.mapAttrsToList mkPathArg config.metadata)) + ++ [ "--paths" config.downloadPath ]; }; in { @@ -59,26 +97,39 @@ in "pkgs.yt-dlp.override { phantomjsSupport = true; }"; }; - archivePath = lib.mkOption { + downloadPath = lib.mkOption { type = lib.types.path; - description = '' - The location of the archive to be downloaded. Must be an absolute path. - ''; + description = "Download path of the service to be given per job (unless overridden)."; default = "/var/yt-dlp"; - example = "/var/archives/yt-dlp-service"; + example = "/srv/Videos"; + }; + + metadata = lib.mkOption { + type = with lib.types; attrsOf (submodule metadataType); + description = '' + Global set of metadata with their appropriate options to be set. + ''; + default = { }; + example = { + thumbnail = { + path = "/var/yt-dlp/thumbnails"; + output = "%(uploader,artist,creator,Unknown)s/%(title)s.%(ext)s"; + }; + infojson.path = "/var/yt-dlp/infojson"; + }; }; extraArgs = lib.mkOption { type = with lib.types; listOf str; description = "Global list of arguments to be passed to each yt-dlp job."; - default = [ "--download-archive videos" ]; + default = [ ]; example = lib.literalExpression '' [ "--verbose" - "--download-archive" "''${cfg.archivePath}/download-list" "--concurrent-fragments" "2" "--retries" "20" + "--download-archive" "videos" ] ''; }; @@ -111,14 +162,9 @@ in }; }; - # There's no need to go to the working directory since yt-dlp has the - # `--paths` flag. config = lib.mkIf cfg.enable { systemd.services = lib.mapAttrs' (name: job: - let - jobLevelArgs = lib.escapeShellArgs job.extraArgs; - in lib.nameValuePair (jobUnitName name) { inherit (job) startAt; wantedBy = [ "multi-user.target" ]; @@ -127,30 +173,45 @@ in description = "yt-dlp archive job for group '${name}'"; documentation = [ "man:yt-dlp(1)" ]; enable = true; - path = [ cfg.package pkgs.coreutils ]; - preStart = '' - mkdir -p ${lib.escapeShellArg job.archivePath} - ''; script = '' - yt-dlp ${serviceLevelArgs} ${jobLevelArgs} \ - ${lib.escapeShellArgs job.urls} \ - --paths ${lib.escapeShellArg job.archivePath} + ${lib.getExe' cfg.package "yt-dlp"} \ + ${lib.escapeShellArgs job.extraArgs} \ + ${lib.escapeShellArgs job.urls} ''; serviceConfig = { + ReadWritePaths = + [ job.downloadPath ] + ++ lib.mapAttrsToList (n: v: lib.optionals (v.path != null) v.path) job.metadata; + LockPersonality = true; NoNewPrivileges = true; + PrivateDevices = true; PrivateTmp = true; PrivateUsers = true; - PrivateDevices = true; - ProtectControlGroups = true; + PrivateMounts = true; ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; ProtectKernelLogs = true; ProtectKernelModules = true; ProtectKernelTunables = true; + ProtectSystem = "full"; + RemoveIPC = true; StandardOutput = "journal"; StandardError = "journal"; SystemCallFilter = "@system-service"; SystemCallErrorNumber = "EPERM"; + + CapabilityBoundingSet = lib.mkDefault [ ]; + AmbientCapabilities = lib.mkDefault [ ]; + RestrictAddressFamilies = [ + "AF_LOCAL" + "AF_INET" + "AF_INET6" + ]; + RestrictNamespaces = true; + RestrictSUIDGUID = true; + MemoryDenyWriteExecute = true; }; }) cfg.jobs;