Skip to content

Commit ab9b445

Browse files
nixos/ytdl-sub: init module (NixOS#369990)
2 parents 641122c + a417538 commit ab9b445

File tree

3 files changed

+158
-0
lines changed

3 files changed

+158
-0
lines changed

nixos/doc/manual/release-notes/rl-2505.section.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949

5050
- [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)
5151

52+
- [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).
53+
5254
- [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).
5355

5456
- [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.

nixos/modules/module-list.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -893,6 +893,7 @@
893893
./services/misc/workout-tracker.nix
894894
./services/misc/whisparr.nix
895895
./services/misc/xmrig.nix
896+
./services/misc/ytdl-sub.nix
896897
./services/misc/zoneminder.nix
897898
./services/misc/zookeeper.nix
898899
./services/monitoring/alerta.nix
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
{
2+
config,
3+
lib,
4+
pkgs,
5+
utils,
6+
...
7+
}:
8+
9+
let
10+
cfg = config.services.ytdl-sub;
11+
12+
settingsFormat = pkgs.formats.yaml { };
13+
in
14+
{
15+
meta.maintainers = with lib.maintainers; [ defelo ];
16+
17+
options.services.ytdl-sub = {
18+
package = lib.mkPackageOption pkgs "ytdl-sub" { };
19+
20+
user = lib.mkOption {
21+
type = lib.types.str;
22+
default = "ytdl-sub";
23+
description = "User account under which ytdl-sub runs.";
24+
};
25+
26+
group = lib.mkOption {
27+
type = lib.types.str;
28+
default = "ytdl-sub";
29+
description = "Group under which ytdl-sub runs.";
30+
};
31+
32+
instances = lib.mkOption {
33+
default = { };
34+
description = "Configuration for ytdl-sub instances.";
35+
type = lib.types.attrsOf (
36+
lib.types.submodule (
37+
{ name, ... }:
38+
{
39+
options = {
40+
enable = lib.mkEnableOption "ytdl-sub instance";
41+
42+
schedule = lib.mkOption {
43+
type = lib.types.nullOr lib.types.str;
44+
description = "How often to run ytdl-sub. See {manpage}`systemd.time(7)` for the format.";
45+
default = null;
46+
example = "0/6:0";
47+
};
48+
49+
config = lib.mkOption {
50+
type = settingsFormat.type;
51+
description = "Configuration for ytdl-sub. See <https://ytdl-sub.readthedocs.io/en/latest/config_reference/config_yaml.html> for more information.";
52+
default = { };
53+
example = {
54+
presets."YouTube Playlist" = {
55+
download = "{subscription_value}";
56+
output_options = {
57+
output_directory = "YouTube";
58+
file_name = "{channel}/{playlist_title}/{playlist_index_padded}_{title}.{ext}";
59+
maintain_download_archive = true;
60+
};
61+
};
62+
};
63+
};
64+
65+
subscriptions = lib.mkOption {
66+
type = settingsFormat.type;
67+
description = "Subscriptions for ytdl-sub. See <https://ytdl-sub.readthedocs.io/en/latest/config_reference/subscription_yaml.html> for more information.";
68+
default = { };
69+
example = {
70+
"YouTube Playlist" = {
71+
"Some Playlist" = "https://www.youtube.com/playlist?list=...";
72+
};
73+
};
74+
};
75+
};
76+
77+
config = {
78+
config.configuration.working_directory = "/run/ytdl-sub/${utils.escapeSystemdPath name}";
79+
};
80+
}
81+
)
82+
);
83+
};
84+
};
85+
86+
config = lib.mkIf (cfg.instances != { }) {
87+
systemd.services =
88+
let
89+
mkService =
90+
name: instance:
91+
let
92+
configFile = settingsFormat.generate "config.yaml" instance.config;
93+
subscriptionsFile = settingsFormat.generate "subscriptions.yaml" instance.subscriptions;
94+
in
95+
lib.nameValuePair "ytdl-sub-${utils.escapeSystemdPath name}" {
96+
inherit (instance) enable;
97+
98+
wants = [ "network-online.target" ];
99+
after = [ "network-online.target" ];
100+
101+
startAt = lib.optional (instance.schedule != null) instance.schedule;
102+
103+
serviceConfig = {
104+
User = cfg.user;
105+
Group = cfg.group;
106+
107+
RuntimeDirectory = "ytdl-sub/${utils.escapeSystemdPath name}";
108+
StateDirectory = "ytdl-sub/${utils.escapeSystemdPath name}";
109+
WorkingDirectory = "/var/lib/ytdl-sub/${utils.escapeSystemdPath name}";
110+
111+
ExecStart = "${lib.getExe cfg.package} --config ${configFile} sub ${subscriptionsFile}";
112+
113+
# Hardening
114+
CapabilityBoundingSet = [ "" ];
115+
DeviceAllow = [ "" ];
116+
LockPersonality = true;
117+
PrivateDevices = true;
118+
PrivateTmp = true;
119+
PrivateUsers = true;
120+
ProcSubset = "pid";
121+
ProtectClock = true;
122+
ProtectControlGroups = true;
123+
ProtectHome = true;
124+
ProtectHostname = true;
125+
ProtectKernelLogs = true;
126+
ProtectKernelModules = true;
127+
ProtectKernelTunables = true;
128+
ProtectProc = "invisible";
129+
ProtectSystem = "strict";
130+
RestrictAddressFamilies = [
131+
"AF_INET"
132+
"AF_INET6"
133+
"AF_UNIX"
134+
];
135+
RestrictNamespaces = true;
136+
RestrictRealtime = true;
137+
RestrictSUIDSGID = true;
138+
SystemCallArchitectures = "native";
139+
};
140+
};
141+
in
142+
lib.mapAttrs' mkService cfg.instances;
143+
144+
users.users = lib.mkIf (cfg.user == "ytdl-sub") {
145+
ytdl-sub = {
146+
isSystemUser = true;
147+
group = cfg.group;
148+
};
149+
};
150+
151+
users.groups = lib.mkIf (cfg.group == "ytdl-sub") {
152+
ytdl-sub = { };
153+
};
154+
};
155+
}

0 commit comments

Comments
 (0)