nixos-modules/modules/matrix.nix

161 lines
5.4 KiB
Nix

{ config, lib, libS, pkgs, ... }:
let
cfg = config.services.matrix-synapse;
cfge = cfg.element-web;
inherit (config.security) ldap;
in
{
options = {
services.matrix-synapse = {
addAdditionalOembedProvider = libS.mkOpinionatedOption "add additional oembed providers from oembed.com";
element-web = {
enable = lib.mkEnableOption (lib.mdDoc "the element-web client");
domain = lib.mkOption {
type = lib.types.str;
example = "element.example.org";
description = lib.mdDoc "The domain that element-web will use.";
};
package = lib.mkPackageOptionMD pkgs "element-web" { };
enableConfigFeatures = libS.mkOpinionatedOption "enable most features available via config.json";
};
ldap = {
enable = lib.mkEnableOption (lib.mdDoc "login via ldap");
userGroup = libS.ldap.mkUserGroupOption;
searchUserPasswordFile = lib.mkOption {
type = lib.types.str;
example = "/var/lib/secrets/search-user-password";
description = lib.mdDoc "Path to a file containing the password for the search/bind user.";
};
};
recommendedDefaults = libS.mkOpinionatedOption "set recommended and secure default settings";
};
};
imports = [
(lib.mkRenamedOptionModule [ "services" "matrix-synapse" "ldap" "bindPasswordFile" ] [ "services" "matrix-synapse" "ldap" "searchUserPasswordFile" ])
];
config.environment.etc = lib.mkIf cfg.enable {
"matrix-synapse/config.yaml".source = cfg.configFile;
};
config.services.matrix-synapse = lib.mkMerge [
{
settings = lib.mkIf cfge.enable rec {
email.client_base_url = web_client_location;
web_client_location = "https://${cfge.domain}";
};
}
(lib.mkIf cfg.ldap.enable {
plugins = with config.services.matrix-synapse.package.plugins; [
matrix-synapse-ldap3
];
settings.modules = [{
module = "ldap_auth_provider.LdapAuthProviderModule";
config = {
enabled = true;
mode = "search";
uri = "ldaps://${ldap.domainName}:${toString ldap.port}";
base = ldap.userBaseDN;
attributes = {
uid = ldap.userField;
mail = ldap.mailField;
name = ldap.givenNameField;
};
bind_dn = ldap.bindDN;
bind_password_file = cfg.ldap.searchUserPasswordFile;
tls_options.validate = true;
} // lib.optionalAttrs (cfg.ldap.userGroup != null) {
filter = ldap.groupFilter cfg.ldap.userGroup;
};
}];
})
{
settings.oembed.additional_providers = lib.mkIf cfg.addAdditionalOembedProvider [
(
let
providers = pkgs.fetchurl {
url = "https://oembed.com/providers.json?2023-03-23";
sha256 = "sha256-OdgBgkLbtNMn84ixKuC1gGzpyr+X+ORiLl6TAK3lYuQ=";
};
in
pkgs.runCommand "providers.json"
{
nativeBuildInputs = with pkgs; [ jq ];
} ''
# filter out entries that do not contain a schemes entry
# Error in configuration at 'oembed.additional_providers.<item 0>.<item 22>.endpoints.<item 0>': 'schemes' is a required property
# and have none http protocols: Unsupported oEmbed scheme (spotify) for pattern: spotify:*
jq '[ ..|objects| select(.endpoints[0]|has("schemes")) | .endpoints[0].schemes=([ .endpoints[0].schemes[]|select(.|contains("http")) ]) ]' ${providers} > $out
''
)
];
}
(lib.mkIf cfg.recommendedDefaults {
settings = {
federation_client_minimum_tls_version = "1.2";
suppress_key_server_warning = true;
user_directory.prefer_local_users = true;
};
withJemalloc = true;
})
];
config.services.nginx = lib.mkIf cfge.enable {
enable = true;
virtualHosts."${cfge.domain}" = {
forceSSL = true;
enableACME = lib.mkDefault true;
locations."/".root = (cfge.package.override {
conf = with config.services.matrix-synapse.settings; {
default_server_config."m.homeserver" = {
"base_url" = public_baseurl;
"server_name" = server_name;
};
default_theme = "dark";
room_directory.servers = [ server_name ];
} // lib.optionalAttrs cfge.enableConfigFeatures {
features = {
# https://github.com/matrix-org/matrix-react-sdk/blob/develop/src/settings/Settings.tsx
# https://github.com/vector-im/element-web/blob/develop/docs/labs.md
feature_ask_to_join = true;
feature_bridge_state = true;
feature_exploring_public_spaces = true;
feature_jump_to_date = true;
feature_mjolnir = true;
feature_pinning = true;
feature_presence_in_room_list = true;
feature_report_to_moderators = true;
feature_qr_signin_reciprocate_show = true;
};
show_labs_settings = true;
};
}).overrideAttrs ({ postInstall ? "", ... }: {
# prevent 404 spam in nginx log
postInstall = postInstall + ''
ln -rs $out/config.json $out/config.${cfge.domain}.json
'';
});
};
};
config.services.portunus.seedSettings.groups = lib.optional (cfg.ldap.userGroup != null) {
long_name = "Matrix Users";
name = cfg.ldap.userGroup;
permissions = { };
};
}