Merge pull request #227588 from camillemndn/jitsi-meet

nixos/jitsi-meet: updated prosody, support secure domain setup and Excalidraw whiteboards
This commit is contained in:
Julien Malka 2023-11-17 22:08:05 +01:00 committed by GitHub
commit cac11727b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 201 additions and 19 deletions

View File

@ -169,6 +169,15 @@ in
off if you want to configure it manually. off if you want to configure it manually.
''; '';
}; };
excalidraw.enable = mkEnableOption (lib.mdDoc "Excalidraw collaboration backend for Jitsi");
excalidraw.port = mkOption {
type = types.port;
default = 3002;
description = lib.mdDoc ''The port which the Excalidraw backend for Jitsi should listen to.'';
};
secureDomain.enable = mkEnableOption (lib.mdDoc "Authenticated room creation");
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
@ -192,41 +201,118 @@ in
roomLocking = false; roomLocking = false;
roomDefaultPublicJids = true; roomDefaultPublicJids = true;
extraConfig = '' extraConfig = ''
restrict_room_creation = true
storage = "memory" storage = "memory"
admins = { "focus@auth.${cfg.hostName}" }
''; '';
} }
{ {
domain = "internal.${cfg.hostName}"; domain = "breakout.${cfg.hostName}";
name = "Jitsi Meet Breakout MUC";
roomLocking = false;
roomDefaultPublicJids = true;
extraConfig = ''
restrict_room_creation = true
storage = "memory"
admins = { "focus@auth.${cfg.hostName}" }
'';
}
{
domain = "internal.auth.${cfg.hostName}";
name = "Jitsi Meet Videobridge MUC"; name = "Jitsi Meet Videobridge MUC";
roomLocking = false;
roomDefaultPublicJids = true;
extraConfig = '' extraConfig = ''
storage = "memory" storage = "memory"
admins = { "focus@auth.${cfg.hostName}", "jvb@auth.${cfg.hostName}" } admins = { "focus@auth.${cfg.hostName}", "jvb@auth.${cfg.hostName}" }
''; '';
#-- muc_room_cache_size = 1000 #-- muc_room_cache_size = 1000
} }
{
domain = "lobby.${cfg.hostName}";
name = "Jitsi Meet Lobby MUC";
roomLocking = false;
roomDefaultPublicJids = true;
extraConfig = ''
restrict_room_creation = true
storage = "memory"
'';
}
];
extraModules = [
"pubsub"
"smacks"
"speakerstats"
"external_services"
"conference_duration"
"end_conference"
"muc_lobby_rooms"
"muc_breakout_rooms"
"av_moderation"
"muc_hide_all"
"muc_meeting_id"
"muc_domain_mapper"
"muc_rate_limit"
"limits_exception"
"persistent_lobby"
"room_metadata"
]; ];
extraModules = [ "pubsub" "smacks" ];
extraPluginPaths = [ "${pkgs.jitsi-meet-prosody}/share/prosody-plugins" ]; extraPluginPaths = [ "${pkgs.jitsi-meet-prosody}/share/prosody-plugins" ];
extraConfig = lib.mkMerge [ (mkAfter '' extraConfig = lib.mkMerge [
(mkAfter ''
Component "focus.${cfg.hostName}" "client_proxy" Component "focus.${cfg.hostName}" "client_proxy"
target_address = "focus@auth.${cfg.hostName}" target_address = "focus@auth.${cfg.hostName}"
Component "speakerstats.${cfg.hostName}" "speakerstats_component"
muc_component = "conference.${cfg.hostName}"
Component "conferenceduration.${cfg.hostName}" "conference_duration_component"
muc_component = "conference.${cfg.hostName}"
Component "endconference.${cfg.hostName}" "end_conference"
muc_component = "conference.${cfg.hostName}"
Component "avmoderation.${cfg.hostName}" "av_moderation_component"
muc_component = "conference.${cfg.hostName}"
Component "metadata.${cfg.hostName}" "room_metadata_component"
muc_component = "conference.${cfg.hostName}"
breakout_rooms_component = "breakout.${cfg.hostName}"
'') '')
(mkBefore '' (mkBefore ''
muc_mapper_domain_base = "${cfg.hostName}"
cross_domain_websocket = true; cross_domain_websocket = true;
consider_websocket_secure = true; consider_websocket_secure = true;
unlimited_jids = {
"focus@auth.${cfg.hostName}",
"jvb@auth.${cfg.hostName}"
}
'') '')
]; ];
virtualHosts.${cfg.hostName} = { virtualHosts.${cfg.hostName} = {
enabled = true; enabled = true;
domain = cfg.hostName; domain = cfg.hostName;
extraConfig = '' extraConfig = ''
authentication = "anonymous" authentication = ${if cfg.secureDomain.enable then "\"internal_hashed\"" else "\"jitsi-anonymous\""}
c2s_require_encryption = false c2s_require_encryption = false
admins = { "focus@auth.${cfg.hostName}" } admins = { "focus@auth.${cfg.hostName}" }
smacks_max_unacked_stanzas = 5 smacks_max_unacked_stanzas = 5
smacks_hibernation_time = 60 smacks_hibernation_time = 60
smacks_max_hibernated_sessions = 1 smacks_max_hibernated_sessions = 1
smacks_max_old_sessions = 1 smacks_max_old_sessions = 1
av_moderation_component = "avmoderation.${cfg.hostName}"
speakerstats_component = "speakerstats.${cfg.hostName}"
conference_duration_component = "conferenceduration.${cfg.hostName}"
end_conference_component = "endconference.${cfg.hostName}"
c2s_require_encryption = false
lobby_muc = "lobby.${cfg.hostName}"
breakout_rooms_muc = "breakout.${cfg.hostName}"
room_metadata_component = "metadata.${cfg.hostName}"
main_muc = "conference.${cfg.hostName}"
''; '';
ssl = { ssl = {
cert = "/var/lib/jitsi-meet/jitsi-meet.crt"; cert = "/var/lib/jitsi-meet/jitsi-meet.crt";
@ -237,7 +323,7 @@ in
enabled = true; enabled = true;
domain = "auth.${cfg.hostName}"; domain = "auth.${cfg.hostName}";
extraConfig = '' extraConfig = ''
authentication = "internal_plain" authentication = "internal_hashed"
''; '';
ssl = { ssl = {
cert = "/var/lib/jitsi-meet/jitsi-meet.crt"; cert = "/var/lib/jitsi-meet/jitsi-meet.crt";
@ -252,6 +338,14 @@ in
c2s_require_encryption = false c2s_require_encryption = false
''; '';
}; };
virtualHosts."guest.${cfg.hostName}" = {
enabled = true;
domain = "guest.${cfg.hostName}";
extraConfig = ''
authentication = "anonymous"
c2s_require_encryption = false
'';
};
}; };
systemd.services.prosody = mkIf cfg.prosody.enable { systemd.services.prosody = mkIf cfg.prosody.enable {
preStart = let preStart = let
@ -317,6 +411,20 @@ in
''; '';
}; };
systemd.services.jitsi-excalidraw = mkIf cfg.excalidraw.enable {
description = "Excalidraw collaboration backend for Jitsi";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
environment.PORT = toString cfg.excalidraw.port;
serviceConfig = {
Type = "simple";
ExecStart = "${pkgs.jitsi-excalidraw}/bin/jitsi-excalidraw-backend";
Restart = "on-failure";
Group = "jitsi-meet";
};
};
services.nginx = mkIf cfg.nginx.enable { services.nginx = mkIf cfg.nginx.enable {
enable = mkDefault true; enable = mkDefault true;
virtualHosts.${cfg.hostName} = { virtualHosts.${cfg.hostName} = {
@ -345,12 +453,23 @@ in
locations."=/external_api.js" = mkDefault { locations."=/external_api.js" = mkDefault {
alias = "${pkgs.jitsi-meet}/libs/external_api.min.js"; alias = "${pkgs.jitsi-meet}/libs/external_api.min.js";
}; };
locations."=/_api/room-info" = {
proxyPass = "http://localhost:5280/room-info";
extraConfig = ''
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
'';
};
locations."=/config.js" = mkDefault { locations."=/config.js" = mkDefault {
alias = overrideJs "${pkgs.jitsi-meet}/config.js" "config" (recursiveUpdate defaultCfg cfg.config) cfg.extraConfig; alias = overrideJs "${pkgs.jitsi-meet}/config.js" "config" (recursiveUpdate defaultCfg cfg.config) cfg.extraConfig;
}; };
locations."=/interface_config.js" = mkDefault { locations."=/interface_config.js" = mkDefault {
alias = overrideJs "${pkgs.jitsi-meet}/interface_config.js" "interfaceConfig" cfg.interfaceConfig ""; alias = overrideJs "${pkgs.jitsi-meet}/interface_config.js" "interfaceConfig" cfg.interfaceConfig "";
}; };
locations."/socket.io/" = mkIf cfg.excalidraw.enable {
proxyPass = "http://127.0.0.1:${toString cfg.excalidraw.port}";
proxyWebsockets = true;
};
}; };
}; };
@ -390,13 +509,24 @@ in
}; };
}; };
services.jitsi-meet.config = recursiveUpdate
(mkIf cfg.excalidraw.enable {
whiteboard = {
enabled = true;
collabServerBaseUrl = "https://${cfg.hostName}";
};
})
(mkIf cfg.secureDomain.enable {
hosts.anonymousdomain = "guest.${cfg.hostName}";
});
services.jitsi-videobridge = mkIf cfg.videobridge.enable { services.jitsi-videobridge = mkIf cfg.videobridge.enable {
enable = true; enable = true;
xmppConfigs."localhost" = { xmppConfigs."localhost" = {
userName = "jvb"; userName = "jvb";
domain = "auth.${cfg.hostName}"; domain = "auth.${cfg.hostName}";
passwordFile = "/var/lib/jitsi-meet/videobridge-secret"; passwordFile = "/var/lib/jitsi-meet/videobridge-secret";
mucJids = "jvbbrewery@internal.${cfg.hostName}"; mucJids = "jvbbrewery@internal.auth.${cfg.hostName}";
disableCertificateVerification = true; disableCertificateVerification = true;
}; };
}; };
@ -409,16 +539,26 @@ in
userName = "focus"; userName = "focus";
userPasswordFile = "/var/lib/jitsi-meet/jicofo-user-secret"; userPasswordFile = "/var/lib/jitsi-meet/jicofo-user-secret";
componentPasswordFile = "/var/lib/jitsi-meet/jicofo-component-secret"; componentPasswordFile = "/var/lib/jitsi-meet/jicofo-component-secret";
bridgeMuc = "jvbbrewery@internal.${cfg.hostName}"; bridgeMuc = "jvbbrewery@internal.auth.${cfg.hostName}";
config = mkMerge [{ config = mkMerge [{
jicofo.xmpp.service.disable-certificate-verification = true; jicofo.xmpp.service.disable-certificate-verification = true;
jicofo.xmpp.client.disable-certificate-verification = true; jicofo.xmpp.client.disable-certificate-verification = true;
#} (lib.mkIf cfg.jibri.enable { }
} (lib.mkIf (config.services.jibri.enable || cfg.jibri.enable) { (lib.mkIf (config.services.jibri.enable || cfg.jibri.enable) {
jicofo.jibri = { jicofo.jibri = {
brewery-jid = "JibriBrewery@internal.${cfg.hostName}"; brewery-jid = "JibriBrewery@internal.auth.${cfg.hostName}";
pending-timeout = "90"; pending-timeout = "90";
}; };
})
(lib.mkIf cfg.secureDomain.enable {
jicofo = {
authentication = {
enabled = "true";
type = "XMPP";
login-url = cfg.hostName;
};
xmpp.client.client-proxy = "focus.${cfg.hostName}";
};
})]; })];
}; };
@ -430,7 +570,7 @@ in
xmppDomain = cfg.hostName; xmppDomain = cfg.hostName;
control.muc = { control.muc = {
domain = "internal.${cfg.hostName}"; domain = "internal.auth.${cfg.hostName}";
roomName = "JibriBrewery"; roomName = "JibriBrewery";
nickname = "jibri"; nickname = "jibri";
}; };

View File

@ -0,0 +1,40 @@
{ lib
, buildNpmPackage
, fetchFromGitHub
, nodejs
, python3
}:
buildNpmPackage rec {
pname = "jitsi-excalidraw-backend";
version = "17";
src = fetchFromGitHub {
owner = "jitsi";
repo = "excalidraw-backend";
rev = "x${version}";
hash = "sha256-aQePkVA8KRL06VewiD0ePRpj88pAItcV7B2SBnRRtCs=";
};
npmDepsHash = "sha256-BJqjaqTeg5i+ECGMuiBYVToK2i2XCOVP9yeDFz6nP4k=";
nativeBuildInputs = [ python3 ];
installPhase = ''
mkdir -p $out/share
cp -r {node_modules,dist} $out/share
'';
postFixup = ''
makeWrapper ${nodejs}/bin/node $out/bin/jitsi-excalidraw-backend \
--add-flags dist/index.js \
--chdir $out/share
'';
meta = with lib; {
description = "Excalidraw collaboration backend for Jitsi";
homepage = "https://github.com/jitsi/excalidraw-backend";
license = licenses.mit;
maintainers = with maintainers; [ camillemndn ];
};
}

View File

@ -26552,6 +26552,8 @@ with pkgs;
jicofo = callPackage ../servers/jicofo { }; jicofo = callPackage ../servers/jicofo { };
jitsi-excalidraw = callPackage ../servers/jitsi-excalidraw { };
jitsi-meet = callPackage ../servers/web-apps/jitsi-meet { }; jitsi-meet = callPackage ../servers/web-apps/jitsi-meet { };
jitsi-meet-prosody = callPackage ../misc/jitsi-meet-prosody { }; jitsi-meet-prosody = callPackage ../misc/jitsi-meet-prosody { };