Unverified Commit cac11727 authored by Julien Malka's avatar Julien Malka Committed by GitHub
Browse files

Merge pull request #227588 from camillemndn/jitsi-meet

nixos/jitsi-meet: updated prosody, support secure domain setup and Excalidraw whiteboards
parents 19e27c35 1f438f85
Loading
Loading
Loading
Loading
+159 −19
Original line number Diff line number Diff line
@@ -169,6 +169,15 @@ in
        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 {
@@ -192,41 +201,118 @@ in
          roomLocking = false;
          roomDefaultPublicJids = true;
          extraConfig = ''
            restrict_room_creation = true
            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";
          roomLocking = false;
          roomDefaultPublicJids = true;
          extraConfig = ''
            storage = "memory"
            admins = { "focus@auth.${cfg.hostName}", "jvb@auth.${cfg.hostName}" }
          '';
          #-- 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" ];
      extraConfig = lib.mkMerge [ (mkAfter ''
      extraConfig = lib.mkMerge [
        (mkAfter ''
          Component "focus.${cfg.hostName}" "client_proxy"
            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 ''
          muc_mapper_domain_base = "${cfg.hostName}"

          cross_domain_websocket = true;
          consider_websocket_secure = true;

          unlimited_jids = {
            "focus@auth.${cfg.hostName}",
            "jvb@auth.${cfg.hostName}"
          }
        '')
      ];
      virtualHosts.${cfg.hostName} = {
        enabled = true;
        domain = cfg.hostName;
        extraConfig = ''
          authentication = "anonymous"
          authentication = ${if cfg.secureDomain.enable then "\"internal_hashed\"" else "\"jitsi-anonymous\""}
          c2s_require_encryption = false
          admins = { "focus@auth.${cfg.hostName}" }
          smacks_max_unacked_stanzas = 5
          smacks_hibernation_time = 60
          smacks_max_hibernated_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 = {
          cert = "/var/lib/jitsi-meet/jitsi-meet.crt";
@@ -237,7 +323,7 @@ in
        enabled = true;
        domain = "auth.${cfg.hostName}";
        extraConfig = ''
          authentication = "internal_plain"
          authentication = "internal_hashed"
        '';
        ssl = {
          cert = "/var/lib/jitsi-meet/jitsi-meet.crt";
@@ -252,6 +338,14 @@ in
          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 {
      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 {
      enable = mkDefault true;
      virtualHosts.${cfg.hostName} = {
@@ -345,12 +453,23 @@ in
        locations."=/external_api.js" = mkDefault {
          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 {
          alias = overrideJs "${pkgs.jitsi-meet}/config.js" "config" (recursiveUpdate defaultCfg cfg.config) cfg.extraConfig;
        };
        locations."=/interface_config.js" = mkDefault {
          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 {
      enable = true;
      xmppConfigs."localhost" = {
        userName = "jvb";
        domain = "auth.${cfg.hostName}";
        passwordFile = "/var/lib/jitsi-meet/videobridge-secret";
        mucJids = "jvbbrewery@internal.${cfg.hostName}";
        mucJids = "jvbbrewery@internal.auth.${cfg.hostName}";
        disableCertificateVerification = true;
      };
    };
@@ -409,16 +539,26 @@ in
      userName = "focus";
      userPasswordFile = "/var/lib/jitsi-meet/jicofo-user-secret";
      componentPasswordFile = "/var/lib/jitsi-meet/jicofo-component-secret";
      bridgeMuc = "jvbbrewery@internal.${cfg.hostName}";
      bridgeMuc = "jvbbrewery@internal.auth.${cfg.hostName}";
      config = mkMerge [{
        jicofo.xmpp.service.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 = {
           brewery-jid = "JibriBrewery@internal.${cfg.hostName}";
            brewery-jid = "JibriBrewery@internal.auth.${cfg.hostName}";
            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;

        control.muc = {
          domain = "internal.${cfg.hostName}";
          domain = "internal.auth.${cfg.hostName}";
          roomName = "JibriBrewery";
          nickname = "jibri";
        };
+40 −0
Original line number Diff line number Diff line
{ 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 ];
  };
}
+2 −0
Original line number Diff line number Diff line
@@ -26552,6 +26552,8 @@ with pkgs;
  jicofo = callPackage ../servers/jicofo { };
  jitsi-excalidraw = callPackage ../servers/jitsi-excalidraw { };
  jitsi-meet = callPackage ../servers/web-apps/jitsi-meet { };
  jitsi-meet-prosody = callPackage ../misc/jitsi-meet-prosody { };