at 25.11-pre 16 kB view raw
1{ 2 config, 3 lib, 4 utils, 5 pkgs, 6 ... 7}: 8let 9 cfg = config.services.pgbouncer; 10 11 settingsFormat = pkgs.formats.ini { }; 12 configFile = settingsFormat.generate "pgbouncer.ini" ( 13 lib.filterAttrsRecursive (_: v: v != null) cfg.settings 14 ); 15 configPath = "pgbouncer/pgbouncer.ini"; 16in 17{ 18 imports = [ 19 (lib.mkRemovedOptionModule [ "services" "pgbouncer" "logFile" ] '' 20 `services.pgbouncer.logFile` has been removed, use `services.pgbouncer.settings.pgbouncer.logfile` 21 instead. 22 Please note that the new option expects an absolute path 23 whereas the old option accepted paths relative to pgbouncer's home dir. 24 '') 25 (lib.mkRenamedOptionModule 26 [ "services" "pgbouncer" "listenAddress" ] 27 [ "services" "pgbouncer" "settings" "pgbouncer" "listen_addr" ] 28 ) 29 (lib.mkRenamedOptionModule 30 [ "services" "pgbouncer" "listenPort" ] 31 [ "services" "pgbouncer" "settings" "pgbouncer" "listen_port" ] 32 ) 33 (lib.mkRenamedOptionModule 34 [ "services" "pgbouncer" "poolMode" ] 35 [ "services" "pgbouncer" "settings" "pgbouncer" "pool_mode" ] 36 ) 37 (lib.mkRenamedOptionModule 38 [ "services" "pgbouncer" "maxClientConn" ] 39 [ "services" "pgbouncer" "settings" "pgbouncer" "max_client_conn" ] 40 ) 41 (lib.mkRenamedOptionModule 42 [ "services" "pgbouncer" "defaultPoolSize" ] 43 [ "services" "pgbouncer" "settings" "pgbouncer" "default_pool_size" ] 44 ) 45 (lib.mkRenamedOptionModule 46 [ "services" "pgbouncer" "maxDbConnections" ] 47 [ "services" "pgbouncer" "settings" "pgbouncer" "max_db_connections" ] 48 ) 49 (lib.mkRenamedOptionModule 50 [ "services" "pgbouncer" "maxUserConnections" ] 51 [ "services" "pgbouncer" "settings" "pgbouncer" "max_user_connections" ] 52 ) 53 (lib.mkRenamedOptionModule 54 [ "services" "pgbouncer" "ignoreStartupParameters" ] 55 [ "services" "pgbouncer" "settings" "pgbouncer" "ignore_startup_parameters" ] 56 ) 57 (lib.mkRenamedOptionModule 58 [ "services" "pgbouncer" "databases" ] 59 [ "services" "pgbouncer" "settings" "databases" ] 60 ) 61 (lib.mkRenamedOptionModule 62 [ "services" "pgbouncer" "users" ] 63 [ "services" "pgbouncer" "settings" "users" ] 64 ) 65 (lib.mkRenamedOptionModule 66 [ "services" "pgbouncer" "peers" ] 67 [ "services" "pgbouncer" "settings" "peers" ] 68 ) 69 (lib.mkRenamedOptionModule 70 [ "services" "pgbouncer" "authType" ] 71 [ "services" "pgbouncer" "settings" "pgbouncer" "auth_type" ] 72 ) 73 (lib.mkRenamedOptionModule 74 [ "services" "pgbouncer" "authHbaFile" ] 75 [ "services" "pgbouncer" "settings" "pgbouncer" "auth_hba_file" ] 76 ) 77 (lib.mkRenamedOptionModule 78 [ "services" "pgbouncer" "authFile" ] 79 [ "services" "pgbouncer" "settings" "pgbouncer" "auth_file" ] 80 ) 81 (lib.mkRenamedOptionModule 82 [ "services" "pgbouncer" "authUser" ] 83 [ "services" "pgbouncer" "settings" "pgbouncer" "auth_user" ] 84 ) 85 (lib.mkRenamedOptionModule 86 [ "services" "pgbouncer" "authQuery" ] 87 [ "services" "pgbouncer" "settings" "pgbouncer" "auth_query" ] 88 ) 89 (lib.mkRenamedOptionModule 90 [ "services" "pgbouncer" "authDbname" ] 91 [ "services" "pgbouncer" "settings" "pgbouncer" "auth_dbname" ] 92 ) 93 (lib.mkRenamedOptionModule 94 [ "services" "pgbouncer" "adminUsers" ] 95 [ "services" "pgbouncer" "settings" "pgbouncer" "admin_users" ] 96 ) 97 (lib.mkRenamedOptionModule 98 [ "services" "pgbouncer" "statsUsers" ] 99 [ "services" "pgbouncer" "settings" "pgbouncer" "stats_users" ] 100 ) 101 (lib.mkRenamedOptionModule 102 [ "services" "pgbouncer" "verbose" ] 103 [ "services" "pgbouncer" "settings" "pgbouncer" "verbose" ] 104 ) 105 (lib.mkChangedOptionModule 106 [ "services" "pgbouncer" "syslog" "enable" ] 107 [ "services" "pgbouncer" "settings" "pgbouncer" "syslog" ] 108 ( 109 config: 110 let 111 enable = lib.getAttrFromPath [ "services" "pgbouncer" "syslog" "enable" ] config; 112 in 113 if enable then 1 else 0 114 ) 115 ) 116 (lib.mkRenamedOptionModule 117 [ "services" "pgbouncer" "syslog" "syslogIdent" ] 118 [ "services" "pgbouncer" "settings" "pgbouncer" "syslog_ident" ] 119 ) 120 (lib.mkRenamedOptionModule 121 [ "services" "pgbouncer" "syslog" "syslogFacility" ] 122 [ "services" "pgbouncer" "settings" "pgbouncer" "syslog_facility" ] 123 ) 124 (lib.mkRenamedOptionModule 125 [ "services" "pgbouncer" "tls" "client" "sslmode" ] 126 [ "services" "pgbouncer" "settings" "pgbouncer" "client_tls_sslmode" ] 127 ) 128 (lib.mkRenamedOptionModule 129 [ "services" "pgbouncer" "tls" "client" "keyFile" ] 130 [ "services" "pgbouncer" "settings" "pgbouncer" "client_tls_key_file" ] 131 ) 132 (lib.mkRenamedOptionModule 133 [ "services" "pgbouncer" "tls" "client" "certFile" ] 134 [ "services" "pgbouncer" "settings" "pgbouncer" "client_tls_cert_file" ] 135 ) 136 (lib.mkRenamedOptionModule 137 [ "services" "pgbouncer" "tls" "client" "caFile" ] 138 [ "services" "pgbouncer" "settings" "pgbouncer" "client_tls_ca_file" ] 139 ) 140 (lib.mkRenamedOptionModule 141 [ "services" "pgbouncer" "tls" "server" "sslmode" ] 142 [ "services" "pgbouncer" "settings" "pgbouncer" "server_tls_sslmode" ] 143 ) 144 (lib.mkRenamedOptionModule 145 [ "services" "pgbouncer" "tls" "server" "keyFile" ] 146 [ "services" "pgbouncer" "settings" "pgbouncer" "server_tls_key_file" ] 147 ) 148 (lib.mkRenamedOptionModule 149 [ "services" "pgbouncer" "tls" "server" "certFile" ] 150 [ "services" "pgbouncer" "settings" "pgbouncer" "server_tls_cert_file" ] 151 ) 152 (lib.mkRenamedOptionModule 153 [ "services" "pgbouncer" "tls" "server" "caFile" ] 154 [ "services" "pgbouncer" "settings" "pgbouncer" "server_tls_ca_file" ] 155 ) 156 (lib.mkRemovedOptionModule [ 157 "services" 158 "pgbouncer" 159 "extraConfig" 160 ] "Use services.pgbouncer.settings instead.") 161 ]; 162 163 options.services.pgbouncer = { 164 enable = lib.mkEnableOption "PostgreSQL connection pooler"; 165 166 package = lib.mkPackageOption pkgs "pgbouncer" { }; 167 168 openFirewall = lib.mkOption { 169 type = lib.types.bool; 170 default = false; 171 description = '' 172 Whether to automatically open the specified TCP port in the firewall. 173 ''; 174 }; 175 176 settings = lib.mkOption { 177 type = lib.types.submodule { 178 freeformType = settingsFormat.type; 179 options = { 180 pgbouncer = { 181 listen_port = lib.mkOption { 182 type = lib.types.port; 183 default = 6432; 184 description = '' 185 Which port to listen on. Applies to both TCP and Unix sockets. 186 ''; 187 }; 188 189 listen_addr = lib.mkOption { 190 type = lib.types.nullOr lib.types.commas; 191 example = "*"; 192 default = null; 193 description = '' 194 Specifies a list (comma-separated) of addresses where to listen for TCP connections. 195 You may also use * meaning listen on all addresses. 196 When not set, only Unix socket connections are accepted. 197 198 Addresses can be specified numerically (IPv4/IPv6) or by name. 199 ''; 200 }; 201 202 pool_mode = lib.mkOption { 203 type = lib.types.enum [ 204 "session" 205 "transaction" 206 "statement" 207 ]; 208 default = "session"; 209 description = '' 210 Specifies when a server connection can be reused by other clients. 211 212 session 213 Server is released back to pool after client disconnects. Default. 214 transaction 215 Server is released back to pool after transaction finishes. 216 statement 217 Server is released back to pool after query finishes. 218 Transactions spanning multiple statements are disallowed in this mode. 219 ''; 220 }; 221 222 max_client_conn = lib.mkOption { 223 type = lib.types.int; 224 default = 100; 225 description = '' 226 Maximum number of client connections allowed. 227 228 When this setting is increased, then the file descriptor limits in the operating system 229 might also have to be increased. Note that the number of file descriptors potentially 230 used is more than maxClientConn. If each user connects under its own user name to the server, 231 the theoretical maximum used is: 232 maxClientConn + (max pool_size * total databases * total users) 233 234 If a database user is specified in the connection string (all users connect under the same user name), 235 the theoretical maximum is: 236 maxClientConn + (max pool_size * total databases) 237 238 The theoretical maximum should never be reached, unless somebody deliberately crafts a special load for it. 239 Still, it means you should set the number of file descriptors to a safely high number. 240 ''; 241 }; 242 243 default_pool_size = lib.mkOption { 244 type = lib.types.int; 245 default = 20; 246 description = '' 247 How many server connections to allow per user/database pair. 248 Can be overridden in the per-database configuration. 249 ''; 250 }; 251 252 max_db_connections = lib.mkOption { 253 type = lib.types.int; 254 default = 0; 255 description = '' 256 Do not allow more than this many server connections per database (regardless of user). 257 This considers the PgBouncer database that the client has connected to, 258 not the PostgreSQL database of the outgoing connection. 259 260 This can also be set per database in the [databases] section. 261 262 Note that when you hit the limit, closing a client connection to one pool will 263 not immediately allow a server connection to be established for another pool, 264 because the server connection for the first pool is still open. 265 Once the server connection closes (due to idle timeout), 266 a new server connection will immediately be opened for the waiting pool. 267 268 0 = unlimited 269 ''; 270 }; 271 272 max_user_connections = lib.mkOption { 273 type = lib.types.int; 274 default = 0; 275 description = '' 276 Do not allow more than this many server connections per user (regardless of database). 277 This considers the PgBouncer user that is associated with a pool, 278 which is either the user specified for the server connection 279 or in absence of that the user the client has connected as. 280 281 This can also be set per user in the [users] section. 282 283 Note that when you hit the limit, closing a client connection to one pool 284 will not immediately allow a server connection to be established for another pool, 285 because the server connection for the first pool is still open. 286 Once the server connection closes (due to idle timeout), a new server connection 287 will immediately be opened for the waiting pool. 288 289 0 = unlimited 290 ''; 291 }; 292 293 ignore_startup_parameters = lib.mkOption { 294 type = lib.types.nullOr lib.types.commas; 295 example = "extra_float_digits"; 296 default = null; 297 description = '' 298 By default, PgBouncer allows only parameters it can keep track of in startup packets: 299 client_encoding, datestyle, timezone and standard_conforming_strings. 300 301 All others parameters will raise an error. 302 To allow others parameters, they can be specified here, so that PgBouncer knows that 303 they are handled by the admin and it can ignore them. 304 305 If you need to specify multiple values, use a comma-separated list. 306 307 IMPORTANT: When using prometheus-pgbouncer-exporter, you need: 308 extra_float_digits 309 <https://github.com/prometheus-community/pgbouncer_exporter#pgbouncer-configuration> 310 ''; 311 }; 312 }; 313 databases = lib.mkOption { 314 type = lib.types.attrsOf lib.types.str; 315 default = { }; 316 example = { 317 exampledb = "host=/run/postgresql/ port=5432 auth_user=exampleuser dbname=exampledb sslmode=require"; 318 bardb = "host=localhost dbname=bazdb"; 319 foodb = "host=host1.example.com port=5432"; 320 }; 321 description = '' 322 Detailed information about PostgreSQL database definitions: 323 <https://www.pgbouncer.org/config.html#section-databases> 324 ''; 325 }; 326 users = lib.mkOption { 327 type = lib.types.attrsOf lib.types.str; 328 default = { }; 329 example = { 330 user1 = "pool_mode=session"; 331 }; 332 description = '' 333 Optional. 334 335 Detailed information about PostgreSQL user definitions: 336 <https://www.pgbouncer.org/config.html#section-users> 337 ''; 338 }; 339 340 peers = lib.mkOption { 341 type = lib.types.attrsOf lib.types.str; 342 default = { }; 343 example = { 344 "1" = "host=host1.example.com"; 345 "2" = "host=/tmp/pgbouncer-2 port=5555"; 346 }; 347 description = '' 348 Optional. 349 350 Detailed information about PostgreSQL database definitions: 351 <https://www.pgbouncer.org/config.html#section-peers> 352 ''; 353 }; 354 }; 355 }; 356 default = { }; 357 description = '' 358 Configuration for PgBouncer, see <https://www.pgbouncer.org/config.html> 359 for supported values. 360 ''; 361 }; 362 363 # Linux settings 364 openFilesLimit = lib.mkOption { 365 type = lib.types.int; 366 default = 65536; 367 description = '' 368 Maximum number of open files. 369 ''; 370 }; 371 372 user = lib.mkOption { 373 type = lib.types.str; 374 default = "pgbouncer"; 375 description = '' 376 The user pgbouncer is run as. 377 ''; 378 }; 379 380 group = lib.mkOption { 381 type = lib.types.str; 382 default = "pgbouncer"; 383 description = '' 384 The group pgbouncer is run as. 385 ''; 386 }; 387 388 homeDir = lib.mkOption { 389 type = lib.types.path; 390 default = "/var/lib/pgbouncer"; 391 description = '' 392 Specifies the home directory. 393 ''; 394 }; 395 }; 396 397 config = lib.mkIf cfg.enable { 398 users.groups.${cfg.group} = { }; 399 users.users.${cfg.user} = { 400 description = "PgBouncer service user"; 401 group = cfg.group; 402 home = cfg.homeDir; 403 createHome = true; 404 isSystemUser = true; 405 }; 406 407 environment.etc.${configPath}.source = configFile; 408 409 # Default to RuntimeDirectory instead of /tmp. 410 services.pgbouncer.settings.pgbouncer.unix_socket_dir = lib.mkDefault "/run/pgbouncer"; 411 412 systemd.services.pgbouncer = { 413 description = "PgBouncer - PostgreSQL connection pooler"; 414 wants = [ "network-online.target" ]; 415 after = [ "network-online.target" ]; 416 wantedBy = [ "multi-user.target" ]; 417 reloadTriggers = [ configFile ]; 418 serviceConfig = { 419 Type = "notify-reload"; 420 User = cfg.user; 421 Group = cfg.group; 422 ExecStart = utils.escapeSystemdExecArgs [ 423 (lib.getExe pkgs.pgbouncer) 424 "/etc/${configPath}" 425 ]; 426 RuntimeDirectory = "pgbouncer"; 427 LimitNOFILE = cfg.openFilesLimit; 428 }; 429 }; 430 431 networking.firewall = lib.mkIf cfg.openFirewall { 432 allowedTCPPorts = [ 433 (cfg.settings.pgbouncer.listen_port or 6432) 434 ]; 435 }; 436 }; 437 438 meta.maintainers = [ lib.maintainers._1000101 ]; 439}