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/part-db.nix
|
||||||
./services/web-apps/pds.nix
|
./services/web-apps/pds.nix
|
||||||
./services/web-apps/peering-manager.nix
|
./services/web-apps/peering-manager.nix
|
||||||
|
./services/web-apps/peertube-runner.nix
|
||||||
./services/web-apps/peertube.nix
|
./services/web-apps/peertube.nix
|
||||||
./services/web-apps/pgpkeyserver-lite.nix
|
./services/web-apps/pgpkeyserver-lite.nix
|
||||||
./services/web-apps/photoprism.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 (
|
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";
|
name = "peertube";
|
||||||
meta.maintainers = with pkgs.lib.maintainers; [ izorkin ];
|
meta.maintainers = with lib.maintainers; [ izorkin ] ++ lib.teams.ngi.members;
|
||||||
|
|
||||||
nodes = {
|
nodes = {
|
||||||
database = {
|
database = {
|
||||||
@ -53,7 +60,7 @@ import ../make-test-python.nix (
|
|||||||
environment = {
|
environment = {
|
||||||
etc = {
|
etc = {
|
||||||
"peertube/password-init-root".text = ''
|
"peertube/password-init-root".text = ''
|
||||||
PT_INITIAL_ROOT_PASSWORD=zw4SqYVdcsXUfRX8aaFX
|
PT_INITIAL_ROOT_PASSWORD=${password}
|
||||||
'';
|
'';
|
||||||
"peertube/secrets-peertube".text = ''
|
"peertube/secrets-peertube".text = ''
|
||||||
063d9c60d519597acef26003d5ecc32729083965d09181ef3949200cbe5f09ee
|
063d9c60d519597acef26003d5ecc32729083965d09181ef3949200cbe5f09ee
|
||||||
@ -77,14 +84,14 @@ import ../make-test-python.nix (
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
extraHosts = ''
|
extraHosts = ''
|
||||||
192.168.2.11 peertube.local
|
192.168.2.11 ${domain}
|
||||||
'';
|
'';
|
||||||
firewall.allowedTCPPorts = [ 9000 ];
|
firewall.allowedTCPPorts = [ port ];
|
||||||
};
|
};
|
||||||
|
|
||||||
services.peertube = {
|
services.peertube = {
|
||||||
enable = true;
|
enable = true;
|
||||||
localDomain = "peertube.local";
|
localDomain = domain;
|
||||||
enableWebHttps = false;
|
enableWebHttps = false;
|
||||||
|
|
||||||
serviceEnvironmentFile = "/etc/peertube/password-init-root";
|
serviceEnvironmentFile = "/etc/peertube/password-init-root";
|
||||||
@ -132,9 +139,28 @@ import ../make-test-python.nix (
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
extraHosts = ''
|
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)
|
database.wait_for_open_port(31638)
|
||||||
|
|
||||||
server.wait_for_unit("peertube.service")
|
server.wait_for_unit("peertube.service")
|
||||||
server.wait_for_open_port(9000)
|
server.wait_for_open_port(${toString port})
|
||||||
|
|
||||||
# Check if PeerTube is running
|
# 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"')
|
# PeerTube CLI
|
||||||
client.succeed('peertube-cli auth list | grep "http://peertube.local:9000"')
|
|
||||||
client.succeed('peertube-cli auth del "http://peertube.local:9000"')
|
client.succeed('peertube-cli auth add -u "${url}" -U "root" --password "${password}"')
|
||||||
client.fail('peertube-cli auth list | grep "http://peertube.local:9000"')
|
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()
|
client.shutdown()
|
||||||
server.shutdown()
|
server.shutdown()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user