···
9
+
cfg = config.services.peertube-runner;
11
+
settingsFormat = pkgs.formats.toml { };
12
+
configFile = settingsFormat.generate "config.toml" cfg.settings;
15
+
NODE_ENV = "production";
16
+
XDG_CONFIG_HOME = "/var/lib/peertube-runner";
17
+
XDG_CACHE_HOME = "/var/cache/peertube-runner";
18
+
# peertube-runner makes its IPC socket in $XDG_DATA_HOME.
19
+
XDG_DATA_HOME = "/run/peertube-runner";
23
+
options.services.peertube-runner = {
24
+
enable = lib.mkEnableOption "peertube-runner";
25
+
package = lib.mkPackageOption pkgs [ "peertube" "runner" ] { };
27
+
user = lib.mkOption {
28
+
type = lib.types.str;
29
+
default = "prunner";
30
+
example = "peertube-runner";
31
+
description = "User account under which peertube-runner runs.";
33
+
group = lib.mkOption {
34
+
type = lib.types.str;
35
+
default = "prunner";
36
+
example = "peertube-runner";
37
+
description = "Group under which peertube-runner runs.";
40
+
settings = lib.mkOption {
41
+
type = settingsFormat.type;
43
+
example = lib.literalExpression ''
45
+
jobs.concurrency = 4;
47
+
threads = 0; # Let ffmpeg automatically choose.
50
+
transcription.model = "large-v3";
54
+
Configuration for peertube-runner.
56
+
See available configuration options at https://docs.joinpeertube.org/maintain/tools#configuration.
59
+
instancesToRegister = lib.mkOption {
62
+
attrsOf (submodule {
64
+
url = lib.mkOption {
65
+
type = lib.types.str;
66
+
example = "https://mypeertubeinstance.com";
67
+
description = "URL of the PeerTube instance.";
69
+
registrationTokenFile = lib.mkOption {
70
+
type = lib.types.path;
71
+
example = "/run/secrets/my-peertube-instance-registration-token";
73
+
Path to a file containing a registration token for the PeerTube instance.
75
+
See how to generate registration tokens at https://docs.joinpeertube.org/admin/remote-runners#manage-remote-runners.
78
+
runnerName = lib.mkOption {
79
+
type = lib.types.str;
80
+
example = "Transcription";
81
+
description = "Runner name declared to the PeerTube instance.";
83
+
runnerDescription = lib.mkOption {
84
+
type = with lib.types; nullOr str;
86
+
example = "Runner for video transcription";
87
+
description = "Runner description declared to the PeerTube instance.";
94
+
url = "https://mypeertubeinstance.com";
95
+
registrationTokenFile = "/run/secrets/my-peertube-instance-registration-token";
96
+
runnerName = "Transcription";
97
+
runnerDescription = "Runner for video transcription";
100
+
description = "PeerTube instances to register this runner with.";
103
+
enabledJobTypes = lib.mkOption {
104
+
type = with lib.types; nonEmptyListOf str;
106
+
"vod-web-video-transcoding"
107
+
"vod-hls-transcoding"
108
+
"vod-audio-merge-transcoding"
109
+
"live-rtmp-hls-transcoding"
110
+
"video-studio-transcoding"
111
+
"video-transcription"
113
+
example = [ "video-transcription" ];
114
+
description = "Job types that this runner will execute.";
118
+
config = lib.mkIf cfg.enable {
121
+
assertion = !(cfg.settings ? registeredInstances);
123
+
`services.peertube-runner.settings.registeredInstances` cannot be used.
124
+
Instead, registered instances can be configured with `services.peertube-runner.instancesToRegister`.
128
+
warnings = lib.optional (cfg.instancesToRegister == { }) ''
129
+
`services.peertube-runner.instancesToRegister` is empty.
130
+
Instances cannot be manually registered using the command line.
133
+
services.peertube-runner.settings = {
134
+
transcription = lib.mkIf (lib.elem "video-transcription" cfg.enabledJobTypes) {
135
+
engine = lib.mkDefault "whisper-ctranslate2";
136
+
enginePath = lib.mkDefault (lib.getExe pkgs.whisper-ctranslate2);
140
+
environment.systemPackages = [
141
+
(pkgs.writeShellScriptBin "peertube-runner" ''
142
+
${lib.concatMapAttrsStringSep "\n" (name: value: ''export ${name}="${toString value}"'') env}
144
+
if [[ "$USER" == ${cfg.user} ]]; then
145
+
exec ${lib.getExe' cfg.package "peertube-runner"} "$@"
147
+
echo "This has to be run with the \`${cfg.user}\` user. Ex: \`sudo -u ${cfg.user} peertube-runner\`"
152
+
systemd.services.peertube-runner = {
153
+
description = "peertube-runner daemon";
156
+
(lib.mkIf config.services.peertube.enable "peertube.service")
158
+
wantedBy = [ "multi-user.target" ];
161
+
path = [ pkgs.ffmpeg-headless ];
164
+
config_dir=$XDG_CONFIG_HOME/peertube-runner-nodejs/default
165
+
mkdir -p $config_dir
166
+
config_file=$config_dir/config.toml
167
+
cp -f --no-preserve=mode,ownership ${configFile} $config_file
169
+
${lib.optionalString ((lib.length (lib.attrNames cfg.instancesToRegister)) > 0) ''
170
+
# Temp config directory for registration commands
171
+
temp_dir=$(mktemp --directory)
172
+
temp_config_dir=$temp_dir/peertube-runner-nodejs/default
173
+
mkdir -p $temp_config_dir
174
+
temp_config_file=$temp_config_dir/config.toml
176
+
mkdir -p $STATE_DIRECTORY/runner_tokens
177
+
${lib.concatMapAttrsStringSep "\n" (instanceName: instance: ''
178
+
runner_token_file=$STATE_DIRECTORY/runner_tokens/${instanceName}
180
+
# Register any currenctly unregistered instances.
181
+
if [ ! -f $runner_token_file ] || [[ $(cat $runner_token_file) != ptrt-* ]]; then
182
+
# Server has to be running for registration.
183
+
XDG_CONFIG_HOME=$temp_dir ${lib.getExe' cfg.package "peertube-runner"} server &
185
+
XDG_CONFIG_HOME=$temp_dir ${lib.getExe' cfg.package "peertube-runner"} register \
186
+
--url ${lib.escapeShellArg instance.url} \
187
+
--registration-token "$(cat ${instance.registrationTokenFile})" \
188
+
--runner-name ${lib.escapeShellArg instance.runnerName} \
189
+
${lib.optionalString (
190
+
instance.runnerDescription != null
191
+
) ''--runner-description ${lib.escapeShellArg instance.runnerDescription}''}
196
+
${lib.getExe pkgs.yq-go} -e ".registeredInstances[0].runnerToken" \
197
+
$temp_config_file > $runner_token_file
198
+
rm $temp_config_file
203
+
[[registeredInstances]]
204
+
url = \"${instance.url}\"
205
+
runnerToken = \"$(cat $runner_token_file)\"
206
+
runnerName = \"${instance.runnerName}\"
207
+
${lib.optionalString (
208
+
instance.runnerDescription != null
209
+
) ''runnerDescription = \"${instance.runnerDescription}\"''}
211
+
'') cfg.instancesToRegister}
214
+
# Don't allow changes that won't persist.
215
+
chmod 440 $config_file
217
+
systemd-notify --ready
218
+
exec ${lib.getExe' cfg.package "peertube-runner"} server ${
219
+
lib.concatMapStringsSep " " (jobType: "--enable-job ${jobType}") cfg.enabledJobTypes
224
+
NotifyAccess = "all"; # for systemd-notify
225
+
Restart = "always";
227
+
SyslogIdentifier = "prunner";
230
+
StateDirectory = "peertube-runner";
231
+
StateDirectoryMode = "0700";
232
+
CacheDirectory = "peertube-runner";
233
+
CacheDirectoryMode = "0700";
234
+
RuntimeDirectory = "peertube-runner";
235
+
RuntimeDirectoryMode = "0700";
237
+
ProtectSystem = "full";
238
+
NoNewPrivileges = true;
239
+
ProtectHome = true;
240
+
CapabilityBoundingSet = "~CAP_SYS_ADMIN";
244
+
users.users = lib.mkIf (cfg.user == "prunner") {
246
+
isSystemUser = true;
250
+
users.groups = lib.mkIf (cfg.group == "prunner") {
251
+
${cfg.group} = { };
255
+
meta.maintainers = lib.teams.ngi.members;