at 24.11-pre 7.6 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.jigasi; 7 homeDirName = "jigasi-home"; 8 stateDir = "/tmp"; 9 sipCommunicatorPropertiesFile = "${stateDir}/${homeDirName}/sip-communicator.properties"; 10 sipCommunicatorPropertiesFileUnsubstituted = "${pkgs.jigasi}/etc/jitsi/jigasi/sip-communicator.properties"; 11in 12{ 13 options.services.jigasi = with types; { 14 enable = mkEnableOption "Jitsi Gateway to SIP - component of Jitsi Meet"; 15 16 xmppHost = mkOption { 17 type = str; 18 example = "localhost"; 19 description = '' 20 Hostname of the XMPP server to connect to. 21 ''; 22 }; 23 24 xmppDomain = mkOption { 25 type = nullOr str; 26 example = "meet.example.org"; 27 description = '' 28 Domain name of the XMMP server to which to connect as a component. 29 30 If null, <option>xmppHost</option> is used. 31 ''; 32 }; 33 34 componentPasswordFile = mkOption { 35 type = str; 36 example = "/run/keys/jigasi-component"; 37 description = '' 38 Path to file containing component secret. 39 ''; 40 }; 41 42 userName = mkOption { 43 type = str; 44 default = "callcontrol"; 45 description = '' 46 User part of the JID for XMPP user connection. 47 ''; 48 }; 49 50 userDomain = mkOption { 51 type = str; 52 example = "internal.meet.example.org"; 53 description = '' 54 Domain part of the JID for XMPP user connection. 55 ''; 56 }; 57 58 userPasswordFile = mkOption { 59 type = str; 60 example = "/run/keys/jigasi-user"; 61 description = '' 62 Path to file containing password for XMPP user connection. 63 ''; 64 }; 65 66 bridgeMuc = mkOption { 67 type = str; 68 example = "jigasibrewery@internal.meet.example.org"; 69 description = '' 70 JID of the internal MUC used to communicate with Videobridges. 71 ''; 72 }; 73 74 defaultJvbRoomName = mkOption { 75 type = str; 76 default = ""; 77 example = "siptest"; 78 description = '' 79 Name of the default JVB room that will be joined if no special header is included in SIP invite. 80 ''; 81 }; 82 83 environmentFile = mkOption { 84 type = types.nullOr types.path; 85 default = null; 86 description = '' 87 File containing environment variables to be passed to the jigasi service, 88 in which secret tokens can be specified securely by defining values for 89 <literal>JIGASI_SIPUSER</literal>, 90 <literal>JIGASI_SIPPWD</literal>, 91 <literal>JIGASI_SIPSERVER</literal> and 92 <literal>JIGASI_SIPPORT</literal>. 93 ''; 94 }; 95 96 config = mkOption { 97 type = attrsOf str; 98 default = { }; 99 example = literalExpression '' 100 { 101 "org.jitsi.jigasi.auth.URL" = "XMPP:jitsi-meet.example.com"; 102 } 103 ''; 104 description = '' 105 Contents of the <filename>sip-communicator.properties</filename> configuration file for jigasi. 106 ''; 107 }; 108 }; 109 110 config = mkIf cfg.enable { 111 services.jicofo.config = { 112 "org.jitsi.jicofo.jigasi.BREWERY" = "${cfg.bridgeMuc}"; 113 }; 114 115 services.jigasi.config = mapAttrs (_: v: mkDefault v) { 116 "org.jitsi.jigasi.BRIDGE_MUC" = cfg.bridgeMuc; 117 }; 118 119 users.groups.jitsi-meet = {}; 120 121 systemd.services.jigasi = let 122 jigasiProps = { 123 "-Dnet.java.sip.communicator.SC_HOME_DIR_LOCATION" = "${stateDir}"; 124 "-Dnet.java.sip.communicator.SC_HOME_DIR_NAME" = "${homeDirName}"; 125 "-Djava.util.logging.config.file" = "${pkgs.jigasi}/etc/jitsi/jigasi/logging.properties"; 126 }; 127 in 128 { 129 description = "Jitsi Gateway to SIP"; 130 wantedBy = [ "multi-user.target" ]; 131 after = [ "network.target" ]; 132 133 preStart = '' 134 [ -f "${sipCommunicatorPropertiesFile}" ] && rm -f "${sipCommunicatorPropertiesFile}" 135 mkdir -p "$(dirname ${sipCommunicatorPropertiesFile})" 136 temp="${sipCommunicatorPropertiesFile}.unsubstituted" 137 138 export DOMAIN_BASE="${cfg.xmppDomain}" 139 export JIGASI_XMPP_PASSWORD=$(cat "${cfg.userPasswordFile}") 140 export JIGASI_DEFAULT_JVB_ROOM_NAME="${cfg.defaultJvbRoomName}" 141 142 # encode the credentials to base64 143 export JIGASI_SIPPWD=$(echo -n "$JIGASI_SIPPWD" | base64 -w 0) 144 export JIGASI_XMPP_PASSWORD_BASE64=$(cat "${cfg.userPasswordFile}" | base64 -w 0) 145 146 cp "${sipCommunicatorPropertiesFileUnsubstituted}" "$temp" 147 chmod 644 "$temp" 148 cat <<EOF >>"$temp" 149 net.java.sip.communicator.impl.protocol.sip.acc1403273890647.SERVER_PORT=$JIGASI_SIPPORT 150 net.java.sip.communicator.impl.protocol.sip.acc1403273890647.PREFERRED_TRANSPORT=udp 151 EOF 152 chmod 444 "$temp" 153 154 # Replace <<$VAR_NAME>> from example config to $VAR_NAME for environment substitution 155 sed -i -E \ 156 's/<<([^>]+)>>/\$\1/g' \ 157 "$temp" 158 159 sed -i \ 160 's|\(net\.java\.sip\.communicator\.impl\.protocol\.jabber\.acc-xmpp-1\.PASSWORD=\).*|\1\$JIGASI_XMPP_PASSWORD_BASE64|g' \ 161 "$temp" 162 163 sed -i \ 164 's|\(#\)\(org.jitsi.jigasi.DEFAULT_JVB_ROOM_NAME=\).*|\2\$JIGASI_DEFAULT_JVB_ROOM_NAME|g' \ 165 "$temp" 166 167 ${pkgs.envsubst}/bin/envsubst \ 168 -o "${sipCommunicatorPropertiesFile}" \ 169 -i "$temp" 170 171 # Set the brewery room name 172 sed -i \ 173 's|\(net\.java\.sip\.communicator\.impl\.protocol\.jabber\.acc-xmpp-1\.BREWERY=\).*|\1${cfg.bridgeMuc}|g' \ 174 "${sipCommunicatorPropertiesFile}" 175 sed -i \ 176 's|\(org\.jitsi\.jigasi\.ALLOWED_JID=\).*|\1${cfg.bridgeMuc}|g' \ 177 "${sipCommunicatorPropertiesFile}" 178 179 180 # Disable certificate verification for self-signed certificates 181 sed -i \ 182 's|\(# \)\(net.java.sip.communicator.service.gui.ALWAYS_TRUST_MODE_ENABLED=true\)|\2|g' \ 183 "${sipCommunicatorPropertiesFile}" 184 ''; 185 186 restartTriggers = [ 187 config.environment.etc."jitsi/jigasi/sip-communicator.properties".source 188 ]; 189 environment.JAVA_SYS_PROPS = concatStringsSep " " (mapAttrsToList (k: v: "${k}=${toString v}") jigasiProps); 190 191 script = '' 192 ${pkgs.jigasi}/bin/jigasi \ 193 --host="${cfg.xmppHost}" \ 194 --domain="${if cfg.xmppDomain == null then cfg.xmppHost else cfg.xmppDomain}" \ 195 --secret="$(cat ${cfg.componentPasswordFile})" \ 196 --user_name="${cfg.userName}" \ 197 --user_domain="${cfg.userDomain}" \ 198 --user_password="$(cat ${cfg.userPasswordFile})" \ 199 --configdir="${stateDir}" \ 200 --configdirname="${homeDirName}" 201 ''; 202 203 serviceConfig = { 204 Type = "exec"; 205 206 DynamicUser = true; 207 User = "jigasi"; 208 Group = "jitsi-meet"; 209 210 CapabilityBoundingSet = ""; 211 NoNewPrivileges = true; 212 ProtectSystem = "strict"; 213 ProtectHome = true; 214 PrivateTmp = true; 215 PrivateDevices = true; 216 ProtectHostname = true; 217 ProtectKernelTunables = true; 218 ProtectKernelModules = true; 219 ProtectControlGroups = true; 220 RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ]; 221 RestrictNamespaces = true; 222 LockPersonality = true; 223 RestrictRealtime = true; 224 RestrictSUIDSGID = true; 225 StateDirectory = baseNameOf stateDir; 226 EnvironmentFile = cfg.environmentFile; 227 }; 228 }; 229 230 environment.etc."jitsi/jigasi/sip-communicator.properties".source = 231 mkDefault "${sipCommunicatorPropertiesFile}"; 232 environment.etc."jitsi/jigasi/logging.properties".source = 233 mkDefault "${stateDir}/logging.properties-journal"; 234 }; 235 236 meta.maintainers = lib.teams.jitsi.members; 237}