at 24.11-pre 11 kB view raw
1{ config, lib, pkgs, options, ... }: 2with lib; 3let 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 { 10 mkKeyValue = k: v: 11 lib.optionalString (v != null) (generators.mkKeyValueDefault {} "=" k v); 12 } cfg.settings); 13 need_CAP_NET_BIND_SERVICE = cfg.settings.identd_port != 0 && cfg.settings.identd_port < 1024; 14in 15{ 16 options = { 17 services.biboumi = { 18 enable = mkEnableOption "the Biboumi XMPP gateway to IRC"; 19 20 settings = mkOption { 21 description = '' 22 See [biboumi 8.5](https://lab.louiz.org/louiz/biboumi/blob/8.5/doc/biboumi.1.rst) 23 for documentation. 24 ''; 25 default = {}; 26 type = types.submodule { 27 freeformType = with types; 28 (attrsOf (nullOr (oneOf [str int bool]))) // { 29 description = "settings option"; 30 }; 31 options.admin = mkOption { 32 type = with types; listOf str; 33 default = []; 34 example = ["admin@example.org"]; 35 apply = concatStringsSep ":"; 36 description = '' 37 The bare JID of the gateway administrator. This JID will have more 38 privileges than other standard users, for example some administration 39 ad-hoc commands will only be available to that JID. 40 ''; 41 }; 42 options.ca_file = mkOption { 43 type = types.path; 44 default = "/etc/ssl/certs/ca-certificates.crt"; 45 description = '' 46 Specifies which file should be used as the list of trusted CA 47 when negotiating a TLS session. 48 ''; 49 }; 50 options.db_name = mkOption { 51 type = with types; either path str; 52 default = "${stateDir}/biboumi.sqlite"; 53 description = '' 54 The name of the database to use. 55 ''; 56 example = "postgresql://user:secret@localhost"; 57 }; 58 options.hostname = mkOption { 59 type = types.str; 60 example = "biboumi.example.org"; 61 description = '' 62 The hostname served by the XMPPgateway. 63 This domain must be configured in the XMPP server 64 as an external component. 65 ''; 66 }; 67 options.identd_port = mkOption { 68 type = types.port; 69 default = 113; 70 example = 0; 71 description = '' 72 The TCP port on which to listen for identd queries. 73 ''; 74 }; 75 options.log_level = mkOption { 76 type = types.ints.between 0 3; 77 default = 1; 78 description = '' 79 Indicate what type of log messages to write in the logs. 80 0 is debug, 1 is info, 2 is warning, 3 is error. 81 ''; 82 }; 83 options.password = mkOption { 84 type = with types; nullOr str; 85 description = '' 86 The password used to authenticate the XMPP component to your XMPP server. 87 This password must be configured in the XMPP server, 88 associated with the external component on 89 [hostname](#opt-services.biboumi.settings.hostname). 90 91 Set it to null and use [credentialsFile](#opt-services.biboumi.credentialsFile) 92 if you do not want this password to go into the Nix store. 93 ''; 94 }; 95 options.persistent_by_default = mkOption { 96 type = types.bool; 97 default = false; 98 description = '' 99 Whether all rooms will be persistent by default: 100 the value of the persistent option in the global configuration of each 101 user will be true, but the value of each individual room will still 102 default to false. This means that a user just needs to change the global 103 persistent configuration option to false in order to override this. 104 ''; 105 }; 106 options.policy_directory = mkOption { 107 type = types.path; 108 default = "${pkgs.biboumi}/etc/biboumi"; 109 defaultText = literalExpression ''"''${pkgs.biboumi}/etc/biboumi"''; 110 description = '' 111 A directory that should contain the policy files, 112 used to customize Botans behaviour 113 when negotiating the TLS connections with the IRC servers. 114 ''; 115 }; 116 options.port = mkOption { 117 type = types.port; 118 default = 5347; 119 description = '' 120 The TCP port to use to connect to the local XMPP component. 121 ''; 122 }; 123 options.realname_customization = mkOption { 124 type = types.bool; 125 default = true; 126 description = '' 127 Whether the users will be able to use 128 the ad-hoc commands that lets them configure 129 their realname and username. 130 ''; 131 }; 132 options.realname_from_jid = mkOption { 133 type = types.bool; 134 default = false; 135 description = '' 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. 140 ''; 141 }; 142 options.xmpp_server_ip = mkOption { 143 type = types.str; 144 default = "127.0.0.1"; 145 description = '' 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. 150 ''; 151 }; 152 }; 153 }; 154 155 credentialsFile = mkOption { 156 type = types.path; 157 description = '' 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 [password](#opt-services.biboumi.settings.password). 163 ''; 164 default = "/dev/null"; 165 example = "/run/keys/biboumi.cfg"; 166 }; 167 168 openFirewall = mkEnableOption "opening of the identd port in the firewall"; 169 }; 170 }; 171 172 config = mkIf cfg.enable { 173 networking.firewall = mkIf (cfg.openFirewall && cfg.settings.identd_port != 0) 174 { allowedTCPPorts = [ cfg.settings.identd_port ]; }; 175 176 systemd.services.biboumi = { 177 description = "Biboumi, XMPP to IRC gateway"; 178 after = [ "network.target" ]; 179 wantedBy = [ "multi-user.target" ]; 180 181 serviceConfig = { 182 Type = "notify"; 183 # Biboumi supports systemd's watchdog. 184 WatchdogSec = 20; 185 Restart = "always"; 186 # Use "+" because credentialsFile may not be accessible to User= or Group=. 187 ExecStartPre = [("+" + pkgs.writeShellScript "biboumi-prestart" '' 188 set -eux 189 cat ${settingsFile} '${cfg.credentialsFile}' | 190 install -m 644 /dev/stdin /run/biboumi/biboumi.cfg 191 '')]; 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 200 # ''; 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; 210 UMask = "0066"; 211 BindPaths = [ 212 stateDir 213 # This is for Type="notify" 214 # See https://github.com/systemd/systemd/issues/3544 215 "/run/systemd/notify" 216 "/run/systemd/journal/socket" 217 ]; 218 BindReadOnlyPaths = [ 219 builtins.storeDir 220 "/etc" 221 ]; 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 227 DeviceAllow = ""; 228 LockPersonality = true; 229 MemoryDenyWriteExecute = true; 230 NoNewPrivileges = true; 231 PrivateDevices = true; 232 PrivateMounts = true; 233 PrivateNetwork = mkDefault false; 234 PrivateTmp = true; 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"; 246 RemoveIPC = true; 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 = [ 253 "@system-service" 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" 261 ]; 262 SystemCallArchitectures = "native"; 263 SystemCallErrorNumber = "EPERM"; 264 }; 265 }; 266 }; 267 268 meta.maintainers = with maintainers; [ julm ]; 269}