nixos/jitsi-videobridge: init
This commit is contained in:
parent
b128516ef1
commit
c695d57895
@ -642,6 +642,7 @@
|
||||
./services/networking/iperf3.nix
|
||||
./services/networking/ircd-hybrid/default.nix
|
||||
./services/networking/iwd.nix
|
||||
./services/networking/jitsi-videobridge.nix
|
||||
./services/networking/keepalived/default.nix
|
||||
./services/networking/keybase.nix
|
||||
./services/networking/kippo.nix
|
||||
|
276
nixos/modules/services/networking/jitsi-videobridge.nix
Normal file
276
nixos/modules/services/networking/jitsi-videobridge.nix
Normal file
@ -0,0 +1,276 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.jitsi-videobridge;
|
||||
attrsToArgs = a: concatStringsSep " " (mapAttrsToList (k: v: "${k}=${toString v}") a);
|
||||
|
||||
# HOCON is a JSON superset that videobridge2 uses for configuration.
|
||||
# It can substitute environment variables which we use for passwords here.
|
||||
# https://github.com/lightbend/config/blob/master/README.md
|
||||
#
|
||||
# Substitution for environment variable FOO is represented as attribute set
|
||||
# { __hocon_envvar = "FOO"; }
|
||||
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;
|
||||
|
||||
defaultJvbConfig = {
|
||||
videobridge = {
|
||||
ice = {
|
||||
tcp = {
|
||||
enabled = true;
|
||||
port = 4443;
|
||||
};
|
||||
udp.port = 10000;
|
||||
};
|
||||
stats = {
|
||||
enabled = true;
|
||||
transports = [ { type = "muc"; } ];
|
||||
};
|
||||
apis.xmpp-client.configs = flip mapAttrs cfg.xmppConfigs (name: xmppConfig: {
|
||||
hostname = xmppConfig.hostName;
|
||||
domain = xmppConfig.domain;
|
||||
username = xmppConfig.userName;
|
||||
password = { __hocon_envvar = toVarName name; };
|
||||
muc_jids = xmppConfig.mucJids;
|
||||
muc_nickname = xmppConfig.mucNickname;
|
||||
disable_certificate_verification = xmppConfig.disableCertificateVerification;
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
# Allow overriding leaves of the default config despite types.attrs not doing any merging.
|
||||
jvbConfig = recursiveUpdate defaultJvbConfig cfg.config;
|
||||
in
|
||||
{
|
||||
options.services.jitsi-videobridge = with types; {
|
||||
enable = mkEnableOption "Jitsi Videobridge, a WebRTC compatible video router";
|
||||
|
||||
config = mkOption {
|
||||
type = attrs;
|
||||
default = { };
|
||||
example = literalExample ''
|
||||
{
|
||||
videobridge = {
|
||||
ice.udp.port = 5000;
|
||||
websockets = {
|
||||
enabled = true;
|
||||
server-id = "jvb1";
|
||||
};
|
||||
};
|
||||
}
|
||||
'';
|
||||
description = ''
|
||||
Videobridge configuration.
|
||||
|
||||
See <link xlink:href="https://github.com/jitsi/jitsi-videobridge/blob/master/src/main/resources/reference.conf" />
|
||||
for default configuration with comments.
|
||||
'';
|
||||
};
|
||||
|
||||
xmppConfigs = mkOption {
|
||||
description = ''
|
||||
XMPP servers to connect to.
|
||||
|
||||
See <link xlink:href="https://github.com/jitsi/jitsi-videobridge/blob/master/doc/muc.md" /> for more information.
|
||||
'';
|
||||
default = { };
|
||||
example = literalExample ''
|
||||
{
|
||||
"localhost" = {
|
||||
hostName = "localhost";
|
||||
userName = "jvb";
|
||||
domain = "auth.xmpp.example.org";
|
||||
passwordFile = "/var/lib/jitsi-meet/videobridge-secret";
|
||||
mucJids = "jvbbrewery@internal.xmpp.example.org";
|
||||
};
|
||||
}
|
||||
'';
|
||||
type = attrsOf (submodule ({ name, ... }: {
|
||||
options = {
|
||||
hostName = mkOption {
|
||||
type = str;
|
||||
example = "xmpp.example.org";
|
||||
description = ''
|
||||
Hostname of the XMPP server to connect to. Name of the attribute set is used by default.
|
||||
'';
|
||||
};
|
||||
domain = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
example = "auth.xmpp.example.org";
|
||||
description = ''
|
||||
Domain part of JID of the XMPP user, if it is different from hostName.
|
||||
'';
|
||||
};
|
||||
userName = mkOption {
|
||||
type = str;
|
||||
default = "jvb";
|
||||
description = ''
|
||||
User part of the JID.
|
||||
'';
|
||||
};
|
||||
passwordFile = mkOption {
|
||||
type = str;
|
||||
example = "/run/keys/jitsi-videobridge-xmpp1";
|
||||
description = ''
|
||||
File containing the password for the user.
|
||||
'';
|
||||
};
|
||||
mucJids = mkOption {
|
||||
type = str;
|
||||
example = "jvbbrewery@internal.xmpp.example.org";
|
||||
description = ''
|
||||
JID of the MUC to join. JiCoFo needs to be configured to join the same MUC.
|
||||
'';
|
||||
};
|
||||
mucNickname = mkOption {
|
||||
# Upstream DEBs use UUID, let's use hostname instead.
|
||||
type = str;
|
||||
description = ''
|
||||
Videobridges use the same XMPP account and need to be distinguished by the
|
||||
nickname (aka resource part of the JID). By default, system hostname is used.
|
||||
'';
|
||||
};
|
||||
disableCertificateVerification = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to skip validation of the server's certificate.
|
||||
'';
|
||||
};
|
||||
};
|
||||
config = {
|
||||
hostName = mkDefault name;
|
||||
mucNickname = mkDefault (builtins.replaceStrings [ "." ] [ "-" ] (
|
||||
config.networking.hostName + optionalString (config.networking.domain != null) ".${config.networking.domain}"
|
||||
));
|
||||
};
|
||||
}));
|
||||
};
|
||||
|
||||
nat = {
|
||||
localAddress = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
example = "192.168.1.42";
|
||||
description = ''
|
||||
Local address when running behind NAT.
|
||||
'';
|
||||
};
|
||||
|
||||
publicAddress = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
example = "1.2.3.4";
|
||||
description = ''
|
||||
Public address when running behind NAT.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
extraProperties = mkOption {
|
||||
type = attrsOf str;
|
||||
default = { };
|
||||
description = ''
|
||||
Additional Java properties passed to jitsi-videobridge.
|
||||
'';
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to open ports in the firewall for the videobridge.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
users.groups.jitsi-meet = {};
|
||||
|
||||
services.jitsi-videobridge.extraProperties = optionalAttrs (cfg.nat.localAddress != null) {
|
||||
"org.ice4j.ice.harvest.NAT_HARVESTER_LOCAL_ADDRESS" = cfg.nat.localAddress;
|
||||
"org.ice4j.ice.harvest.NAT_HARVESTER_PUBLIC_ADDRESS" = cfg.nat.publicAddress;
|
||||
};
|
||||
|
||||
systemd.services.jitsi-videobridge2 = let
|
||||
jvbProps = {
|
||||
"-Dnet.java.sip.communicator.SC_HOME_DIR_LOCATION" = "/etc/jitsi";
|
||||
"-Dnet.java.sip.communicator.SC_HOME_DIR_NAME" = "videobridge";
|
||||
"-Djava.util.logging.config.file" = "/etc/jitsi/videobridge/logging.properties";
|
||||
"-Dconfig.file" = pkgs.writeText "jvb.conf" (toHOCON jvbConfig);
|
||||
} // (mapAttrs' (k: v: nameValuePair "-D${k}" v) cfg.extraProperties);
|
||||
in
|
||||
{
|
||||
aliases = [ "jitsi-videobridge.service" ];
|
||||
description = "Jitsi Videobridge";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
environment.JAVA_SYS_PROPS = attrsToArgs jvbProps;
|
||||
|
||||
script = (concatStrings (mapAttrsToList (name: xmppConfig:
|
||||
"export ${toVarName name}=$(cat ${xmppConfig.passwordFile})\n"
|
||||
) cfg.xmppConfigs))
|
||||
+ ''
|
||||
${pkgs.jitsi-videobridge}/bin/jitsi-videobridge --apis=none
|
||||
'';
|
||||
|
||||
serviceConfig = {
|
||||
Type = "exec";
|
||||
|
||||
DynamicUser = true;
|
||||
User = "jitsi-videobridge";
|
||||
Group = "jitsi-meet";
|
||||
|
||||
CapabilityBoundingSet = "";
|
||||
NoNewPrivileges = true;
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
PrivateTmp = true;
|
||||
PrivateDevices = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
|
||||
RestrictNamespaces = true;
|
||||
LockPersonality = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
|
||||
TasksMax = 65000;
|
||||
LimitNPROC = 65000;
|
||||
LimitNOFILE = 65000;
|
||||
};
|
||||
};
|
||||
|
||||
environment.etc."jitsi/videobridge/logging.properties".source =
|
||||
mkDefault "${pkgs.jitsi-videobridge}/etc/jitsi/videobridge/logging.properties-journal";
|
||||
|
||||
# (from videobridge2 .deb)
|
||||
# this sets the max, so that we can bump the JVB UDP single port buffer size.
|
||||
boot.kernel.sysctl."net.core.rmem_max" = mkDefault 10485760;
|
||||
boot.kernel.sysctl."net.core.netdev_max_backlog" = mkDefault 100000;
|
||||
|
||||
networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall
|
||||
[ jvbConfig.videobridge.ice.tcp.port ];
|
||||
networking.firewall.allowedUDPPorts = mkIf cfg.openFirewall
|
||||
[ jvbConfig.videobridge.ice.udp.port ];
|
||||
|
||||
assertions = [{
|
||||
message = "publicAddress must be set if and only if localAddress is set";
|
||||
assertion = (cfg.nat.publicAddress == null) == (cfg.nat.localAddress == null);
|
||||
}];
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ ];
|
||||
}
|
Loading…
Reference in New Issue
Block a user