···
+
cfg = config.services.peertube-runner;
+
settingsFormat = pkgs.formats.toml { };
+
configFile = settingsFormat.generate "config.toml" cfg.settings;
+
NODE_ENV = "production";
+
XDG_CONFIG_HOME = "/var/lib/peertube-runner";
+
XDG_CACHE_HOME = "/var/cache/peertube-runner";
+
# peertube-runner makes its IPC socket in $XDG_DATA_HOME.
+
XDG_DATA_HOME = "/run/peertube-runner";
+
options.services.peertube-runner = {
+
enable = lib.mkEnableOption "peertube-runner";
+
package = lib.mkPackageOption pkgs [ "peertube" "runner" ] { };
+
example = "peertube-runner";
+
description = "User account under which peertube-runner runs.";
+
example = "peertube-runner";
+
description = "Group under which peertube-runner runs.";
+
settings = lib.mkOption {
+
type = settingsFormat.type;
+
example = lib.literalExpression ''
+
threads = 0; # Let ffmpeg automatically choose.
+
transcription.model = "large-v3";
+
Configuration for peertube-runner.
+
See available configuration options at https://docs.joinpeertube.org/maintain/tools#configuration.
+
instancesToRegister = lib.mkOption {
+
example = "https://mypeertubeinstance.com";
+
description = "URL of the PeerTube instance.";
+
registrationTokenFile = lib.mkOption {
+
example = "/run/secrets/my-peertube-instance-registration-token";
+
Path to a file containing a registration token for the PeerTube instance.
+
See how to generate registration tokens at https://docs.joinpeertube.org/admin/remote-runners#manage-remote-runners.
+
runnerName = lib.mkOption {
+
example = "Transcription";
+
description = "Runner name declared to the PeerTube instance.";
+
runnerDescription = lib.mkOption {
+
type = with lib.types; nullOr str;
+
example = "Runner for video transcription";
+
description = "Runner description declared to the PeerTube instance.";
+
url = "https://mypeertubeinstance.com";
+
registrationTokenFile = "/run/secrets/my-peertube-instance-registration-token";
+
runnerName = "Transcription";
+
runnerDescription = "Runner for video transcription";
+
description = "PeerTube instances to register this runner with.";
+
enabledJobTypes = lib.mkOption {
+
type = with lib.types; nonEmptyListOf str;
+
"vod-web-video-transcoding"
+
"vod-audio-merge-transcoding"
+
"live-rtmp-hls-transcoding"
+
"video-studio-transcoding"
+
example = [ "video-transcription" ];
+
description = "Job types that this runner will execute.";
+
config = lib.mkIf cfg.enable {
+
assertion = !(cfg.settings ? registeredInstances);
+
`services.peertube-runner.settings.registeredInstances` cannot be used.
+
Instead, registered instances can be configured with `services.peertube-runner.instancesToRegister`.
+
warnings = lib.optional (cfg.instancesToRegister == { }) ''
+
`services.peertube-runner.instancesToRegister` is empty.
+
Instances cannot be manually registered using the command line.
+
services.peertube-runner.settings = {
+
transcription = lib.mkIf (lib.elem "video-transcription" cfg.enabledJobTypes) {
+
engine = lib.mkDefault "whisper-ctranslate2";
+
enginePath = lib.mkDefault (lib.getExe pkgs.whisper-ctranslate2);
+
environment.systemPackages = [
+
(pkgs.writeShellScriptBin "peertube-runner" ''
+
${lib.concatMapAttrsStringSep "\n" (name: value: ''export ${name}="${toString value}"'') env}
+
if [[ "$USER" == ${cfg.user} ]]; then
+
exec ${lib.getExe' cfg.package "peertube-runner"} "$@"
+
echo "This has to be run with the \`${cfg.user}\` user. Ex: \`sudo -u ${cfg.user} peertube-runner\`"
+
systemd.services.peertube-runner = {
+
description = "peertube-runner daemon";
+
(lib.mkIf config.services.peertube.enable "peertube.service")
+
wantedBy = [ "multi-user.target" ];
+
path = [ pkgs.ffmpeg-headless ];
+
config_dir=$XDG_CONFIG_HOME/peertube-runner-nodejs/default
+
config_file=$config_dir/config.toml
+
cp -f --no-preserve=mode,ownership ${configFile} $config_file
+
${lib.optionalString ((lib.length (lib.attrNames cfg.instancesToRegister)) > 0) ''
+
# Temp config directory for registration commands
+
temp_dir=$(mktemp --directory)
+
temp_config_dir=$temp_dir/peertube-runner-nodejs/default
+
mkdir -p $temp_config_dir
+
temp_config_file=$temp_config_dir/config.toml
+
mkdir -p $STATE_DIRECTORY/runner_tokens
+
${lib.concatMapAttrsStringSep "\n" (instanceName: instance: ''
+
runner_token_file=$STATE_DIRECTORY/runner_tokens/${instanceName}
+
# Register any currenctly unregistered instances.
+
if [ ! -f $runner_token_file ] || [[ $(cat $runner_token_file) != ptrt-* ]]; then
+
# Server has to be running for registration.
+
XDG_CONFIG_HOME=$temp_dir ${lib.getExe' cfg.package "peertube-runner"} server &
+
XDG_CONFIG_HOME=$temp_dir ${lib.getExe' cfg.package "peertube-runner"} register \
+
--url ${lib.escapeShellArg instance.url} \
+
--registration-token "$(cat ${instance.registrationTokenFile})" \
+
--runner-name ${lib.escapeShellArg instance.runnerName} \
+
instance.runnerDescription != null
+
) ''--runner-description ${lib.escapeShellArg instance.runnerDescription}''}
+
${lib.getExe pkgs.yq-go} -e ".registeredInstances[0].runnerToken" \
+
$temp_config_file > $runner_token_file
+
[[registeredInstances]]
+
url = \"${instance.url}\"
+
runnerToken = \"$(cat $runner_token_file)\"
+
runnerName = \"${instance.runnerName}\"
+
instance.runnerDescription != null
+
) ''runnerDescription = \"${instance.runnerDescription}\"''}
+
'') cfg.instancesToRegister}
+
# Don't allow changes that won't persist.
+
exec ${lib.getExe' cfg.package "peertube-runner"} server ${
+
lib.concatMapStringsSep " " (jobType: "--enable-job ${jobType}") cfg.enabledJobTypes
+
NotifyAccess = "all"; # for systemd-notify
+
SyslogIdentifier = "prunner";
+
StateDirectory = "peertube-runner";
+
StateDirectoryMode = "0700";
+
CacheDirectory = "peertube-runner";
+
CacheDirectoryMode = "0700";
+
RuntimeDirectory = "peertube-runner";
+
RuntimeDirectoryMode = "0700";
+
ProtectSystem = "full";
+
NoNewPrivileges = true;
+
CapabilityBoundingSet = "~CAP_SYS_ADMIN";
+
users.users = lib.mkIf (cfg.user == "prunner") {
+
users.groups = lib.mkIf (cfg.group == "prunner") {
+
meta.maintainers = lib.teams.ngi.members;