nixos/peertube-runner: init module (#427007)
This commit is contained in:
commit
009450ee9e
@ -1648,6 +1648,7 @@
|
||||
./services/web-apps/part-db.nix
|
||||
./services/web-apps/pds.nix
|
||||
./services/web-apps/peering-manager.nix
|
||||
./services/web-apps/peertube-runner.nix
|
||||
./services/web-apps/peertube.nix
|
||||
./services/web-apps/pgpkeyserver-lite.nix
|
||||
./services/web-apps/photoprism.nix
|
||||
|
||||
256
nixos/modules/services/web-apps/peertube-runner.nix
Normal file
256
nixos/modules/services/web-apps/peertube-runner.nix
Normal file
@ -0,0 +1,256 @@
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.services.peertube-runner;
|
||||
|
||||
settingsFormat = pkgs.formats.toml { };
|
||||
configFile = settingsFormat.generate "config.toml" cfg.settings;
|
||||
|
||||
env = {
|
||||
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";
|
||||
};
|
||||
in
|
||||
{
|
||||
options.services.peertube-runner = {
|
||||
enable = lib.mkEnableOption "peertube-runner";
|
||||
package = lib.mkPackageOption pkgs [ "peertube" "runner" ] { };
|
||||
|
||||
user = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "prunner";
|
||||
example = "peertube-runner";
|
||||
description = "User account under which peertube-runner runs.";
|
||||
};
|
||||
group = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "prunner";
|
||||
example = "peertube-runner";
|
||||
description = "Group under which peertube-runner runs.";
|
||||
};
|
||||
|
||||
settings = lib.mkOption {
|
||||
type = settingsFormat.type;
|
||||
default = { };
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
jobs.concurrency = 4;
|
||||
ffmpeg = {
|
||||
threads = 0; # Let ffmpeg automatically choose.
|
||||
nice = 5;
|
||||
};
|
||||
transcription.model = "large-v3";
|
||||
}
|
||||
'';
|
||||
description = ''
|
||||
Configuration for peertube-runner.
|
||||
|
||||
See available configuration options at https://docs.joinpeertube.org/maintain/tools#configuration.
|
||||
'';
|
||||
};
|
||||
instancesToRegister = lib.mkOption {
|
||||
type =
|
||||
with lib.types;
|
||||
attrsOf (submodule {
|
||||
options = {
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = "https://mypeertubeinstance.com";
|
||||
description = "URL of the PeerTube instance.";
|
||||
};
|
||||
registrationTokenFile = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
example = "/run/secrets/my-peertube-instance-registration-token";
|
||||
description = ''
|
||||
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 {
|
||||
type = lib.types.str;
|
||||
example = "Transcription";
|
||||
description = "Runner name declared to the PeerTube instance.";
|
||||
};
|
||||
runnerDescription = lib.mkOption {
|
||||
type = with lib.types; nullOr str;
|
||||
default = null;
|
||||
example = "Runner for video transcription";
|
||||
description = "Runner description declared to the PeerTube instance.";
|
||||
};
|
||||
};
|
||||
});
|
||||
default = { };
|
||||
example = {
|
||||
personal = {
|
||||
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;
|
||||
default = [
|
||||
"vod-web-video-transcoding"
|
||||
"vod-hls-transcoding"
|
||||
"vod-audio-merge-transcoding"
|
||||
"live-rtmp-hls-transcoding"
|
||||
"video-studio-transcoding"
|
||||
"video-transcription"
|
||||
];
|
||||
example = [ "video-transcription" ];
|
||||
description = "Job types that this runner will execute.";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = !(cfg.settings ? registeredInstances);
|
||||
message = ''
|
||||
`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"} "$@"
|
||||
else
|
||||
echo "This has to be run with the \`${cfg.user}\` user. Ex: \`sudo -u ${cfg.user} peertube-runner\`"
|
||||
fi
|
||||
'')
|
||||
];
|
||||
|
||||
systemd.services.peertube-runner = {
|
||||
description = "peertube-runner daemon";
|
||||
after = [
|
||||
"network.target"
|
||||
(lib.mkIf config.services.peertube.enable "peertube.service")
|
||||
];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
environment = env;
|
||||
path = [ pkgs.ffmpeg-headless ];
|
||||
|
||||
script = ''
|
||||
config_dir=$XDG_CONFIG_HOME/peertube-runner-nodejs/default
|
||||
mkdir -p $config_dir
|
||||
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} \
|
||||
${lib.optionalString (
|
||||
instance.runnerDescription != null
|
||||
) ''--runner-description ${lib.escapeShellArg instance.runnerDescription}''}
|
||||
|
||||
# Kill the server
|
||||
kill $!
|
||||
|
||||
${lib.getExe pkgs.yq-go} -e ".registeredInstances[0].runnerToken" \
|
||||
$temp_config_file > $runner_token_file
|
||||
rm $temp_config_file
|
||||
fi
|
||||
|
||||
echo "
|
||||
|
||||
[[registeredInstances]]
|
||||
url = \"${instance.url}\"
|
||||
runnerToken = \"$(cat $runner_token_file)\"
|
||||
runnerName = \"${instance.runnerName}\"
|
||||
${lib.optionalString (
|
||||
instance.runnerDescription != null
|
||||
) ''runnerDescription = \"${instance.runnerDescription}\"''}
|
||||
" >> $config_file
|
||||
'') cfg.instancesToRegister}
|
||||
''}
|
||||
|
||||
# Don't allow changes that won't persist.
|
||||
chmod 440 $config_file
|
||||
|
||||
systemd-notify --ready
|
||||
exec ${lib.getExe' cfg.package "peertube-runner"} server ${
|
||||
lib.concatMapStringsSep " " (jobType: "--enable-job ${jobType}") cfg.enabledJobTypes
|
||||
}
|
||||
'';
|
||||
serviceConfig = {
|
||||
Type = "notify";
|
||||
NotifyAccess = "all"; # for systemd-notify
|
||||
Restart = "always";
|
||||
RestartSec = 5;
|
||||
SyslogIdentifier = "prunner";
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
StateDirectory = "peertube-runner";
|
||||
StateDirectoryMode = "0700";
|
||||
CacheDirectory = "peertube-runner";
|
||||
CacheDirectoryMode = "0700";
|
||||
RuntimeDirectory = "peertube-runner";
|
||||
RuntimeDirectoryMode = "0700";
|
||||
|
||||
ProtectSystem = "full";
|
||||
NoNewPrivileges = true;
|
||||
ProtectHome = true;
|
||||
CapabilityBoundingSet = "~CAP_SYS_ADMIN";
|
||||
};
|
||||
};
|
||||
|
||||
users.users = lib.mkIf (cfg.user == "prunner") {
|
||||
${cfg.user} = {
|
||||
isSystemUser = true;
|
||||
group = cfg.group;
|
||||
};
|
||||
};
|
||||
users.groups = lib.mkIf (cfg.group == "prunner") {
|
||||
${cfg.group} = { };
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = lib.teams.ngi.members;
|
||||
}
|
||||
@ -1,8 +1,15 @@
|
||||
import ../make-test-python.nix (
|
||||
{ pkgs, ... }:
|
||||
{ lib, pkgs, ... }:
|
||||
let
|
||||
domain = "peertube.local";
|
||||
port = 9000;
|
||||
url = "http://${domain}:${toString port}";
|
||||
password = "zw4SqYVdcsXUfRX8aaFX";
|
||||
registrationTokenFile = "/etc/peertube-runner-registration-token";
|
||||
in
|
||||
{
|
||||
name = "peertube";
|
||||
meta.maintainers = with pkgs.lib.maintainers; [ izorkin ];
|
||||
meta.maintainers = with lib.maintainers; [ izorkin ] ++ lib.teams.ngi.members;
|
||||
|
||||
nodes = {
|
||||
database = {
|
||||
@ -53,7 +60,7 @@ import ../make-test-python.nix (
|
||||
environment = {
|
||||
etc = {
|
||||
"peertube/password-init-root".text = ''
|
||||
PT_INITIAL_ROOT_PASSWORD=zw4SqYVdcsXUfRX8aaFX
|
||||
PT_INITIAL_ROOT_PASSWORD=${password}
|
||||
'';
|
||||
"peertube/secrets-peertube".text = ''
|
||||
063d9c60d519597acef26003d5ecc32729083965d09181ef3949200cbe5f09ee
|
||||
@ -77,14 +84,14 @@ import ../make-test-python.nix (
|
||||
];
|
||||
};
|
||||
extraHosts = ''
|
||||
192.168.2.11 peertube.local
|
||||
192.168.2.11 ${domain}
|
||||
'';
|
||||
firewall.allowedTCPPorts = [ 9000 ];
|
||||
firewall.allowedTCPPorts = [ port ];
|
||||
};
|
||||
|
||||
services.peertube = {
|
||||
enable = true;
|
||||
localDomain = "peertube.local";
|
||||
localDomain = domain;
|
||||
enableWebHttps = false;
|
||||
|
||||
serviceEnvironmentFile = "/etc/peertube/password-init-root";
|
||||
@ -132,9 +139,28 @@ import ../make-test-python.nix (
|
||||
];
|
||||
};
|
||||
extraHosts = ''
|
||||
192.168.2.11 peertube.local
|
||||
192.168.2.11 ${domain}
|
||||
'';
|
||||
};
|
||||
|
||||
services.peertube-runner = {
|
||||
enable = true;
|
||||
# Don't pull in unneeded dependencies.
|
||||
enabledJobTypes = [ "video-studio-transcoding" ];
|
||||
instancesToRegister = {
|
||||
testServer1 = {
|
||||
inherit url registrationTokenFile;
|
||||
runnerName = "I'm a test!!!";
|
||||
};
|
||||
testServer2 = {
|
||||
inherit url registrationTokenFile;
|
||||
runnerName = "I'm also a test...";
|
||||
runnerDescription = "Even more testing?!?!";
|
||||
};
|
||||
};
|
||||
};
|
||||
# Will be manually started in test script.
|
||||
systemd.services.peertube-runner.wantedBy = lib.mkForce [ ];
|
||||
};
|
||||
|
||||
};
|
||||
@ -149,16 +175,49 @@ import ../make-test-python.nix (
|
||||
database.wait_for_open_port(31638)
|
||||
|
||||
server.wait_for_unit("peertube.service")
|
||||
server.wait_for_open_port(9000)
|
||||
server.wait_for_open_port(${toString port})
|
||||
|
||||
# Check if PeerTube is running
|
||||
client.succeed("curl --fail http://peertube.local:9000/api/v1/config/about | jq -r '.instance.name' | grep 'PeerTube\ Test\ Server'")
|
||||
client.succeed("curl --fail ${url}/api/v1/config/about | jq -r '.instance.name' | grep 'PeerTube Test Server'")
|
||||
|
||||
# Check PeerTube CLI version
|
||||
client.succeed('peertube-cli auth add -u "http://peertube.local:9000" -U "root" --password "zw4SqYVdcsXUfRX8aaFX"')
|
||||
client.succeed('peertube-cli auth list | grep "http://peertube.local:9000"')
|
||||
client.succeed('peertube-cli auth del "http://peertube.local:9000"')
|
||||
client.fail('peertube-cli auth list | grep "http://peertube.local:9000"')
|
||||
|
||||
# PeerTube CLI
|
||||
|
||||
client.succeed('peertube-cli auth add -u "${url}" -U "root" --password "${password}"')
|
||||
client.succeed('peertube-cli auth list | grep "${url}"')
|
||||
client.succeed('peertube-cli auth del "${url}"')
|
||||
client.fail('peertube-cli auth list | grep "${url}"')
|
||||
|
||||
|
||||
# peertube-runner
|
||||
|
||||
access_token = client.succeed(
|
||||
'peertube-cli get-access-token --url "${url}" --username "root" --password "${password}"'
|
||||
).strip()
|
||||
# Generate registration token.
|
||||
client.succeed(f"curl --fail -X POST -H 'Authorization: Bearer {access_token}' ${url}/api/v1/runners/registration-tokens/generate")
|
||||
# Get registration token, and put it where `registrationTokenFile` from the
|
||||
# peertube-runner module points to.
|
||||
client.succeed(
|
||||
f"curl --fail -H 'Authorization: Bearer {access_token}' ${url}/api/v1/runners/registration-tokens" \
|
||||
" | jq --raw-output '.data[0].registrationToken'" \
|
||||
" > ${registrationTokenFile}"
|
||||
)
|
||||
|
||||
client.systemctl("start peertube-runner.service")
|
||||
client.wait_for_unit("peertube-runner.service")
|
||||
|
||||
runner_command = "sudo -u prunner peertube-runner"
|
||||
client.succeed(f'{runner_command} list-registered | grep "I\'m a test!!!"')
|
||||
client.succeed(f'{runner_command} list-registered | grep "I\'m also a test..."')
|
||||
client.succeed(f'{runner_command} list-registered | grep "Even more testing?!?!"')
|
||||
|
||||
# Service should still work once instances are already registered.
|
||||
client.systemctl("restart peertube-runner.service")
|
||||
client.wait_for_unit("peertube-runner.service")
|
||||
|
||||
|
||||
# Cleanup
|
||||
|
||||
client.shutdown()
|
||||
server.shutdown()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user