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