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