3
0
Fork 0
forked from mirrors/nixpkgs
nixpkgs/nixos/modules/services/networking/jibri/default.nix
pennae 2e751c0772 treewide: automatically md-convert option descriptions
the conversion procedure is simple:

 - find all things that look like options, ie calls to either `mkOption`
   or `lib.mkOption` that take an attrset. remember the attrset as the
   option
 - for all options, find a `description` attribute who's value is not a
   call to `mdDoc` or `lib.mdDoc`
 - textually convert the entire value of the attribute to MD with a few
   simple regexes (the set from mdize-module.sh)
 - if the change produced a change in the manual output, discard
 - if the change kept the manual unchanged, add some text to the
   description to make sure we've actually found an option. if the
   manual changes this time, keep the converted description

this procedure converts 80% of nixos options to markdown. around 2000
options remain to be inspected, but most of those fail the "does not
change the manual output check": currently the MD conversion process
does not faithfully convert docbook tags like <code> and <package>, so
any option using such tags will not be converted at all.
2022-07-30 15:16:34 +02:00

418 lines
13 KiB
Nix

{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.jibri;
# Copied from the jitsi-videobridge.nix file.
toHOCON = x:
if isAttrs x && x ? __hocon_envvar then ("\${" + x.__hocon_envvar + "}")
else if isAttrs x then "{${ concatStringsSep "," (mapAttrsToList (k: v: ''"${k}":${toHOCON v}'') x) }}"
else if isList x then "[${ concatMapStringsSep "," toHOCON x }]"
else builtins.toJSON x;
# We're passing passwords in environment variables that have names generated
# from an attribute name, which may not be a valid bash identifier.
toVarName = s: "XMPP_PASSWORD_" + stringAsChars (c: if builtins.match "[A-Za-z0-9]" c != null then c else "_") s;
defaultJibriConfig = {
id = "";
single-use-mode = false;
api = {
http.external-api-port = 2222;
http.internal-api-port = 3333;
xmpp.environments = flip mapAttrsToList cfg.xmppEnvironments (name: env: {
inherit name;
xmpp-server-hosts = env.xmppServerHosts;
xmpp-domain = env.xmppDomain;
control-muc = {
domain = env.control.muc.domain;
room-name = env.control.muc.roomName;
nickname = env.control.muc.nickname;
};
control-login = {
domain = env.control.login.domain;
username = env.control.login.username;
password.__hocon_envvar = toVarName "${name}_control";
};
call-login = {
domain = env.call.login.domain;
username = env.call.login.username;
password.__hocon_envvar = toVarName "${name}_call";
};
strip-from-room-domain = env.stripFromRoomDomain;
usage-timeout = env.usageTimeout;
trust-all-xmpp-certs = env.disableCertificateVerification;
});
};
recording = {
recordings-directory = "/tmp/recordings";
finalize-script = "${cfg.finalizeScript}";
};
streaming.rtmp-allow-list = [ ".*" ];
chrome.flags = [
"--use-fake-ui-for-media-stream"
"--start-maximized"
"--kiosk"
"--enabled"
"--disable-infobars"
"--autoplay-policy=no-user-gesture-required"
]
++ lists.optional cfg.ignoreCert
"--ignore-certificate-errors";
stats.enable-stats-d = true;
webhook.subscribers = [ ];
jwt-info = { };
call-status-checks = {
no-media-timout = "30 seconds";
all-muted-timeout = "10 minutes";
default-call-empty-timout = "30 seconds";
};
};
# Allow overriding leaves of the default config despite types.attrs not doing any merging.
jibriConfig = recursiveUpdate defaultJibriConfig cfg.config;
configFile = pkgs.writeText "jibri.conf" (toHOCON { jibri = jibriConfig; });
in
{
options.services.jibri = with types; {
enable = mkEnableOption "Jitsi BRoadcasting Infrastructure. Currently Jibri must be run on a host that is also running <option>services.jitsi-meet.enable</option>, so for most use cases it will be simpler to run <option>services.jitsi-meet.jibri.enable</option>";
config = mkOption {
type = attrs;
default = { };
description = lib.mdDoc ''
Jibri configuration.
See <https://github.com/jitsi/jibri/blob/master/src/main/resources/reference.conf>
for default configuration with comments.
'';
};
finalizeScript = mkOption {
type = types.path;
default = pkgs.writeScript "finalize_recording.sh" ''
#!/bin/sh
RECORDINGS_DIR=$1
echo "This is a dummy finalize script" > /tmp/finalize.out
echo "The script was invoked with recordings directory $RECORDINGS_DIR." >> /tmp/finalize.out
echo "You should put any finalize logic (renaming, uploading to a service" >> /tmp/finalize.out
echo "or storage provider, etc.) in this script" >> /tmp/finalize.out
exit 0
'';
defaultText = literalExpression ''
pkgs.writeScript "finalize_recording.sh" ''''''
#!/bin/sh
RECORDINGS_DIR=$1
echo "This is a dummy finalize script" > /tmp/finalize.out
echo "The script was invoked with recordings directory $RECORDINGS_DIR." >> /tmp/finalize.out
echo "You should put any finalize logic (renaming, uploading to a service" >> /tmp/finalize.out
echo "or storage provider, etc.) in this script" >> /tmp/finalize.out
exit 0
'''''';
'';
example = literalExpression ''
pkgs.writeScript "finalize_recording.sh" ''''''
#!/bin/sh
RECORDINGS_DIR=$1
''${pkgs.rclone}/bin/rclone copy $RECORDINGS_DIR RCLONE_REMOTE:jibri-recordings/ -v --log-file=/var/log/jitsi/jibri/recording-upload.txt
exit 0
'''''';
'';
description = lib.mdDoc ''
This script runs when jibri finishes recording a video of a conference.
'';
};
ignoreCert = mkOption {
type = bool;
default = false;
example = true;
description = lib.mdDoc ''
Whether to enable the flag "--ignore-certificate-errors" for the Chromium browser opened by Jibri.
Intended for use in automated tests or anywhere else where using a verified cert for Jitsi-Meet is not possible.
'';
};
xmppEnvironments = mkOption {
description = lib.mdDoc ''
XMPP servers to connect to.
'';
example = literalExpression ''
"jitsi-meet" = {
xmppServerHosts = [ "localhost" ];
xmppDomain = config.services.jitsi-meet.hostName;
control.muc = {
domain = "internal.''${config.services.jitsi-meet.hostName}";
roomName = "JibriBrewery";
nickname = "jibri";
};
control.login = {
domain = "auth.''${config.services.jitsi-meet.hostName}";
username = "jibri";
passwordFile = "/var/lib/jitsi-meet/jibri-auth-secret";
};
call.login = {
domain = "recorder.''${config.services.jitsi-meet.hostName}";
username = "recorder";
passwordFile = "/var/lib/jitsi-meet/jibri-recorder-secret";
};
usageTimeout = "0";
disableCertificateVerification = true;
stripFromRoomDomain = "conference.";
};
'';
default = { };
type = attrsOf (submodule ({ name, ... }: {
options = {
xmppServerHosts = mkOption {
type = listOf str;
example = [ "xmpp.example.org" ];
description = lib.mdDoc ''
Hostnames of the XMPP servers to connect to.
'';
};
xmppDomain = mkOption {
type = str;
example = "xmpp.example.org";
description = lib.mdDoc ''
The base XMPP domain.
'';
};
control.muc.domain = mkOption {
type = str;
description = lib.mdDoc ''
The domain part of the MUC to connect to for control.
'';
};
control.muc.roomName = mkOption {
type = str;
default = "JibriBrewery";
description = lib.mdDoc ''
The room name of the MUC to connect to for control.
'';
};
control.muc.nickname = mkOption {
type = str;
default = "jibri";
description = lib.mdDoc ''
The nickname for this Jibri instance in the MUC.
'';
};
control.login.domain = mkOption {
type = str;
description = lib.mdDoc ''
The domain part of the JID for this Jibri instance.
'';
};
control.login.username = mkOption {
type = str;
default = "jvb";
description = lib.mdDoc ''
User part of the JID.
'';
};
control.login.passwordFile = mkOption {
type = str;
example = "/run/keys/jibri-xmpp1";
description = lib.mdDoc ''
File containing the password for the user.
'';
};
call.login.domain = mkOption {
type = str;
example = "recorder.xmpp.example.org";
description = lib.mdDoc ''
The domain part of the JID for the recorder.
'';
};
call.login.username = mkOption {
type = str;
default = "recorder";
description = lib.mdDoc ''
User part of the JID for the recorder.
'';
};
call.login.passwordFile = mkOption {
type = str;
example = "/run/keys/jibri-recorder-xmpp1";
description = lib.mdDoc ''
File containing the password for the user.
'';
};
disableCertificateVerification = mkOption {
type = bool;
default = false;
description = lib.mdDoc ''
Whether to skip validation of the server's certificate.
'';
};
stripFromRoomDomain = mkOption {
type = str;
default = "0";
example = "conference.";
description = lib.mdDoc ''
The prefix to strip from the room's JID domain to derive the call URL.
'';
};
usageTimeout = mkOption {
type = str;
default = "0";
example = "1 hour";
description = lib.mdDoc ''
The duration that the Jibri session can be.
A value of zero means indefinitely.
'';
};
};
config =
let
nick = mkDefault (builtins.replaceStrings [ "." ] [ "-" ] (
config.networking.hostName + optionalString (config.networking.domain != null) ".${config.networking.domain}"
));
in
{
call.login.username = nick;
control.muc.nickname = nick;
};
}));
};
};
config = mkIf cfg.enable {
users.groups.jibri = { };
users.groups.plugdev = { };
users.users.jibri = {
isSystemUser = true;
group = "jibri";
home = "/var/lib/jibri";
extraGroups = [ "jitsi-meet" "adm" "audio" "video" "plugdev" ];
};
systemd.services.jibri-xorg = {
description = "Jitsi Xorg Process";
after = [ "network.target" ];
wantedBy = [ "jibri.service" "jibri-icewm.service" ];
preStart = ''
cp --no-preserve=mode,ownership ${pkgs.jibri}/etc/jitsi/jibri/* /var/lib/jibri
mv /var/lib/jibri/{,.}asoundrc
'';
environment.DISPLAY = ":0";
serviceConfig = {
Type = "simple";
User = "jibri";
Group = "jibri";
KillMode = "process";
Restart = "on-failure";
RestartPreventExitStatus = 255;
StateDirectory = "jibri";
ExecStart = "${pkgs.xorg.xorgserver}/bin/Xorg -nocursor -noreset +extension RANDR +extension RENDER -config ${pkgs.jibri}/etc/jitsi/jibri/xorg-video-dummy.conf -logfile /dev/null :0";
};
};
systemd.services.jibri-icewm = {
description = "Jitsi Window Manager";
requires = [ "jibri-xorg.service" ];
after = [ "jibri-xorg.service" ];
wantedBy = [ "jibri.service" ];
environment.DISPLAY = ":0";
serviceConfig = {
Type = "simple";
User = "jibri";
Group = "jibri";
Restart = "on-failure";
RestartPreventExitStatus = 255;
StateDirectory = "jibri";
ExecStart = "${pkgs.icewm}/bin/icewm-session";
};
};
systemd.services.jibri = {
description = "Jibri Process";
requires = [ "jibri-icewm.service" "jibri-xorg.service" ];
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
path = with pkgs; [ chromedriver chromium ffmpeg-full ];
script = (concatStrings (mapAttrsToList
(name: env: ''
export ${toVarName "${name}_control"}=$(cat ${env.control.login.passwordFile})
export ${toVarName "${name}_call"}=$(cat ${env.call.login.passwordFile})
'')
cfg.xmppEnvironments))
+ ''
${pkgs.jre8_headless}/bin/java -Djava.util.logging.config.file=${./logging.properties-journal} -Dconfig.file=${configFile} -jar ${pkgs.jibri}/opt/jitsi/jibri/jibri.jar --config /var/lib/jibri/jibri.json
'';
environment.HOME = "/var/lib/jibri";
serviceConfig = {
Type = "simple";
User = "jibri";
Group = "jibri";
Restart = "always";
RestartPreventExitStatus = 255;
StateDirectory = "jibri";
};
};
systemd.tmpfiles.rules = [
"d /var/log/jitsi/jibri 755 jibri jibri"
];
# Configure Chromium to not show the "Chrome is being controlled by automatic test software" message.
environment.etc."chromium/policies/managed/managed_policies.json".text = builtins.toJSON { CommandLineFlagSecurityWarningsEnabled = false; };
warnings = [ "All security warnings for Chromium have been disabled. This is necessary for Jibri, but it also impacts all other uses of Chromium on this system." ];
boot = {
extraModprobeConfig = ''
options snd-aloop enable=1,1,1,1,1,1,1,1
'';
kernelModules = [ "snd-aloop" ];
};
};
meta.maintainers = lib.teams.jitsi.members;
}