1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.jicofo;
7
8 # HOCON is a JSON superset that some jitsi-meet components use for configuration
9 toHOCON = x: if isAttrs x && x ? __hocon_envvar then ("\${" + x.__hocon_envvar + "}")
10 else if isAttrs x && x ? __hocon_unquoted_string then x.__hocon_unquoted_string
11 else if isAttrs x then "{${ concatStringsSep "," (mapAttrsToList (k: v: ''"${k}":${toHOCON v}'') x) }}"
12 else if isList x then "[${ concatMapStringsSep "," toHOCON x }]"
13 else builtins.toJSON x;
14
15 configFile = pkgs.writeText "jicofo.conf" (toHOCON cfg.config);
16in
17{
18 options.services.jicofo = with types; {
19 enable = mkEnableOption (lib.mdDoc "Jitsi Conference Focus - component of Jitsi Meet");
20
21 xmppHost = mkOption {
22 type = str;
23 example = "localhost";
24 description = lib.mdDoc ''
25 Hostname of the XMPP server to connect to.
26 '';
27 };
28
29 xmppDomain = mkOption {
30 type = nullOr str;
31 example = "meet.example.org";
32 description = lib.mdDoc ''
33 Domain name of the XMMP server to which to connect as a component.
34
35 If null, {option}`xmppHost` is used.
36 '';
37 };
38
39 componentPasswordFile = mkOption {
40 type = str;
41 example = "/run/keys/jicofo-component";
42 description = lib.mdDoc ''
43 Path to file containing component secret.
44 '';
45 };
46
47 userName = mkOption {
48 type = str;
49 default = "focus";
50 description = lib.mdDoc ''
51 User part of the JID for XMPP user connection.
52 '';
53 };
54
55 userDomain = mkOption {
56 type = str;
57 example = "auth.meet.example.org";
58 description = lib.mdDoc ''
59 Domain part of the JID for XMPP user connection.
60 '';
61 };
62
63 userPasswordFile = mkOption {
64 type = str;
65 example = "/run/keys/jicofo-user";
66 description = lib.mdDoc ''
67 Path to file containing password for XMPP user connection.
68 '';
69 };
70
71 bridgeMuc = mkOption {
72 type = str;
73 example = "jvbbrewery@internal.meet.example.org";
74 description = lib.mdDoc ''
75 JID of the internal MUC used to communicate with Videobridges.
76 '';
77 };
78
79 config = mkOption {
80 type = (pkgs.formats.json {}).type;
81 default = { };
82 example = literalExpression ''
83 {
84 jicofo.bridge.max-bridge-participants = 42;
85 }
86 '';
87 description = lib.mdDoc ''
88 Contents of the {file}`jicofo.conf` configuration file.
89 '';
90 };
91 };
92
93 config = mkIf cfg.enable {
94 services.jicofo.config = {
95 jicofo = {
96 bridge.brewery-jid = cfg.bridgeMuc;
97 xmpp = rec {
98 client = {
99 hostname = cfg.xmppHost;
100 username = cfg.userName;
101 domain = cfg.userDomain;
102 password = { __hocon_envvar = "JICOFO_AUTH_PASS"; };
103 xmpp-domain = if cfg.xmppDomain == null then cfg.xmppHost else cfg.xmppDomain;
104 };
105 service = client;
106 };
107 };
108 };
109
110 users.groups.jitsi-meet = {};
111
112 systemd.services.jicofo = let
113 jicofoProps = {
114 "-Dnet.java.sip.communicator.SC_HOME_DIR_LOCATION" = "/etc/jitsi";
115 "-Dnet.java.sip.communicator.SC_HOME_DIR_NAME" = "jicofo";
116 "-Djava.util.logging.config.file" = "/etc/jitsi/jicofo/logging.properties";
117 "-Dconfig.file" = configFile;
118 };
119 in
120 {
121 description = "JItsi COnference FOcus";
122 wantedBy = [ "multi-user.target" ];
123 after = [ "network.target" ];
124
125 restartTriggers = [
126 configFile
127 ];
128 environment.JAVA_SYS_PROPS = concatStringsSep " " (mapAttrsToList (k: v: "${k}=${toString v}") jicofoProps);
129
130 script = ''
131 export JICOFO_AUTH_PASS="$(<${cfg.userPasswordFile})"
132 exec "${pkgs.jicofo}/bin/jicofo"
133 '';
134
135 serviceConfig = {
136 Type = "exec";
137
138 DynamicUser = true;
139 User = "jicofo";
140 Group = "jitsi-meet";
141
142 CapabilityBoundingSet = "";
143 NoNewPrivileges = true;
144 ProtectSystem = "strict";
145 ProtectHome = true;
146 PrivateTmp = true;
147 PrivateDevices = true;
148 ProtectHostname = true;
149 ProtectKernelTunables = true;
150 ProtectKernelModules = true;
151 ProtectControlGroups = true;
152 RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
153 RestrictNamespaces = true;
154 LockPersonality = true;
155 RestrictRealtime = true;
156 RestrictSUIDSGID = true;
157 };
158 };
159
160 environment.etc."jitsi/jicofo/sip-communicator.properties".text = "";
161 environment.etc."jitsi/jicofo/logging.properties".source =
162 mkDefault "${pkgs.jicofo}/etc/jitsi/jicofo/logging.properties-journal";
163 };
164
165 meta.maintainers = lib.teams.jitsi.members;
166}