git.iko.soy/typeable/nixpkgs
on master help sign in
nixos/heisenbridge: Init
commit4d69ad4b1f4133fea19471361a4626ee47bbabb9 authorpiegames <git@piegames.de> dateSun 24 Oct 2021, 18:41 (5 years ago) parentb077916
3 files changed+217
nixos/doc/manual/from_md/release-notes/rl-2205.section.xml+7 nixos/doc/manual/release-notes/rl-2205.section.md+2 nixos/modules/services/misc/heisenbridge.nix+208
nixos/doc/manual/from_md/release-notes/rl-2205.section.xml+7
@@ -67,6 +67,13 @@
6767 <link linkend="opt-services.filebeat.enable">services.filebeat</link>.
6868 </para>
6969 </listitem>
70+ <listitem>
71+ <para>
72+ <link xlink:href="https://github.com/hifi/heisenbridge">heisenbridge</link>,
73+ a bouncer-style Matrix IRC bridge. Available as
74+ <link xlink:href="options.html#opt-services.heisenbridge.enable">services.heisenbridge</link>.
75+ </para>
76+ </listitem>
7077 <listitem>
7178 <para>
7279 <link xlink:href="https://github.com/ngoduykhanh/PowerDNS-Admin">PowerDNS-Admin</link>,
nixos/doc/manual/release-notes/rl-2205.section.md+2
@@ -23,6 +23,8 @@ In addition to numerous new and upgraded packages, this release has the followin
2323
2424- [filebeat](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-overview.html), a lightweight shipper for forwarding and centralizing log data. Available as [services.filebeat](#opt-services.filebeat.enable).
2525
26+- [heisenbridge](https://github.com/hifi/heisenbridge), a bouncer-style Matrix IRC bridge. Available as [services.heisenbridge](options.html#opt-services.heisenbridge.enable).
27+
2628- [PowerDNS-Admin](https://github.com/ngoduykhanh/PowerDNS-Admin), a web interface for the PowerDNS server. Available at [services.powerdns-admin](options.html#opt-services.powerdns-admin.enable).
2729
2830- [maddy](https://maddy.email), a composable all-in-one mail server. Available as [services.maddy](options.html#opt-services.maddy.enable).
nixos/modules/services/misc/heisenbridge.nixnew file+208
@@ -0,0 +1,208 @@
1+{ config, pkgs, lib, ... }:
2+
3+with lib;
4+
5+let
6+ cfg = config.services.heisenbridge;
7+
8+ pkg = config.services.heisenbridge.package;
9+ bin = "${pkg}/bin/heisenbridge";
10+
11+ jsonType = (pkgs.formats.json { }).type;
12+
13+ registrationFile = "/var/lib/heisenbridge/registration.yml";
14+ # JSON is a proper subset of YAML
15+ bridgeConfig = builtins.toFile "heisenbridge-registration.yml" (builtins.toJSON {
16+ id = "heisenbridge";
17+ url = cfg.registrationUrl;
18+ # Don't specify as_token and hs_token
19+ rate_limited = false;
20+ sender_localpart = "heisenbridge";
21+ namespaces = cfg.namespaces;
22+ });
23+in
24+{
25+ options.services.heisenbridge = {
26+ enable = mkEnableOption "the Matrix<->IRC bridge";
27+
28+ package = mkOption {
29+ type = types.package;
30+ default = pkgs.heisenbridge;
31+ defaultText = "pkgs.heisenbridge";
32+ example = "pkgs.heisenbridge.override { … = …; }";
33+ description = ''
34+ Package of the application to run, exposed for overriding purposes.
35+ '';
36+ };
37+
38+ homeserver = mkOption {
39+ type = types.str;
40+ description = "The URL to the home server for client-server API calls";
41+ example = "http://localhost:8008";
42+ };
43+
44+ registrationUrl = mkOption {
45+ type = types.str;
46+ description = ''
47+ The URL where the application service is listening for HS requests, from the Matrix HS perspective.#
48+ The default value assumes the bridge runs on the same host as the home server, in the same network.
49+ '';
50+ example = "https://matrix.example.org";
51+ default = "http://${cfg.address}:${toString cfg.port}";
52+ defaultText = "http://$${cfg.address}:$${toString cfg.port}";
53+ };
54+
55+ address = mkOption {
56+ type = types.str;
57+ description = "Address to listen on. IPv6 does not seem to be supported.";
58+ default = "127.0.0.1";
59+ example = "0.0.0.0";
60+ };
61+
62+ port = mkOption {
63+ type = types.port;
64+ description = "The port to listen on";
65+ default = 9898;
66+ };
67+
68+ debug = mkOption {
69+ type = types.bool;
70+ description = "More verbose logging. Recommended during initial setup.";
71+ default = false;
72+ };
73+
74+ owner = mkOption {
75+ type = types.nullOr types.str;
76+ description = ''
77+ Set owner MXID otherwise first talking local user will claim the bridge
78+ '';
79+ default = null;
80+ example = "@admin:example.org";
81+ };
82+
83+ namespaces = mkOption {
84+ description = "Configure the 'namespaces' section of the registration.yml for the bridge and the server";
85+ # TODO link to Matrix documentation of the format
86+ type = types.submodule {
87+ freeformType = jsonType;
88+ };
89+
90+ default = {
91+ users = [
92+ {
93+ regex = "@irc_.*";
94+ exclusive = true;
95+ }
96+ ];
97+ aliases = [ ];
98+ rooms = [ ];
99+ };
100+ };
101+
102+ identd.enable = mkEnableOption "identd service support";
103+ identd.port = mkOption {
104+ type = types.port;
105+ description = "identd listen port";
106+ default = 113;
107+ };
108+
109+ extraArgs = mkOption {
110+ type = types.listOf types.str;
111+ description = "Heisenbridge is configured over the command line. Append extra arguments here";
112+ default = [ ];
113+ };
114+ };
115+
116+ config = mkIf cfg.enable {
117+ systemd.services.heisenbridge = {
118+ description = "Matrix<->IRC bridge";
119+ before = [ "matrix-synapse.service" ]; # So the registration file can be used by Synapse
120+ wantedBy = [ "multi-user.target" ];
121+
122+ preStart = ''
123+ umask 077
124+ set -e -u -o pipefail
125+
126+ if ! [ -f "${registrationFile}" ]; then
127+ # Generate registration file if not present (actually, we only care about the tokens in it)
128+ ${bin} --generate --config ${registrationFile}
129+ fi
130+
131+ # Overwrite the registration file with our generated one (the config may have changed since then),
132+ # but keep the tokens. Two step procedure to be failure safe
133+ ${pkgs.yq}/bin/yq --slurp \
134+ '.[0] + (.[1] | {as_token, hs_token})' \
135+ ${bridgeConfig} \
136+ ${registrationFile} \
137+ > ${registrationFile}.new
138+ mv -f ${registrationFile}.new ${registrationFile}
139+
140+ # Grant Synapse access to the registration
141+ if ${getBin pkgs.glibc}/bin/getent group matrix-synapse > /dev/null; then
142+ chgrp -v matrix-synapse ${registrationFile}
143+ chmod -v g+r ${registrationFile}
144+ fi
145+ '';
146+
147+ serviceConfig = rec {
148+ Type = "simple";
149+ ExecStart = lib.concatStringsSep " " (
150+ [
151+ bin
152+ (if cfg.debug then "-vvv" else "-v")
153+ "--config"
154+ registrationFile
155+ "--listen-address"
156+ (lib.escapeShellArg cfg.address)
157+ "--listen-port"
158+ (toString cfg.port)
159+ ]
160+ ++ (lib.optionals (cfg.owner != null) [
161+ "--owner"
162+ (lib.escapeShellArg cfg.owner)
163+ ])
164+ ++ (lib.optionals cfg.identd.enable [
165+ "--identd"
166+ "--identd-port"
167+ (toString cfg.identd.port)
168+ ])
169+ ++ [
170+ (lib.escapeShellArg cfg.homeserver)
171+ ]
172+ ++ (map (lib.escapeShellArg) cfg.extraArgs)
173+ );
174+
175+ ProtectHome = true;
176+ PrivateDevices = true;
177+ ProtectKernelTunables = true;
178+ ProtectKernelModules = true;
179+ ProtectControlGroups = true;
180+ StateDirectory = "heisenbridge";
181+ StateDirectoryMode = "755";
182+
183+ User = "heisenbridge";
184+ Group = "heisenbridge";
185+
186+ CapabilityBoundingSet = [ "CAP_CHOWN" ] ++ optional (cfg.port < 1024 || cfg.identd.port < 1024) "CAP_NET_BIND_SERVICE";
187+ AmbientCapabilities = CapabilityBoundingSet;
188+ NoNewPrivileges = true;
189+
190+ LockPersonality = true;
191+ RestrictRealtime = true;
192+ PrivateMounts = true;
193+ SystemCallFilter = "~@aio @clock @cpu-emulation @debug @keyring @memlock @module @mount @obsolete @raw-io @setuid @swap";
194+ SystemCallArchitectures = "native";
195+ RestrictAddressFamilies = "AF_INET AF_INET6";
196+ };
197+ };
198+
199+ users.groups.heisenbridge = {};
200+ users.users.heisenbridge = {
201+ description = "Service user for the Heisenbridge";
202+ group = "heisenbridge";
203+ isSystemUser = true;
204+ };
205+ };
206+
207+ meta.maintainers = [ lib.maintainers.piegames ];
208+}