Unverified Commit def08aa2 authored by lassulus's avatar lassulus Committed by GitHub
Browse files

jitsi-meet: Default NAT harvester, Excalidraw Caddy, Prosody lockdown (#280615)

parents 0b86640b 40c1971b
Loading
Loading
Loading
Loading
+27 −6
Original line number Diff line number Diff line
@@ -156,7 +156,7 @@ in
        default = null;
        example = "192.168.1.42";
        description = ''
          Local address when running behind NAT.
          Local address to assume when running behind NAT.
        '';
      };

@@ -165,7 +165,25 @@ in
        default = null;
        example = "1.2.3.4";
        description = ''
          Public address when running behind NAT.
          Public address to assume when running behind NAT.
        '';
      };

      harvesterAddresses = lib.mkOption {
        type = listOf str;
        default = [
          "stunserver.stunprotocol.org:3478"
          "stun.framasoft.org:3478"
          "meet-jit-si-turnrelay.jitsi.net:443"
        ];
        example = [];
        description = ''
          Addresses of public STUN services to use to automatically find
          the public and local addresses of this Jitsi-Videobridge instance
          without the need for manual configuration.

          This option is ignored if {option}`services.jitsi-videobridge.nat.localAddress`
          and {option}`services.jitsi-videobridge.nat.publicAddress` are set.
        '';
      };
    };
@@ -199,9 +217,12 @@ in
  config = lib.mkIf cfg.enable {
    users.groups.jitsi-meet = {};

    services.jitsi-videobridge.extraProperties = lib.optionalAttrs (cfg.nat.localAddress != null) {
    services.jitsi-videobridge.extraProperties =
      if (cfg.nat.localAddress != null) then {
        "org.ice4j.ice.harvest.NAT_HARVESTER_LOCAL_ADDRESS" = cfg.nat.localAddress;
        "org.ice4j.ice.harvest.NAT_HARVESTER_PUBLIC_ADDRESS" = cfg.nat.publicAddress;
      } else {
        "org.ice4j.ice.harvest.STUN_MAPPING_HARVESTER_ADDRESSES" = lib.concatStringsSep "," cfg.nat.harvesterAddresses;
      };

    systemd.services.jitsi-videobridge2 = let
+8 −0
Original line number Diff line number Diff line
@@ -19,6 +19,13 @@ A minimal configuration using Let's Encrypt for TLS certificates looks like this
}
```

Jitsi Meet depends on the Prosody XMPP server only for message passing from
the web browser while the default Prosody configuration is intended for use
with standalone XMPP clients and XMPP federation. If you only use Prosody as
a backend for Jitsi Meet it is therefore recommended to also enable
{option}`services.jitsi-meet.prosody.lockdown` option to disable unnecessary
Prosody features such as federation or the file proxy.

## Configuration {#module-services-jitsi-configuration}

Here is the minimal configuration with additional configurations:
@@ -27,6 +34,7 @@ Here is the minimal configuration with additional configurations:
  services.jitsi-meet = {
    enable = true;
    hostName = "jitsi.example.com";
    prosody.lockdown = true;
    config = {
      enableWelcomePage = false;
      prejoinPageEnabled = true;
+51 −4
Original line number Diff line number Diff line
@@ -175,11 +175,26 @@ in
    prosody.enable = mkOption {
      type = bool;
      default = true;
      example = false;
      description = ''
        Whether to configure Prosody to relay XMPP messages between Jitsi Meet components. Turn this
        off if you want to configure it manually.
      '';
    };
    prosody.lockdown = mkOption {
      type = bool;
      default = false;
      example = true;
      description = ''
        Whether to disable Prosody features not needed by Jitsi Meet.

        The default Prosody configuration assumes that it will be used as a
        general-purpose XMPP server rather than as a companion service for
        Jitsi Meet. This option reconfigures Prosody to only listen on
        localhost without support for TLS termination, XMPP federation or
        the file transfer proxy.
      '';
    };

    excalidraw.enable = mkEnableOption "Excalidraw collaboration backend for Jitsi";
    excalidraw.port = mkOption {
@@ -211,7 +226,10 @@ in
        smacks = mkDefault true;
        tls = mkDefault true;
        websocket = mkDefault true;
        proxy65 = mkIf cfg.prosody.lockdown (mkDefault false);
      };
      httpInterfaces = mkIf cfg.prosody.lockdown (mkDefault [ "127.0.0.1" ]);
      httpsPorts = mkIf cfg.prosody.lockdown (mkDefault []);
      muc = [
        {
          domain = "conference.${cfg.hostName}";
@@ -232,7 +250,7 @@ in
          extraConfig = ''
            restrict_room_creation = true
            storage = "memory"
            admins = { "focus@auth.${cfg.hostName}" }
            admins = { "focus@auth.${cfg.hostName}", "jvb@auth.${cfg.hostName}" }
          '';
        }
        {
@@ -300,7 +318,7 @@ in
            muc_component = "conference.${cfg.hostName}"
            breakout_rooms_component = "breakout.${cfg.hostName}"
        '')
        (mkBefore ''
        (mkBefore (''
          muc_mapper_domain_base = "${cfg.hostName}"

          cross_domain_websocket = true;
@@ -310,7 +328,10 @@ in
            "focus@auth.${cfg.hostName}",
            "jvb@auth.${cfg.hostName}"
          }
        '')
        '' + optionalString cfg.prosody.lockdown ''
          c2s_interfaces = { "127.0.0.1" };
          modules_disabled = { "s2s" };
        ''))
      ];
      virtualHosts.${cfg.hostName} = {
        enabled = true;
@@ -444,7 +465,29 @@ in
        Type = "simple";
        ExecStart = "${pkgs.jitsi-excalidraw}/bin/jitsi-excalidraw-backend";
        Restart = "on-failure";

        DynamicUser = true;
        Group = "jitsi-meet";
        CapabilityBoundingSet = "";
        NoNewPrivileges = true;
        ProtectSystem = "strict";
        ProtectClock = true;
        ProtectHome = true;
        ProtectProc = true;
        ProtectKernelLogs = true;
        PrivateTmp = true;
        PrivateDevices = true;
        PrivateUsers = true;
        ProtectHostname = true;
        ProtectKernelTunables = true;
        ProtectKernelModules = true;
        ProtectControlGroups = true;
        RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
        RestrictNamespaces = true;
        LockPersonality = true;
        RestrictRealtime = true;
        RestrictSUIDSGID = true;
        SystemCallFilter = [ "@system-service @pkey" "~@privileged" ];
      };
    };

@@ -513,7 +556,11 @@ in
            cp ${overrideJs "${pkgs.jitsi-meet}/interface_config.js" "interfaceConfig" cfg.interfaceConfig ""} $out/interface_config.js
            cp ./libs/external_api.min.js $out/external_api.js
          '';
        in ''
        in (optionalString cfg.excalidraw.enable ''
          handle /socket.io/ {
            reverse_proxy 127.0.0.1:${toString cfg.excalidraw.port}
          }
        '') + ''
          handle /http-bind {
            header Host ${cfg.hostName}
            reverse_proxy 127.0.0.1:5280
+2 −1
Original line number Diff line number Diff line
@@ -18,7 +18,8 @@ stdenv.mkDerivation rec {
    runHook postInstall
  '';

  passthru.tests = {
  # Test requires running Jitsi Videobridge and Jicofo which are Linux-only
  passthru.tests = lib.optionalAttrs stdenv.isLinux {
    single-host-smoke-test = nixosTests.jitsi-meet;
  };