vuls: init at 0.27.0
[NixPkgs.git] / nixos / modules / services / networking / biboumi.nix
blob33cb1d95bc51fd0e794dd6fe4c7c704343c765b0
1 { config, lib, pkgs, options, ... }:
2 let
3   cfg = config.services.biboumi;
4   inherit (config.environment) etc;
5   rootDir = "/run/biboumi/mnt-root";
6   stateDir = "/var/lib/biboumi";
7   settingsFile = pkgs.writeText "biboumi.cfg" (
8     lib.generators.toKeyValue {
9       mkKeyValue = k: v:
10         lib.optionalString (v != null) (lib.generators.mkKeyValueDefault {} "=" k v);
11     } cfg.settings);
12   need_CAP_NET_BIND_SERVICE = cfg.settings.identd_port != 0 && cfg.settings.identd_port < 1024;
15   options = {
16     services.biboumi = {
17       enable = lib.mkEnableOption "the Biboumi XMPP gateway to IRC";
19       settings = lib.mkOption {
20         description = ''
21           See [biboumi 8.5](https://lab.louiz.org/louiz/biboumi/blob/8.5/doc/biboumi.1.rst)
22           for documentation.
23         '';
24         default = {};
25         type = lib.types.submodule {
26           freeformType = with lib.types;
27             (attrsOf (nullOr (oneOf [str int bool]))) // {
28               description = "settings option";
29             };
30           options.admin = lib.mkOption {
31             type = with lib.types; listOf str;
32             default = [];
33             example = ["admin@example.org"];
34             apply = lib.concatStringsSep ":";
35             description = ''
36               The bare JID of the gateway administrator. This JID will have more
37               privileges than other standard users, for example some administration
38               ad-hoc commands will only be available to that JID.
39             '';
40           };
41           options.ca_file = lib.mkOption {
42             type = lib.types.path;
43             default = "/etc/ssl/certs/ca-certificates.crt";
44             description = ''
45               Specifies which file should be used as the list of trusted CA
46               when negotiating a TLS session.
47             '';
48           };
49           options.db_name = lib.mkOption {
50             type = with lib.types; either path str;
51             default = "${stateDir}/biboumi.sqlite";
52             description = ''
53               The name of the database to use.
54             '';
55             example = "postgresql://user:secret@localhost";
56           };
57           options.hostname = lib.mkOption {
58             type = lib.types.str;
59             example = "biboumi.example.org";
60             description = ''
61               The hostname served by the XMPP gateway.
62               This domain must be configured in the XMPP server
63               as an external component.
64             '';
65           };
66           options.identd_port = lib.mkOption {
67             type = lib.types.port;
68             default = 113;
69             example = 0;
70             description = ''
71               The TCP port on which to listen for identd queries.
72             '';
73           };
74           options.log_level = lib.mkOption {
75             type = lib.types.ints.between 0 3;
76             default = 1;
77             description = ''
78               Indicate what type of log messages to write in the logs.
79               0 is debug, 1 is info, 2 is warning, 3 is error.
80             '';
81           };
82           options.password = lib.mkOption {
83             type = with lib.types; nullOr str;
84             description = ''
85               The password used to authenticate the XMPP component to your XMPP server.
86               This password must be configured in the XMPP server,
87               associated with the external component on
88               [hostname](#opt-services.biboumi.settings.hostname).
90               Set it to null and use [credentialsFile](#opt-services.biboumi.credentialsFile)
91               if you do not want this password to go into the Nix store.
92             '';
93           };
94           options.persistent_by_default = lib.mkOption {
95             type = lib.types.bool;
96             default = false;
97             description = ''
98               Whether all rooms will be persistent by default:
99               the value of the “persistent” option in the global configuration of each
100               user will be “true”, but the value of each individual room will still
101               default to false. This means that a user just needs to change the global
102               “persistent” configuration option to false in order to override this.
103             '';
104           };
105           options.policy_directory = lib.mkOption {
106             type = lib.types.path;
107             default = "${pkgs.biboumi}/etc/biboumi";
108             defaultText = lib.literalExpression ''"''${pkgs.biboumi}/etc/biboumi"'';
109             description = ''
110               A directory that should contain the policy files,
111               used to customize Botan’s behaviour
112               when negotiating the TLS connections with the IRC servers.
113             '';
114           };
115           options.port = lib.mkOption {
116             type = lib.types.port;
117             default = 5347;
118             description = ''
119               The TCP port to use to connect to the local XMPP component.
120             '';
121           };
122           options.realname_customization = lib.mkOption {
123             type = lib.types.bool;
124             default = true;
125             description = ''
126               Whether the users will be able to use
127               the ad-hoc commands that lets them configure
128               their realname and username.
129             '';
130           };
131           options.realname_from_jid = lib.mkOption {
132             type = lib.types.bool;
133             default = false;
134             description = ''
135               Whether the realname and username of each biboumi
136               user will be extracted from their JID.
137               Otherwise they will be set to the nick
138               they used to connect to the IRC server.
139             '';
140           };
141           options.xmpp_server_ip = lib.mkOption {
142             type = lib.types.str;
143             default = "127.0.0.1";
144             description = ''
145               The IP address to connect to the XMPP server on.
146               The connection to the XMPP server is unencrypted,
147               so the biboumi instance and the server should
148               normally be on the same host.
149             '';
150           };
151         };
152       };
154       credentialsFile = lib.mkOption {
155         type = lib.types.path;
156         description = ''
157           Path to a configuration file to be merged with the settings.
158           Beware not to surround "=" with spaces when setting biboumi's options in this file.
159           Useful to merge a file which is better kept out of the Nix store
160           because it contains sensible data like
161           [password](#opt-services.biboumi.settings.password).
162         '';
163         default = "/dev/null";
164         example = "/run/keys/biboumi.cfg";
165       };
167       openFirewall = lib.mkEnableOption "opening of the identd port in the firewall";
168     };
169   };
171   config = lib.mkIf cfg.enable {
172     networking.firewall = lib.mkIf (cfg.openFirewall && cfg.settings.identd_port != 0)
173       { allowedTCPPorts = [ cfg.settings.identd_port ]; };
175     systemd.services.biboumi = {
176       description = "Biboumi, XMPP to IRC gateway";
177       after = [ "network.target" ];
178       wantedBy = [ "multi-user.target" ];
180       serviceConfig = {
181         Type = "notify";
182         # Biboumi supports systemd's watchdog.
183         WatchdogSec = 20;
184         Restart = "always";
185         # Use "+" because credentialsFile may not be accessible to User= or Group=.
186         ExecStartPre = [("+" + pkgs.writeShellScript "biboumi-prestart" ''
187           set -eux
188           cat ${settingsFile} '${cfg.credentialsFile}' |
189           install -m 644 /dev/stdin /run/biboumi/biboumi.cfg
190         '')];
191         ExecStart = "${pkgs.biboumi}/bin/biboumi /run/biboumi/biboumi.cfg";
192         ExecReload = "${pkgs.coreutils}/bin/kill -USR1 $MAINPID";
193         # Firewalls needing opening for output connections can still do that
194         # selectively for biboumi with:
195         # users.users.biboumi.isSystemUser = true;
196         # and, for example:
197         # networking.nftables.ruleset = ''
198         #   add rule inet filter output meta skuid biboumi tcp accept
199         # '';
200         DynamicUser = true;
201         RootDirectory = rootDir;
202         RootDirectoryStartOnly = true;
203         InaccessiblePaths = [ "-+${rootDir}" ];
204         RuntimeDirectory = [ "biboumi" (lib.removePrefix "/run/" rootDir) ];
205         RuntimeDirectoryMode = "700";
206         StateDirectory = "biboumi";
207         StateDirectoryMode = "700";
208         MountAPIVFS = true;
209         UMask = "0066";
210         BindPaths = [
211           stateDir
212           # This is for Type="notify"
213           # See https://github.com/systemd/systemd/issues/3544
214           "/run/systemd/notify"
215           "/run/systemd/journal/socket"
216         ];
217         BindReadOnlyPaths = [
218           builtins.storeDir
219           "/etc"
220         ];
221         # The following options are only for optimizing:
222         # systemd-analyze security biboumi
223         AmbientCapabilities = [ (lib.optionalString need_CAP_NET_BIND_SERVICE "CAP_NET_BIND_SERVICE") ];
224         CapabilityBoundingSet = [ (lib.optionalString need_CAP_NET_BIND_SERVICE "CAP_NET_BIND_SERVICE") ];
225         # ProtectClock= adds DeviceAllow=char-rtc r
226         DeviceAllow = "";
227         LockPersonality = true;
228         MemoryDenyWriteExecute = true;
229         NoNewPrivileges = true;
230         PrivateDevices = true;
231         PrivateMounts = true;
232         PrivateNetwork = lib.mkDefault false;
233         PrivateTmp = true;
234         # PrivateUsers=true breaks AmbientCapabilities=CAP_NET_BIND_SERVICE
235         # See https://bugs.archlinux.org/task/65921
236         PrivateUsers = !need_CAP_NET_BIND_SERVICE;
237         ProtectClock = true;
238         ProtectControlGroups = true;
239         ProtectHome = true;
240         ProtectHostname = true;
241         ProtectKernelLogs = true;
242         ProtectKernelModules = true;
243         ProtectKernelTunables = true;
244         ProtectSystem = "strict";
245         RemoveIPC = true;
246         # AF_UNIX is for /run/systemd/notify
247         RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
248         RestrictNamespaces = true;
249         RestrictRealtime = true;
250         RestrictSUIDSGID = true;
251         SystemCallFilter = [
252           "@system-service"
253           # Groups in @system-service which do not contain a syscall
254           # listed by perf stat -e 'syscalls:sys_enter_*' biboumi biboumi.cfg
255           # in tests, and seem likely not necessary for biboumi.
256           # To run such a perf in ExecStart=, you have to:
257           # - AmbientCapabilities="CAP_SYS_ADMIN"
258           # - mount -o remount,mode=755 /sys/kernel/debug/{,tracing}
259           "~@aio" "~@chown" "~@ipc" "~@keyring" "~@resources" "~@setuid" "~@timer"
260         ];
261         SystemCallArchitectures = "native";
262         SystemCallErrorNumber = "EPERM";
263       };
264     };
265   };
267   meta.maintainers = with lib.maintainers; [ julm ];