Merge pull request #221318 from mweinelt/synapse-extras

nixos/matrix-synapse: Allow passing extras, discover extras from config

authored by Maximilian Bosch and committed by GitHub a471325e 14ae6da1

+219 -45
+7
nixos/doc/manual/release-notes/rl-2311.section.md
··· 68 69 - The `services.ananicy.extraRules` option now has the type of `listOf attrs` instead of `string`. 70 71 - `etcd` has been updated to 3.5, you will want to read the [3.3 to 3.4](https://etcd.io/docs/v3.5/upgrades/upgrade_3_4/) and [3.4 to 3.5](https://etcd.io/docs/v3.5/upgrades/upgrade_3_5/) upgrade guides 72 73 - `consul` has been updated to `1.16.0`. See the [release note](https://github.com/hashicorp/consul/releases/tag/v1.16.0) for more details. Once a new Consul version has started and upgraded its data directory, it generally cannot be downgraded to the previous version.
··· 68 69 - The `services.ananicy.extraRules` option now has the type of `listOf attrs` instead of `string`. 70 71 + - The `matrix-synapse` package & module have undergone some significant internal changes, for most setups no intervention is needed, though: 72 + - The option [`services.matrix-synapse.package`](#opt-services.matrix-synapse.package) is now read-only. For modifying the package, use an overlay which modifies `matrix-synapse-unwrapped` instead. More on that below. 73 + - The `enableSystemd` & `enableRedis` arguments have been removed and `matrix-synapse` has been renamed to `matrix-synapse-unwrapped`. Also, several optional dependencies (such as `psycopg2` or `authlib`) have been removed. 74 + - These optional dependencies are automatically added via a wrapper (`pkgs.matrix-synapse.override { extras = ["redis"]; }` for `hiredis` & `txredisapi` for instance) if the relevant config section is declared in `services.matrix-synapse.settings`. For instance, if `services.matrix-synapse.settings.redis.enabled` is set to `true`, `"redis"` will be automatically added to the `extras` list of `pkgs.matrix-synapse`. 75 + - A list of all extras (and the extras enabled by default) can be found at the [option's reference for `services.matrix-synapse.extras`](#opt-services.matrix-synapse.extras). 76 + - In some cases (e.g. for running synapse workers) it was necessary to re-use the `PYTHONPATH` of `matrix-synapse.service`'s environment to have all plugins available. This isn't necessary anymore, instead `config.services.matrix-synapse.package` can be used as it points to the wrapper with properly configured `extras` and also all plugins defined via [`services.matrix-synapse.plugins`](#opt-services.matrix-synapse.plugins) available. This is also the reason for why the option is read-only now, it's supposed to be set by the module only. 77 + 78 - `etcd` has been updated to 3.5, you will want to read the [3.3 to 3.4](https://etcd.io/docs/v3.5/upgrades/upgrade_3_4/) and [3.4 to 3.5](https://etcd.io/docs/v3.5/upgrades/upgrade_3_5/) upgrade guides 79 80 - `consul` has been updated to `1.16.0`. See the [release note](https://github.com/hashicorp/consul/releases/tag/v1.16.0) for more details. Once a new Consul version has started and upgraded its data directory, it generally cannot be downgraded to the previous version.
+75 -12
nixos/modules/services/matrix/synapse.nix
··· 9 # remove null values from the final configuration 10 finalSettings = lib.filterAttrsRecursive (_: v: v != null) cfg.settings; 11 configFile = format.generate "homeserver.yaml" finalSettings; 12 - logConfigFile = format.generate "log_config.yaml" cfg.logConfig; 13 - 14 - pluginsEnv = cfg.package.python.buildEnv.override { 15 - extraLibs = cfg.plugins; 16 - }; 17 18 usePostgresql = cfg.settings.database.name == "psycopg2"; 19 hasLocalPostgresDB = let args = cfg.settings.database.args; in ··· 50 "${bindAddress}" 51 }:${builtins.toString listener.port}/" 52 ''; 53 in { 54 55 imports = [ ··· 151 152 package = mkOption { 153 type = types.package; 154 - default = pkgs.matrix-synapse; 155 - defaultText = literalExpression "pkgs.matrix-synapse"; 156 description = lib.mdDoc '' 157 - Overridable attribute of the matrix synapse server package to use. 158 ''; 159 }; 160 ··· 193 default = {}; 194 description = mdDoc '' 195 The primary synapse configuration. See the 196 - [sample configuration](https://github.com/matrix-org/synapse/blob/v${cfg.package.version}/docs/sample_config.yaml) 197 for possible values. 198 199 Secrets should be passed in by using the `extraConfigFiles` option. ··· 706 ]; 707 708 services.matrix-synapse.configFile = configFile; 709 710 users.users.matrix-synapse = { 711 group = "matrix-synapse"; ··· 729 --keys-directory ${cfg.dataDir} \ 730 --generate-keys 731 ''; 732 - environment = { 733 - PYTHONPATH = makeSearchPathOutput "lib" cfg.package.python.sitePackages [ pluginsEnv ]; 734 - } // optionalAttrs (cfg.withJemalloc) { 735 LD_PRELOAD = "${pkgs.jemalloc}/lib/libjemalloc.so"; 736 }; 737 serviceConfig = {
··· 9 # remove null values from the final configuration 10 finalSettings = lib.filterAttrsRecursive (_: v: v != null) cfg.settings; 11 configFile = format.generate "homeserver.yaml" finalSettings; 12 13 usePostgresql = cfg.settings.database.name == "psycopg2"; 14 hasLocalPostgresDB = let args = cfg.settings.database.args; in ··· 45 "${bindAddress}" 46 }:${builtins.toString listener.port}/" 47 ''; 48 + 49 + defaultExtras = [ 50 + "systemd" 51 + "postgres" 52 + "url-preview" 53 + "user-search" 54 + ]; 55 + 56 + wantedExtras = cfg.extras 57 + ++ lib.optional (cfg.settings ? oidc_providers) "oidc" 58 + ++ lib.optional (cfg.settings ? jwt_config) "jwt" 59 + ++ lib.optional (cfg.settings ? saml2_config) "saml2" 60 + ++ lib.optional (cfg.settings ? opentracing) "opentracing" 61 + ++ lib.optional (cfg.settings ? redis) "redis" 62 + ++ lib.optional (cfg.settings ? sentry) "sentry" 63 + ++ lib.optional (cfg.settings ? user_directory) "user-search" 64 + ++ lib.optional (cfg.settings.url_preview_enabled) "url-preview" 65 + ++ lib.optional (cfg.settings.database.name == "psycopg2") "postgres"; 66 + 67 + wrapped = pkgs.matrix-synapse.override { 68 + extras = wantedExtras; 69 + inherit (cfg) plugins; 70 + }; 71 in { 72 73 imports = [ ··· 169 170 package = mkOption { 171 type = types.package; 172 + readOnly = true; 173 + description = lib.mdDoc '' 174 + Reference to the `matrix-synapse` wrapper with all extras 175 + (e.g. for `oidc` or `saml2`) added to the `PYTHONPATH` of all executables. 176 + 177 + This option is useful to reference the "final" `matrix-synapse` package that's 178 + actually used by `matrix-synapse.service`. For instance, when using 179 + workers, it's possible to run 180 + `''${config.services.matrix-synapse.package}/bin/synapse_worker` and 181 + no additional PYTHONPATH needs to be specified for extras or plugins configured 182 + via `services.matrix-synapse`. 183 + 184 + However, this means that this option is supposed to be only declared 185 + by the `services.matrix-synapse` module itself and is thus read-only. 186 + In order to modify `matrix-synapse` itself, use an overlay to override 187 + `pkgs.matrix-synapse-unwrapped`. 188 + ''; 189 + }; 190 + 191 + extras = mkOption { 192 + type = types.listOf (types.enum (lib.attrNames pkgs.matrix-synapse-unwrapped.optional-dependencies)); 193 + default = defaultExtras; 194 + example = literalExpression '' 195 + [ 196 + "cache-memory" # Provide statistics about caching memory consumption 197 + "jwt" # JSON Web Token authentication 198 + "opentracing" # End-to-end tracing support using Jaeger 199 + "oidc" # OpenID Connect authentication 200 + "postgres" # PostgreSQL database backend 201 + "redis" # Redis support for the replication stream between worker processes 202 + "saml2" # SAML2 authentication 203 + "sentry" # Error tracking and performance metrics 204 + "systemd" # Provide the JournalHandler used in the default log_config 205 + "url-preview" # Support for oEmbed URL previews 206 + "user-search" # Support internationalized domain names in user-search 207 + ] 208 + ''; 209 description = lib.mdDoc '' 210 + Explicitly install extras provided by matrix-synapse. Most 211 + will require some additional configuration. 212 + 213 + Extras will automatically be enabled, when the relevant 214 + configuration sections are present. 215 + 216 + Please note that this option is additive: i.e. when adding a new item 217 + to this list, the defaults are still kept. To override the defaults as well, 218 + use `lib.mkForce`. 219 ''; 220 }; 221 ··· 254 default = {}; 255 description = mdDoc '' 256 The primary synapse configuration. See the 257 + [sample configuration](https://github.com/matrix-org/synapse/blob/v${pkgs.matrix-synapse-unwrapped.version}/docs/sample_config.yaml) 258 for possible values. 259 260 Secrets should be passed in by using the `extraConfigFiles` option. ··· 767 ]; 768 769 services.matrix-synapse.configFile = configFile; 770 + services.matrix-synapse.package = wrapped; 771 + 772 + # default them, so they are additive 773 + services.matrix-synapse.extras = defaultExtras; 774 775 users.users.matrix-synapse = { 776 group = "matrix-synapse"; ··· 794 --keys-directory ${cfg.dataDir} \ 795 --generate-keys 796 ''; 797 + environment = optionalAttrs (cfg.withJemalloc) { 798 LD_PRELOAD = "${pkgs.jemalloc}/lib/libjemalloc.so"; 799 }; 800 serviceConfig = {
+14 -1
nixos/tests/matrix/synapse.nix
··· 65 66 nodes = { 67 # Since 0.33.0, matrix-synapse doesn't allow underscores in server names 68 - serverpostgres = { pkgs, nodes, ... }: let 69 mailserverIP = nodes.mailserver.config.networking.primaryIPAddress; 70 in 71 { ··· 76 database = { 77 name = "psycopg2"; 78 args.password = "synapse"; 79 }; 80 tls_certificate_path = "${cert}"; 81 tls_private_key_path = "${key}"; ··· 105 LC_COLLATE = "C" 106 LC_CTYPE = "C"; 107 ''; 108 }; 109 110 networking.extraHosts = '' ··· 207 serverpostgres.wait_for_unit("matrix-synapse.service") 208 serverpostgres.wait_until_succeeds( 209 "curl --fail -L --cacert ${ca_pem} https://localhost:8448/" 210 ) 211 serverpostgres.require_unit_state("postgresql.service") 212 serverpostgres.succeed("register_new_matrix_user -u ${testUser} -p ${testPassword} -a -k ${registrationSharedSecret} https://localhost:8448/")
··· 65 66 nodes = { 67 # Since 0.33.0, matrix-synapse doesn't allow underscores in server names 68 + serverpostgres = { pkgs, nodes, config, ... }: let 69 mailserverIP = nodes.mailserver.config.networking.primaryIPAddress; 70 in 71 { ··· 76 database = { 77 name = "psycopg2"; 78 args.password = "synapse"; 79 + }; 80 + redis = { 81 + enabled = true; 82 + host = "localhost"; 83 + port = config.services.redis.servers.matrix-synapse.port; 84 }; 85 tls_certificate_path = "${cert}"; 86 tls_private_key_path = "${key}"; ··· 110 LC_COLLATE = "C" 111 LC_CTYPE = "C"; 112 ''; 113 + }; 114 + 115 + services.redis.servers.matrix-synapse = { 116 + enable = true; 117 + port = 6380; 118 }; 119 120 networking.extraHosts = '' ··· 217 serverpostgres.wait_for_unit("matrix-synapse.service") 218 serverpostgres.wait_until_succeeds( 219 "curl --fail -L --cacert ${ca_pem} https://localhost:8448/" 220 + ) 221 + serverpostgres.wait_until_succeeds( 222 + "journalctl -u matrix-synapse.service | grep -q 'Connected to redis'" 223 ) 224 serverpostgres.require_unit_state("postgresql.service") 225 serverpostgres.succeed("register_new_matrix_user -u ${testUser} -p ${testPassword} -a -k ${registrationSharedSecret} https://localhost:8448/")
+69 -21
pkgs/servers/matrix-synapse/default.nix
··· 1 - { lib, stdenv, fetchFromGitHub, python3, openssl, cargo, rustPlatform, rustc 2 - , enableSystemd ? lib.meta.availableOn stdenv.hostPlatform python3.pkgs.systemd 3 , nixosTests 4 - , enableRedis ? true 5 , callPackage 6 }: 7 ··· 9 plugins = python3.pkgs.callPackage ./plugins { }; 10 tools = callPackage ./tools { }; 11 in 12 - with python3.pkgs; 13 - buildPythonApplication rec { 14 pname = "matrix-synapse"; 15 version = "1.89.0"; 16 format = "pyproject"; ··· 34 sed -i '/^setuptools_rust =/d' pyproject.toml 35 ''; 36 37 - nativeBuildInputs = [ 38 poetry-core 39 rustPlatform.cargoSetupHook 40 setuptools-rust ··· 42 rustc 43 ]; 44 45 - buildInputs = [ openssl ]; 46 47 - propagatedBuildInputs = [ 48 - authlib 49 bcrypt 50 bleach 51 canonicaljson 52 - daemonize 53 ijson 54 immutabledict 55 jinja2 56 jsonschema 57 - lxml 58 matrix-common 59 msgpack 60 netaddr 61 phonenumbers 62 pillow 63 prometheus-client 64 - psutil 65 - psycopg2 66 pyasn1 67 pydantic 68 - pyicu 69 pymacaroons 70 - pynacl 71 pyopenssl 72 - pysaml2 73 pyyaml 74 - requests 75 - setuptools 76 signedjson 77 sortedcontainers 78 treq 79 twisted 80 typing-extensions 81 unpaddedbase64 82 - ] ++ lib.optional enableSystemd systemd 83 - ++ lib.optionals enableRedis [ hiredis txredisapi ]; 84 85 - nativeCheckInputs = [ mock parameterized openssl ]; 86 87 doCheck = !stdenv.isDarwin; 88 ··· 112 113 meta = with lib; { 114 homepage = "https://matrix.org"; 115 description = "Matrix reference homeserver"; 116 license = licenses.asl20; 117 maintainers = teams.matrix.members;
··· 1 + { lib 2 + , stdenv 3 + , fetchFromGitHub 4 + , python3 5 + , openssl 6 + , cargo 7 + , rustPlatform 8 + , rustc 9 , nixosTests 10 , callPackage 11 }: 12 ··· 14 plugins = python3.pkgs.callPackage ./plugins { }; 15 tools = callPackage ./tools { }; 16 in 17 + python3.pkgs.buildPythonApplication rec { 18 pname = "matrix-synapse"; 19 version = "1.89.0"; 20 format = "pyproject"; ··· 38 sed -i '/^setuptools_rust =/d' pyproject.toml 39 ''; 40 41 + nativeBuildInputs = with python3.pkgs; [ 42 poetry-core 43 rustPlatform.cargoSetupHook 44 setuptools-rust ··· 46 rustc 47 ]; 48 49 + buildInputs = [ 50 + openssl 51 + ]; 52 53 + propagatedBuildInputs = with python3.pkgs; [ 54 + attrs 55 bcrypt 56 bleach 57 canonicaljson 58 + cryptography 59 ijson 60 immutabledict 61 jinja2 62 jsonschema 63 matrix-common 64 msgpack 65 netaddr 66 + packaging 67 phonenumbers 68 pillow 69 prometheus-client 70 pyasn1 71 + pyasn1-modules 72 pydantic 73 pymacaroons 74 pyopenssl 75 pyyaml 76 + service-identity 77 signedjson 78 sortedcontainers 79 treq 80 twisted 81 typing-extensions 82 unpaddedbase64 83 + ] 84 + ++ twisted.optional-dependencies.tls; 85 86 + passthru.optional-dependencies = with python3.pkgs; { 87 + postgres = if isPyPy then [ 88 + psycopg2cffi 89 + ] else [ 90 + psycopg2 91 + ]; 92 + saml2 = [ 93 + pysaml2 94 + ]; 95 + oidc = [ 96 + authlib 97 + ]; 98 + systemd = [ 99 + systemd 100 + ]; 101 + url-preview = [ 102 + lxml 103 + ]; 104 + sentry = [ 105 + sentry-sdk 106 + ]; 107 + opentracing = [ 108 + jaeger-client 109 + opentracing 110 + ]; 111 + jwt = [ 112 + authlib 113 + ]; 114 + redis = [ 115 + hiredis 116 + txredisapi 117 + ]; 118 + cache-memory = [ 119 + pympler 120 + ]; 121 + user-search = [ 122 + pyicu 123 + ]; 124 + }; 125 + 126 + nativeCheckInputs = [ 127 + openssl 128 + ] ++ (with python3.pkgs; [ 129 + mock 130 + parameterized 131 + ]) 132 + ++ lib.flatten (lib.attrValues passthru.optional-dependencies); 133 134 doCheck = !stdenv.isDarwin; 135 ··· 159 160 meta = with lib; { 161 homepage = "https://matrix.org"; 162 + changelog = "https://github.com/matrix-org/synapse/releases/tag/v${version}"; 163 description = "Matrix reference homeserver"; 164 license = licenses.asl20; 165 maintainers = teams.matrix.members;
+2 -2
pkgs/servers/matrix-synapse/plugins/ldap3.nix
··· 4 , fetchPypi 5 , ldap3 6 , ldaptor 7 - , matrix-synapse 8 , pytestCheckHook 9 , service-identity 10 , setuptools ··· 33 34 propagatedBuildInputs = [ service-identity ldap3 twisted ]; 35 36 - nativeCheckInputs = [ ldaptor matrix-synapse pytestCheckHook ]; 37 38 pythonImportsCheck = [ "ldap_auth_provider" ]; 39
··· 4 , fetchPypi 5 , ldap3 6 , ldaptor 7 + , matrix-synapse-unwrapped 8 , pytestCheckHook 9 , service-identity 10 , setuptools ··· 33 34 propagatedBuildInputs = [ service-identity ldap3 twisted ]; 35 36 + nativeCheckInputs = [ ldaptor matrix-synapse-unwrapped pytestCheckHook ]; 37 38 pythonImportsCheck = [ "ldap_auth_provider" ]; 39
+2 -2
pkgs/servers/matrix-synapse/plugins/mjolnir-antispam.nix
··· 1 - { lib, stdenv, buildPythonPackage, fetchFromGitHub, matrix-synapse }: 2 3 buildPythonPackage rec { 4 pname = "matrix-synapse-mjolnir-antispam"; ··· 13 14 sourceRoot = "./${src.name}/synapse_antispam"; 15 16 - buildInputs = [ matrix-synapse ]; 17 18 doCheck = false; # no tests 19 pythonImportsCheck = [ "mjolnir" ];
··· 1 + { lib, stdenv, buildPythonPackage, fetchFromGitHub, matrix-synapse-unwrapped }: 2 3 buildPythonPackage rec { 4 pname = "matrix-synapse-mjolnir-antispam"; ··· 13 14 sourceRoot = "./${src.name}/synapse_antispam"; 15 16 + buildInputs = [ matrix-synapse-unwrapped ]; 17 18 doCheck = false; # no tests 19 pythonImportsCheck = [ "mjolnir" ];
+2 -2
pkgs/servers/matrix-synapse/plugins/shared-secret-auth.nix
··· 1 - { lib, buildPythonPackage, fetchFromGitHub, matrix-synapse, twisted }: 2 3 buildPythonPackage rec { 4 pname = "matrix-synapse-shared-secret-auth"; ··· 14 doCheck = false; 15 pythonImportsCheck = [ "shared_secret_authenticator" ]; 16 17 - buildInputs = [ matrix-synapse ]; 18 propagatedBuildInputs = [ twisted ]; 19 20 meta = with lib; {
··· 1 + { lib, buildPythonPackage, fetchFromGitHub, matrix-synapse-unwrapped, twisted }: 2 3 buildPythonPackage rec { 4 pname = "matrix-synapse-shared-secret-auth"; ··· 14 doCheck = false; 15 pythonImportsCheck = [ "shared_secret_authenticator" ]; 16 17 + buildInputs = [ matrix-synapse-unwrapped ]; 18 propagatedBuildInputs = [ twisted ]; 19 20 meta = with lib; {
+44
pkgs/servers/matrix-synapse/wrapper.nix
···
··· 1 + { lib 2 + , stdenv 3 + , makeWrapper 4 + , matrix-synapse-unwrapped 5 + , extras ? [ 6 + "postgres" 7 + "url-preview" 8 + "user-search" 9 + ] ++ lib.optional (lib.meta.availableOn stdenv.hostPlatform matrix-synapse-unwrapped.python.pkgs.systemd) "systemd" 10 + , plugins ? [ ] 11 + , ... 12 + }: 13 + 14 + let 15 + extraPackages = lib.concatMap (extra: matrix-synapse-unwrapped.optional-dependencies.${extra}) (lib.unique extras); 16 + 17 + pluginsEnv = matrix-synapse-unwrapped.python.buildEnv.override { 18 + extraLibs = plugins; 19 + }; 20 + 21 + searchPath = lib.makeSearchPathOutput "lib" matrix-synapse-unwrapped.python.sitePackages (extraPackages ++ [ pluginsEnv ]); 22 + in 23 + stdenv.mkDerivation { 24 + name = (lib.appendToName "wrapped" matrix-synapse-unwrapped).name; 25 + 26 + nativeBuildInputs = [ 27 + makeWrapper 28 + ]; 29 + 30 + buildCommand = '' 31 + for bin in ${matrix-synapse-unwrapped}/bin/*; do 32 + echo $bin 33 + makeWrapper "$bin" "$out/bin/$(basename $bin)" \ 34 + --set PYTHONPATH ${searchPath} 35 + done; 36 + ''; 37 + 38 + passthru = { 39 + unwrapped = matrix-synapse-unwrapped; 40 + 41 + # for backward compatibility 42 + inherit (matrix-synapse-unwrapped) plugins tools; 43 + }; 44 + }
+4 -5
pkgs/top-level/all-packages.nix
··· 9839 9840 matrix-sliding-sync = callPackage ../servers/matrix-synapse/sliding-sync { }; 9841 9842 - matrix-synapse = callPackage ../servers/matrix-synapse { }; 9843 - 9844 - matrix-synapse-plugins = recurseIntoAttrs matrix-synapse.plugins; 9845 - 9846 - matrix-synapse-tools = recurseIntoAttrs matrix-synapse.tools; 9847 9848 matrix-appservice-irc = callPackage ../servers/matrix-synapse/matrix-appservice-irc { }; 9849
··· 9839 9840 matrix-sliding-sync = callPackage ../servers/matrix-synapse/sliding-sync { }; 9841 9842 + matrix-synapse = callPackage ../servers/matrix-synapse/wrapper.nix { }; 9843 + matrix-synapse-unwrapped = callPackage ../servers/matrix-synapse/default.nix { }; 9844 + matrix-synapse-plugins = recurseIntoAttrs matrix-synapse-unwrapped.plugins; 9845 + matrix-synapse-tools = recurseIntoAttrs matrix-synapse-unwrapped.tools; 9846 9847 matrix-appservice-irc = callPackage ../servers/matrix-synapse/matrix-appservice-irc { }; 9848