mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-06-18 23:50:07 +03:00
Merge pull request #308700 from tie/pgbouncer-settings
nixos/pgbouncer: add services.pgbouncer.settings option
This commit is contained in:
commit
c67dbda54f
6 changed files with 226 additions and 632 deletions
|
@ -184,6 +184,8 @@
|
||||||
|
|
||||||
- `services.ddclient.use` has been deprecated: `ddclient` now supports separate IPv4 and IPv6 configuration. Use `services.ddclient.usev4` and `services.ddclient.usev6` instead.
|
- `services.ddclient.use` has been deprecated: `ddclient` now supports separate IPv4 and IPv6 configuration. Use `services.ddclient.usev4` and `services.ddclient.usev6` instead.
|
||||||
|
|
||||||
|
- `services.pgbouncer` systemd service is configured with `Type=notify-reload` and allows reloading configuration without process restart. PgBouncer configuration options were moved to the free-form type option named [`services.pgbouncer.settings`](#opt-services.pgbouncer.settings) according to the NixOS RFC 0042.
|
||||||
|
|
||||||
- `teleport` has been upgraded from major version 15 to major version 16.
|
- `teleport` has been upgraded from major version 15 to major version 16.
|
||||||
Refer to upstream [upgrade instructions](https://goteleport.com/docs/management/operations/upgrading/)
|
Refer to upstream [upgrade instructions](https://goteleport.com/docs/management/operations/upgrading/)
|
||||||
and [release notes for v16](https://goteleport.com/docs/changelog/#1600-061324).
|
and [release notes for v16](https://goteleport.com/docs/changelog/#1600-061324).
|
||||||
|
|
|
@ -1,543 +1,138 @@
|
||||||
{ lib, pkgs, config, ... } :
|
{ config, lib, utils, pkgs, ... }:
|
||||||
|
|
||||||
with lib;
|
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.services.pgbouncer;
|
cfg = config.services.pgbouncer;
|
||||||
|
|
||||||
confFile = pkgs.writeTextFile {
|
settingsFormat = pkgs.formats.ini { };
|
||||||
name = "pgbouncer.ini";
|
configFile = settingsFormat.generate "pgbouncer.ini" cfg.settings;
|
||||||
text = ''
|
configPath = "pgbouncer/pgbouncer.ini";
|
||||||
[databases]
|
in
|
||||||
${concatStringsSep "\n"
|
{
|
||||||
(mapAttrsToList (dbname : settings : "${dbname} = ${settings}") cfg.databases)}
|
imports = [
|
||||||
|
(lib.mkRenamedOptionModule
|
||||||
[users]
|
[ "services" "pgbouncer" "logFile" ]
|
||||||
${concatStringsSep "\n"
|
[ "services" "pgbouncer" "settings" "pgbouncer" "log_file" ])
|
||||||
(mapAttrsToList (username : settings : "${username} = ${settings}") cfg.users)}
|
(lib.mkRenamedOptionModule
|
||||||
|
[ "services" "pgbouncer" "listenAddress" ]
|
||||||
[peers]
|
[ "services" "pgbouncer" "settings" "pgbouncer" "listen_addr" ])
|
||||||
${concatStringsSep "\n"
|
(lib.mkRenamedOptionModule
|
||||||
(mapAttrsToList (peerid : settings : "${peerid} = ${settings}") cfg.peers)}
|
[ "services" "pgbouncer" "listenPort" ]
|
||||||
|
[ "services" "pgbouncer" "settings" "pgbouncer" "listen_port" ])
|
||||||
[pgbouncer]
|
(lib.mkRenamedOptionModule
|
||||||
# general
|
[ "services" "pgbouncer" "poolMode" ]
|
||||||
${optionalString (cfg.ignoreStartupParameters != null) "ignore_startup_parameters = ${cfg.ignoreStartupParameters}"}
|
[ "services" "pgbouncer" "settings" "pgbouncer" "pool_mode" ])
|
||||||
listen_port = ${toString cfg.listenPort}
|
(lib.mkRenamedOptionModule
|
||||||
${optionalString (cfg.listenAddress != null) "listen_addr = ${cfg.listenAddress}"}
|
[ "services" "pgbouncer" "maxClientConn" ]
|
||||||
pool_mode = ${cfg.poolMode}
|
[ "services" "pgbouncer" "settings" "pgbouncer" "max_client_conn" ])
|
||||||
max_client_conn = ${toString cfg.maxClientConn}
|
(lib.mkRenamedOptionModule
|
||||||
default_pool_size = ${toString cfg.defaultPoolSize}
|
[ "services" "pgbouncer" "defaultPoolSize" ]
|
||||||
max_user_connections = ${toString cfg.maxUserConnections}
|
[ "services" "pgbouncer" "settings" "pgbouncer" "default_pool_size" ])
|
||||||
max_db_connections = ${toString cfg.maxDbConnections}
|
(lib.mkRenamedOptionModule
|
||||||
|
[ "services" "pgbouncer" "maxDbConnections" ]
|
||||||
#auth
|
[ "services" "pgbouncer" "settings" "pgbouncer" "max_db_connections" ])
|
||||||
auth_type = ${cfg.authType}
|
(lib.mkRenamedOptionModule
|
||||||
${optionalString (cfg.authHbaFile != null) "auth_hba_file = ${cfg.authHbaFile}"}
|
[ "services" "pgbouncer" "maxUserConnections" ]
|
||||||
${optionalString (cfg.authFile != null) "auth_file = ${cfg.authFile}"}
|
[ "services" "pgbouncer" "settings" "pgbouncer" "max_user_connections" ])
|
||||||
${optionalString (cfg.authUser != null) "auth_user = ${cfg.authUser}"}
|
(lib.mkRenamedOptionModule
|
||||||
${optionalString (cfg.authQuery != null) "auth_query = ${cfg.authQuery}"}
|
[ "services" "pgbouncer" "ignoreStartupParameters" ]
|
||||||
${optionalString (cfg.authDbname != null) "auth_dbname = ${cfg.authDbname}"}
|
[ "services" "pgbouncer" "settings" "pgbouncer" "ignore_startup_parameters" ])
|
||||||
|
(lib.mkRenamedOptionModule
|
||||||
# TLS
|
[ "services" "pgbouncer" "databases" ]
|
||||||
${optionalString (cfg.tls.client != null) ''
|
[ "services" "pgbouncer" "settings" "databases" ])
|
||||||
client_tls_sslmode = ${cfg.tls.client.sslmode}
|
(lib.mkRenamedOptionModule
|
||||||
client_tls_key_file = ${cfg.tls.client.keyFile}
|
[ "services" "pgbouncer" "users" ]
|
||||||
client_tls_cert_file = ${cfg.tls.client.certFile}
|
[ "services" "pgbouncer" "settings" "users" ])
|
||||||
client_tls_ca_file = ${cfg.tls.client.caFile}
|
(lib.mkRenamedOptionModule
|
||||||
''}
|
[ "services" "pgbouncer" "peers" ]
|
||||||
${optionalString (cfg.tls.server != null) ''
|
[ "services" "pgbouncer" "settings" "peers" ])
|
||||||
server_tls_sslmode = ${cfg.tls.server.sslmode}
|
(lib.mkRenamedOptionModule
|
||||||
server_tls_key_file = ${cfg.tls.server.keyFile}
|
[ "services" "pgbouncer" "authType" ]
|
||||||
server_tls_cert_file = ${cfg.tls.server.certFile}
|
[ "services" "pgbouncer" "settings" "pgbouncer" "auth_type" ])
|
||||||
server_tls_ca_file = ${cfg.tls.server.caFile}
|
(lib.mkRenamedOptionModule
|
||||||
''}
|
[ "services" "pgbouncer" "authHbaFile" ]
|
||||||
|
[ "services" "pgbouncer" "settings" "pgbouncer" "auth_hba_file" ])
|
||||||
# log
|
(lib.mkRenamedOptionModule
|
||||||
${optionalString (cfg.logFile != null) "logfile = ${cfg.homeDir}/${cfg.logFile}"}
|
[ "services" "pgbouncer" "authFile" ]
|
||||||
${optionalString (cfg.syslog != null) ''
|
[ "services" "pgbouncer" "settings" "pgbouncer" "auth_file" ])
|
||||||
syslog = ${if cfg.syslog.enable then "1" else "0"}
|
(lib.mkRenamedOptionModule
|
||||||
syslog_ident = ${cfg.syslog.syslogIdent}
|
[ "services" "pgbouncer" "authUser" ]
|
||||||
syslog_facility = ${cfg.syslog.syslogFacility}
|
[ "services" "pgbouncer" "settings" "pgbouncer" "auth_user" ])
|
||||||
''}
|
(lib.mkRenamedOptionModule
|
||||||
${optionalString (cfg.verbose != null) "verbose = ${toString cfg.verbose}"}
|
[ "services" "pgbouncer" "authQuery" ]
|
||||||
|
[ "services" "pgbouncer" "settings" "pgbouncer" "auth_query" ])
|
||||||
# console access
|
(lib.mkRenamedOptionModule
|
||||||
${optionalString (cfg.adminUsers != null) "admin_users = ${cfg.adminUsers}"}
|
[ "services" "pgbouncer" "authDbname" ]
|
||||||
${optionalString (cfg.statsUsers != null) "stats_users = ${cfg.statsUsers}"}
|
[ "services" "pgbouncer" "settings" "pgbouncer" "auth_dbname" ])
|
||||||
|
(lib.mkRenamedOptionModule
|
||||||
# extra
|
[ "services" "pgbouncer" "adminUsers" ]
|
||||||
${cfg.extraConfig}
|
[ "services" "pgbouncer" "settings" "pgbouncer" "admin_users" ])
|
||||||
'';
|
(lib.mkRenamedOptionModule
|
||||||
};
|
[ "services" "pgbouncer" "statsUsers" ]
|
||||||
|
[ "services" "pgbouncer" "settings" "pgbouncer" "stats_users" ])
|
||||||
in {
|
(lib.mkRenamedOptionModule
|
||||||
|
[ "services" "pgbouncer" "verbose" ]
|
||||||
|
[ "services" "pgbouncer" "settings" "pgbouncer" "verbose" ])
|
||||||
|
(lib.mkChangedOptionModule
|
||||||
|
[ "services" "pgbouncer" "syslog" "enable" ]
|
||||||
|
[ "services" "pgbouncer" "settings" "pgbouncer" "syslog" ]
|
||||||
|
(config:
|
||||||
|
let
|
||||||
|
enable = lib.getAttrFromPath
|
||||||
|
[ "services" "pgbouncer" "syslog" "enable" ]
|
||||||
|
config;
|
||||||
|
in
|
||||||
|
if enable then 1 else 0))
|
||||||
|
(lib.mkRenamedOptionModule
|
||||||
|
[ "services" "pgbouncer" "syslog" "syslogIdent" ]
|
||||||
|
[ "services" "pgbouncer" "settings" "pgbouncer" "syslog_ident" ])
|
||||||
|
(lib.mkRenamedOptionModule
|
||||||
|
[ "services" "pgbouncer" "syslog" "syslogFacility" ]
|
||||||
|
[ "services" "pgbouncer" "settings" "pgbouncer" "syslog_facility" ])
|
||||||
|
(lib.mkRenamedOptionModule
|
||||||
|
[ "services" "pgbouncer" "tls" "client" "sslmode" ]
|
||||||
|
[ "services" "pgbouncer" "settings" "pgbouncer" "client_tls_sslmode" ])
|
||||||
|
(lib.mkRenamedOptionModule
|
||||||
|
[ "services" "pgbouncer" "tls" "client" "keyFile" ]
|
||||||
|
[ "services" "pgbouncer" "settings" "pgbouncer" "client_tls_key_file" ])
|
||||||
|
(lib.mkRenamedOptionModule
|
||||||
|
[ "services" "pgbouncer" "tls" "client" "certFile" ]
|
||||||
|
[ "services" "pgbouncer" "settings" "pgbouncer" "client_tls_cert_file" ])
|
||||||
|
(lib.mkRenamedOptionModule
|
||||||
|
[ "services" "pgbouncer" "tls" "client" "caFile" ]
|
||||||
|
[ "services" "pgbouncer" "settings" "pgbouncer" "client_tls_ca_file" ])
|
||||||
|
(lib.mkRenamedOptionModule
|
||||||
|
[ "services" "pgbouncer" "tls" "server" "sslmode" ]
|
||||||
|
[ "services" "pgbouncer" "settings" "pgbouncer" "server_tls_sslmode" ])
|
||||||
|
(lib.mkRenamedOptionModule
|
||||||
|
[ "services" "pgbouncer" "tls" "server" "keyFile" ]
|
||||||
|
[ "services" "pgbouncer" "settings" "pgbouncer" "server_tls_key_file" ])
|
||||||
|
(lib.mkRenamedOptionModule
|
||||||
|
[ "services" "pgbouncer" "tls" "server" "certFile" ]
|
||||||
|
[ "services" "pgbouncer" "settings" "pgbouncer" "server_tls_cert_file" ])
|
||||||
|
(lib.mkRenamedOptionModule
|
||||||
|
[ "services" "pgbouncer" "tls" "server" "caFile" ]
|
||||||
|
[ "services" "pgbouncer" "settings" "pgbouncer" "server_tls_ca_file" ])
|
||||||
|
(lib.mkRemovedOptionModule [ "services" "pgbouncer" "extraConfig" ] "Use services.pgbouncer.settings instead.")
|
||||||
|
];
|
||||||
|
|
||||||
options.services.pgbouncer = {
|
options.services.pgbouncer = {
|
||||||
|
enable = lib.mkEnableOption "PostgreSQL connection pooler";
|
||||||
|
|
||||||
# NixOS settings
|
package = lib.mkPackageOption pkgs "pgbouncer" { };
|
||||||
|
|
||||||
enable = mkEnableOption "PostgreSQL connection pooler";
|
openFirewall = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
package = mkPackageOption pkgs "pgbouncer" { };
|
|
||||||
|
|
||||||
openFirewall = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = ''
|
||||||
Whether to automatically open the specified TCP port in the firewall.
|
Whether to automatically open the specified TCP port in the firewall.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
# Generic settings
|
settings = lib.mkOption {
|
||||||
|
type = settingsFormat.type;
|
||||||
logFile = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = null;
|
|
||||||
description = ''
|
|
||||||
Specifies a log file in addition to journald.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
listenAddress = mkOption {
|
|
||||||
type = types.nullOr types.commas;
|
|
||||||
example = "*";
|
|
||||||
default = null;
|
|
||||||
description = ''
|
|
||||||
Specifies a list (comma-separated) of addresses where to listen for TCP connections.
|
|
||||||
You may also use * meaning “listen on all addresses”.
|
|
||||||
When not set, only Unix socket connections are accepted.
|
|
||||||
|
|
||||||
Addresses can be specified numerically (IPv4/IPv6) or by name.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
listenPort = mkOption {
|
|
||||||
type = types.port;
|
|
||||||
default = 6432;
|
|
||||||
description = ''
|
|
||||||
Which port to listen on. Applies to both TCP and Unix sockets.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
poolMode = mkOption {
|
|
||||||
type = types.enum [ "session" "transaction" "statement" ];
|
|
||||||
default = "session";
|
|
||||||
description = ''
|
|
||||||
Specifies when a server connection can be reused by other clients.
|
|
||||||
|
|
||||||
session
|
|
||||||
Server is released back to pool after client disconnects. Default.
|
|
||||||
transaction
|
|
||||||
Server is released back to pool after transaction finishes.
|
|
||||||
statement
|
|
||||||
Server is released back to pool after query finishes.
|
|
||||||
Transactions spanning multiple statements are disallowed in this mode.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
maxClientConn = mkOption {
|
|
||||||
type = types.int;
|
|
||||||
default = 100;
|
|
||||||
description = ''
|
|
||||||
Maximum number of client connections allowed.
|
|
||||||
|
|
||||||
When this setting is increased, then the file descriptor limits in the operating system
|
|
||||||
might also have to be increased. Note that the number of file descriptors potentially
|
|
||||||
used is more than maxClientConn. If each user connects under its own user name to the server,
|
|
||||||
the theoretical maximum used is:
|
|
||||||
maxClientConn + (max pool_size * total databases * total users)
|
|
||||||
|
|
||||||
If a database user is specified in the connection string (all users connect under the same user name),
|
|
||||||
the theoretical maximum is:
|
|
||||||
maxClientConn + (max pool_size * total databases)
|
|
||||||
|
|
||||||
The theoretical maximum should never be reached, unless somebody deliberately crafts a special load for it.
|
|
||||||
Still, it means you should set the number of file descriptors to a safely high number.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
defaultPoolSize = mkOption {
|
|
||||||
type = types.int;
|
|
||||||
default = 20;
|
|
||||||
description = ''
|
|
||||||
How many server connections to allow per user/database pair.
|
|
||||||
Can be overridden in the per-database configuration.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
maxDbConnections = mkOption {
|
|
||||||
type = types.int;
|
|
||||||
default = 0;
|
|
||||||
description = ''
|
|
||||||
Do not allow more than this many server connections per database (regardless of user).
|
|
||||||
This considers the PgBouncer database that the client has connected to,
|
|
||||||
not the PostgreSQL database of the outgoing connection.
|
|
||||||
|
|
||||||
This can also be set per database in the [databases] section.
|
|
||||||
|
|
||||||
Note that when you hit the limit, closing a client connection to one pool will
|
|
||||||
not immediately allow a server connection to be established for another pool,
|
|
||||||
because the server connection for the first pool is still open.
|
|
||||||
Once the server connection closes (due to idle timeout),
|
|
||||||
a new server connection will immediately be opened for the waiting pool.
|
|
||||||
|
|
||||||
0 = unlimited
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
maxUserConnections = mkOption {
|
|
||||||
type = types.int;
|
|
||||||
default = 0;
|
|
||||||
description = ''
|
|
||||||
Do not allow more than this many server connections per user (regardless of database).
|
|
||||||
This considers the PgBouncer user that is associated with a pool,
|
|
||||||
which is either the user specified for the server connection
|
|
||||||
or in absence of that the user the client has connected as.
|
|
||||||
|
|
||||||
This can also be set per user in the [users] section.
|
|
||||||
|
|
||||||
Note that when you hit the limit, closing a client connection to one pool
|
|
||||||
will not immediately allow a server connection to be established for another pool,
|
|
||||||
because the server connection for the first pool is still open.
|
|
||||||
Once the server connection closes (due to idle timeout), a new server connection
|
|
||||||
will immediately be opened for the waiting pool.
|
|
||||||
|
|
||||||
0 = unlimited
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
ignoreStartupParameters = mkOption {
|
|
||||||
type = types.nullOr types.commas;
|
|
||||||
example = "extra_float_digits";
|
|
||||||
default = null;
|
|
||||||
description = ''
|
|
||||||
By default, PgBouncer allows only parameters it can keep track of in startup packets:
|
|
||||||
client_encoding, datestyle, timezone and standard_conforming_strings.
|
|
||||||
|
|
||||||
All others parameters will raise an error.
|
|
||||||
To allow others parameters, they can be specified here, so that PgBouncer knows that
|
|
||||||
they are handled by the admin and it can ignore them.
|
|
||||||
|
|
||||||
If you need to specify multiple values, use a comma-separated list.
|
|
||||||
|
|
||||||
IMPORTANT: When using prometheus-pgbouncer-exporter, you need:
|
|
||||||
extra_float_digits
|
|
||||||
<https://github.com/prometheus-community/pgbouncer_exporter#pgbouncer-configuration>
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# Section [databases]
|
|
||||||
databases = mkOption {
|
|
||||||
type = types.attrsOf types.str;
|
|
||||||
default = { };
|
default = { };
|
||||||
example = {
|
|
||||||
exampledb = "host=/run/postgresql/ port=5432 auth_user=exampleuser dbname=exampledb sslmode=require";
|
|
||||||
bardb = "host=localhost dbname=bazdb";
|
|
||||||
foodb = "host=host1.example.com port=5432";
|
|
||||||
};
|
|
||||||
description = ''
|
description = ''
|
||||||
Detailed information about PostgreSQL database definitions:
|
Configuration for PgBouncer, see <https://www.pgbouncer.org/config.html>
|
||||||
<https://www.pgbouncer.org/config.html#section-databases>
|
for supported values.
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# Section [users]
|
|
||||||
users = mkOption {
|
|
||||||
type = types.attrsOf types.str;
|
|
||||||
default = {};
|
|
||||||
example = {
|
|
||||||
user1 = "pool_mode=session";
|
|
||||||
};
|
|
||||||
description = ''
|
|
||||||
Optional.
|
|
||||||
|
|
||||||
Detailed information about PostgreSQL user definitions:
|
|
||||||
<https://www.pgbouncer.org/config.html#section-users>
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# Section [peers]
|
|
||||||
peers = mkOption {
|
|
||||||
type = types.attrsOf types.str;
|
|
||||||
default = {};
|
|
||||||
example = {
|
|
||||||
"1" = "host=host1.example.com";
|
|
||||||
"2" = "host=/tmp/pgbouncer-2 port=5555";
|
|
||||||
};
|
|
||||||
description = ''
|
|
||||||
Optional.
|
|
||||||
|
|
||||||
Detailed information about PostgreSQL database definitions:
|
|
||||||
<https://www.pgbouncer.org/config.html#section-peers>
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# Authentication settings
|
|
||||||
authType = mkOption {
|
|
||||||
type = types.enum [ "cert" "md5" "scram-sha-256" "plain" "trust" "any" "hba" "pam" ];
|
|
||||||
default = "md5";
|
|
||||||
description = ''
|
|
||||||
How to authenticate users.
|
|
||||||
|
|
||||||
cert
|
|
||||||
Client must connect over TLS connection with a valid client certificate.
|
|
||||||
The user name is then taken from the CommonName field from the certificate.
|
|
||||||
md5
|
|
||||||
Use MD5-based password check. This is the default authentication method.
|
|
||||||
authFile may contain both MD5-encrypted and plain-text passwords.
|
|
||||||
If md5 is configured and a user has a SCRAM secret, then SCRAM authentication is used automatically instead.
|
|
||||||
scram-sha-256
|
|
||||||
Use password check with SCRAM-SHA-256. authFile has to contain SCRAM secrets or plain-text passwords.
|
|
||||||
plain
|
|
||||||
The clear-text password is sent over the wire. Deprecated.
|
|
||||||
trust
|
|
||||||
No authentication is done. The user name must still exist in authFile.
|
|
||||||
any
|
|
||||||
Like the trust method, but the user name given is ignored.
|
|
||||||
Requires that all databases are configured to log in as a specific user.
|
|
||||||
Additionally, the console database allows any user to log in as admin.
|
|
||||||
hba
|
|
||||||
The actual authentication type is loaded from authHbaFile.
|
|
||||||
This allows different authentication methods for different access paths,
|
|
||||||
for example: connections over Unix socket use the peer auth method, connections over TCP must use TLS.
|
|
||||||
pam
|
|
||||||
PAM is used to authenticate users, authFile is ignored.
|
|
||||||
This method is not compatible with databases using the authUser option.
|
|
||||||
The service name reported to PAM is “pgbouncer”. pam is not supported in the HBA configuration file.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
authHbaFile = mkOption {
|
|
||||||
type = types.nullOr types.path;
|
|
||||||
default = null;
|
|
||||||
example = "/secrets/pgbouncer_hba";
|
|
||||||
description = ''
|
|
||||||
HBA configuration file to use when authType is hba.
|
|
||||||
|
|
||||||
See HBA file format details:
|
|
||||||
<https://www.pgbouncer.org/config.html#hba-file-format>
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
authFile = mkOption {
|
|
||||||
type = types.nullOr types.path;
|
|
||||||
default = null;
|
|
||||||
example = "/secrets/pgbouncer_authfile";
|
|
||||||
description = ''
|
|
||||||
The name of the file to load user names and passwords from.
|
|
||||||
|
|
||||||
See section Authentication file format details:
|
|
||||||
<https://www.pgbouncer.org/config.html#authentication-file-format>
|
|
||||||
|
|
||||||
Most authentication types require that either authFile or authUser be set;
|
|
||||||
otherwise there would be no users defined.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
authUser = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = null;
|
|
||||||
example = "pgbouncer";
|
|
||||||
description = ''
|
|
||||||
If authUser is set, then any user not specified in authFile will be queried
|
|
||||||
through the authQuery query from pg_shadow in the database, using authUser.
|
|
||||||
The password of authUser will be taken from authFile.
|
|
||||||
(If the authUser does not require a password then it does not need to be defined in authFile.)
|
|
||||||
|
|
||||||
Direct access to pg_shadow requires admin rights.
|
|
||||||
It's preferable to use a non-superuser that calls a SECURITY DEFINER function instead.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
authQuery = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = null;
|
|
||||||
example = "SELECT usename, passwd FROM pg_shadow WHERE usename=$1";
|
|
||||||
description = ''
|
|
||||||
Query to load user's password from database.
|
|
||||||
|
|
||||||
Direct access to pg_shadow requires admin rights.
|
|
||||||
It's preferable to use a non-superuser that calls a SECURITY DEFINER function instead.
|
|
||||||
|
|
||||||
Note that the query is run inside the target database.
|
|
||||||
So if a function is used, it needs to be installed into each database.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
authDbname = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = null;
|
|
||||||
example = "authdb";
|
|
||||||
description = ''
|
|
||||||
Database name in the [database] section to be used for authentication purposes.
|
|
||||||
This option can be either global or overriden in the connection string if this parameter is specified.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# TLS settings
|
|
||||||
tls.client = mkOption {
|
|
||||||
type = types.nullOr (types.submodule {
|
|
||||||
options = {
|
|
||||||
sslmode = mkOption {
|
|
||||||
type = types.enum [ "disable" "allow" "prefer" "require" "verify-ca" "verify-full" ];
|
|
||||||
default = "disable";
|
|
||||||
description = ''
|
|
||||||
TLS mode to use for connections from clients.
|
|
||||||
TLS connections are disabled by default.
|
|
||||||
|
|
||||||
When enabled, tls.client.keyFile and tls.client.certFile
|
|
||||||
must be also configured to set up the key and certificate
|
|
||||||
PgBouncer uses to accept client connections.
|
|
||||||
|
|
||||||
disable
|
|
||||||
Plain TCP. If client requests TLS, it's ignored. Default.
|
|
||||||
allow
|
|
||||||
If client requests TLS, it is used. If not, plain TCP is used.
|
|
||||||
If the client presents a client certificate, it is not validated.
|
|
||||||
prefer
|
|
||||||
Same as allow.
|
|
||||||
require
|
|
||||||
Client must use TLS. If not, the client connection is rejected.
|
|
||||||
If the client presents a client certificate, it is not validated.
|
|
||||||
verify-ca
|
|
||||||
Client must use TLS with valid client certificate.
|
|
||||||
verify-full
|
|
||||||
Same as verify-ca
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
certFile = mkOption {
|
|
||||||
type = types.path;
|
|
||||||
example = "/secrets/pgbouncer.key";
|
|
||||||
description = "Path to certificate for private key. Clients can validate it";
|
|
||||||
};
|
|
||||||
keyFile = mkOption {
|
|
||||||
type = types.path;
|
|
||||||
example = "/secrets/pgbouncer.crt";
|
|
||||||
description = "Path to private key for PgBouncer to accept client connections";
|
|
||||||
};
|
|
||||||
caFile = mkOption {
|
|
||||||
type = types.path;
|
|
||||||
example = "/secrets/pgbouncer.crt";
|
|
||||||
description = "Path to root certificate file to validate client certificates";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
});
|
|
||||||
default = null;
|
|
||||||
description = ''
|
|
||||||
<https://www.pgbouncer.org/config.html#tls-settings>
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
tls.server = mkOption {
|
|
||||||
type = types.nullOr (types.submodule {
|
|
||||||
options = {
|
|
||||||
sslmode = mkOption {
|
|
||||||
type = types.enum [ "disable" "allow" "prefer" "require" "verify-ca" "verify-full" ];
|
|
||||||
default = "disable";
|
|
||||||
description = ''
|
|
||||||
TLS mode to use for connections to PostgreSQL servers.
|
|
||||||
TLS connections are disabled by default.
|
|
||||||
|
|
||||||
disable
|
|
||||||
Plain TCP. TLS is not even requested from the server. Default.
|
|
||||||
allow
|
|
||||||
FIXME: if server rejects plain, try TLS?
|
|
||||||
prefer
|
|
||||||
TLS connection is always requested first from PostgreSQL.
|
|
||||||
If refused, the connection will be established over plain TCP.
|
|
||||||
Server certificate is not validated.
|
|
||||||
require
|
|
||||||
Connection must go over TLS. If server rejects it, plain TCP is not attempted.
|
|
||||||
Server certificate is not validated.
|
|
||||||
verify-ca
|
|
||||||
Connection must go over TLS and server certificate must be valid according to tls.server.caFile.
|
|
||||||
Server host name is not checked against certificate.
|
|
||||||
verify-full
|
|
||||||
Connection must go over TLS and server certificate must be valid according to tls.server.caFile.
|
|
||||||
Server host name must match certificate information.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
certFile = mkOption {
|
|
||||||
type = types.path;
|
|
||||||
example = "/secrets/pgbouncer_server.key";
|
|
||||||
description = "Certificate for private key. PostgreSQL server can validate it.";
|
|
||||||
};
|
|
||||||
keyFile = mkOption {
|
|
||||||
type = types.path;
|
|
||||||
example = "/secrets/pgbouncer_server.crt";
|
|
||||||
description = "Private key for PgBouncer to authenticate against PostgreSQL server.";
|
|
||||||
};
|
|
||||||
caFile = mkOption {
|
|
||||||
type = types.path;
|
|
||||||
example = "/secrets/pgbouncer_server.crt";
|
|
||||||
description = "Root certificate file to validate PostgreSQL server certificates.";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
});
|
|
||||||
default = null;
|
|
||||||
description = ''
|
|
||||||
<https://www.pgbouncer.org/config.html#tls-settings>
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# Log settings
|
|
||||||
syslog = mkOption {
|
|
||||||
type = types.nullOr (types.submodule {
|
|
||||||
options = {
|
|
||||||
enable = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = false;
|
|
||||||
description = ''
|
|
||||||
Toggles syslog on/off.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
syslogIdent = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "pgbouncer";
|
|
||||||
description = ''
|
|
||||||
Under what name to send logs to syslog.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
syslogFacility = mkOption {
|
|
||||||
type = types.enum [ "auth" "authpriv" "daemon" "user" "local0" "local1" "local2" "local3" "local4" "local5" "local6" "local7" ];
|
|
||||||
default = "daemon";
|
|
||||||
description = ''
|
|
||||||
Under what facility to send logs to syslog.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
});
|
|
||||||
default = null;
|
|
||||||
description = ''
|
|
||||||
<https://www.pgbouncer.org/config.html#log-settings>
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
verbose = lib.mkOption {
|
|
||||||
type = lib.types.int;
|
|
||||||
default = 0;
|
|
||||||
description = ''
|
|
||||||
Increase verbosity. Mirrors the “-v” switch on the command line.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# Console access control
|
|
||||||
adminUsers = mkOption {
|
|
||||||
type = types.nullOr types.commas;
|
|
||||||
default = null;
|
|
||||||
description = ''
|
|
||||||
Comma-separated list of database users that are allowed to connect and run all commands on the console.
|
|
||||||
Ignored when authType is any, in which case any user name is allowed in as admin.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
statsUsers = mkOption {
|
|
||||||
type = types.nullOr types.commas;
|
|
||||||
default = null;
|
|
||||||
description = ''
|
|
||||||
Comma-separated list of database users that are allowed to connect and run read-only queries on the console.
|
|
||||||
That means all SHOW commands except SHOW FDS.
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -550,42 +145,32 @@ in {
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
user = mkOption {
|
user = lib.mkOption {
|
||||||
type = types.str;
|
type = lib.types.str;
|
||||||
default = "pgbouncer";
|
default = "pgbouncer";
|
||||||
description = ''
|
description = ''
|
||||||
The user pgbouncer is run as.
|
The user pgbouncer is run as.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
group = mkOption {
|
group = lib.mkOption {
|
||||||
type = types.str;
|
type = lib.types.str;
|
||||||
default = "pgbouncer";
|
default = "pgbouncer";
|
||||||
description = ''
|
description = ''
|
||||||
The group pgbouncer is run as.
|
The group pgbouncer is run as.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
homeDir = mkOption {
|
homeDir = lib.mkOption {
|
||||||
type = types.path;
|
type = lib.types.path;
|
||||||
default = "/var/lib/pgbouncer";
|
default = "/var/lib/pgbouncer";
|
||||||
description = ''
|
description = ''
|
||||||
Specifies the home directory.
|
Specifies the home directory.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
# Extra settings
|
|
||||||
extraConfig = mkOption {
|
|
||||||
type = types.lines;
|
|
||||||
description = ''
|
|
||||||
Any additional text to be appended to config.ini
|
|
||||||
<https://www.pgbouncer.org/config.html>.
|
|
||||||
'';
|
|
||||||
default = "";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
users.groups.${cfg.group} = { };
|
users.groups.${cfg.group} = { };
|
||||||
users.users.${cfg.user} = {
|
users.users.${cfg.user} = {
|
||||||
description = "PgBouncer service user";
|
description = "PgBouncer service user";
|
||||||
|
@ -595,26 +180,36 @@ in {
|
||||||
isSystemUser = true;
|
isSystemUser = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
environment.etc.${configPath}.source = configFile;
|
||||||
|
|
||||||
|
# Default to RuntimeDirectory instead of /tmp.
|
||||||
|
services.pgbouncer.settings.pgbouncer.unix_socket_dir = lib.mkDefault "/run/pgbouncer";
|
||||||
|
|
||||||
systemd.services.pgbouncer = {
|
systemd.services.pgbouncer = {
|
||||||
description = "PgBouncer - PostgreSQL connection pooler";
|
description = "PgBouncer - PostgreSQL connection pooler";
|
||||||
wants = [ "network-online.target" ] ++ lib.optional config.services.postgresql.enable "postgresql.service";
|
wants = [ "network-online.target" ];
|
||||||
after = [ "network-online.target" ] ++ lib.optional config.services.postgresql.enable "postgresql.service";
|
after = [ "network-online.target" ];
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
reloadTriggers = [ configFile ];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "notify";
|
Type = "notify-reload";
|
||||||
User = cfg.user;
|
User = cfg.user;
|
||||||
Group = cfg.group;
|
Group = cfg.group;
|
||||||
ExecStart = "${lib.getExe pkgs.pgbouncer} ${confFile}";
|
ExecStart = utils.escapeSystemdExecArgs [
|
||||||
ExecReload = "${pkgs.coreutils}/bin/kill -SIGHUP $MAINPID";
|
(lib.getExe pkgs.pgbouncer)
|
||||||
|
"/etc/${configPath}"
|
||||||
|
];
|
||||||
RuntimeDirectory = "pgbouncer";
|
RuntimeDirectory = "pgbouncer";
|
||||||
LimitNOFILE = cfg.openFilesLimit;
|
LimitNOFILE = cfg.openFilesLimit;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.listenPort;
|
networking.firewall = lib.mkIf cfg.openFirewall {
|
||||||
|
allowedTCPPorts = [
|
||||||
|
(cfg.settings.pgbouncer.listen_port or 6432)
|
||||||
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
meta.maintainers = [ maintainers._1000101 ];
|
meta.maintainers = [ lib.maintainers._1000101 ];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -367,18 +367,6 @@ in
|
||||||
message = ''
|
message = ''
|
||||||
PgBouncer exporter needs either connectionStringFile or connectionString configured"
|
PgBouncer exporter needs either connectionStringFile or connectionString configured"
|
||||||
'';
|
'';
|
||||||
} {
|
|
||||||
assertion = cfg.pgbouncer.enable -> (
|
|
||||||
config.services.pgbouncer.ignoreStartupParameters != null && builtins.match ".*extra_float_digits.*" config.services.pgbouncer.ignoreStartupParameters != null
|
|
||||||
);
|
|
||||||
message = ''
|
|
||||||
Prometheus PgBouncer exporter requires including `extra_float_digits` in services.pgbouncer.ignoreStartupParameters
|
|
||||||
|
|
||||||
Example:
|
|
||||||
services.pgbouncer.ignoreStartupParameters = extra_float_digits;
|
|
||||||
|
|
||||||
See https://github.com/prometheus-community/pgbouncer_exporter#pgbouncer-configuration
|
|
||||||
'';
|
|
||||||
} {
|
} {
|
||||||
assertion = cfg.sql.enable -> (
|
assertion = cfg.sql.enable -> (
|
||||||
(cfg.sql.configFile == null) != (cfg.sql.configuration == null)
|
(cfg.sql.configFile == null) != (cfg.sql.configuration == null)
|
||||||
|
@ -437,11 +425,6 @@ in
|
||||||
config.services.prometheus.exporters.pgbouncer.connectionString is insecure. Use connectionStringFile instead.
|
config.services.prometheus.exporters.pgbouncer.connectionString is insecure. Use connectionStringFile instead.
|
||||||
''
|
''
|
||||||
)
|
)
|
||||||
(mkIf
|
|
||||||
(cfg.pgbouncer.enable && config.services.pgbouncer.authType != "any") ''
|
|
||||||
Admin user (with password or passwordless) MUST exist in the services.pgbouncer.authFile if authType other than any is used.
|
|
||||||
''
|
|
||||||
)
|
|
||||||
] ++ config.services.prometheus.exporters.warnings;
|
] ++ config.services.prometheus.exporters.warnings;
|
||||||
}] ++ [(mkIf config.services.prometheus.exporters.rtl_433.enable {
|
}] ++ [(mkIf config.services.prometheus.exporters.rtl_433.enable {
|
||||||
hardware.rtl-sdr.enable = mkDefault true;
|
hardware.rtl-sdr.enable = mkDefault true;
|
||||||
|
|
|
@ -4,15 +4,21 @@ let
|
||||||
cfg = config.services.prometheus.exporters.pgbouncer;
|
cfg = config.services.prometheus.exporters.pgbouncer;
|
||||||
inherit (lib)
|
inherit (lib)
|
||||||
mkOption
|
mkOption
|
||||||
|
mkPackageOption
|
||||||
types
|
types
|
||||||
optionals
|
optionals
|
||||||
|
optionalString
|
||||||
|
getExe
|
||||||
|
getExe'
|
||||||
escapeShellArg
|
escapeShellArg
|
||||||
|
escapeShellArgs
|
||||||
concatStringsSep
|
concatStringsSep
|
||||||
;
|
;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
port = 9127;
|
port = 9127;
|
||||||
extraOpts = {
|
extraOpts = {
|
||||||
|
package = mkPackageOption pkgs "prometheus-pgbouncer-exporter" { };
|
||||||
|
|
||||||
telemetryPath = mkOption {
|
telemetryPath = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
|
@ -31,8 +37,10 @@ in
|
||||||
|
|
||||||
NOTE: You MUST keep pgbouncer as database name (special internal db)!!!
|
NOTE: You MUST keep pgbouncer as database name (special internal db)!!!
|
||||||
|
|
||||||
NOTE: Admin user (with password or passwordless) MUST exist
|
NOTE: ignore_startup_parameters MUST contain "extra_float_digits".
|
||||||
in the services.pgbouncer.authFile if authType other than any is used.
|
|
||||||
|
NOTE: Admin user (with password or passwordless) MUST exist in the
|
||||||
|
auth_file if auth_type other than "any" is used.
|
||||||
|
|
||||||
WARNING: this secret is stored in the world-readable Nix store!
|
WARNING: this secret is stored in the world-readable Nix store!
|
||||||
Use {option}`connectionStringFile` instead.
|
Use {option}`connectionStringFile` instead.
|
||||||
|
@ -49,8 +57,10 @@ in
|
||||||
|
|
||||||
NOTE: You MUST keep pgbouncer as database name (special internal db)!!!
|
NOTE: You MUST keep pgbouncer as database name (special internal db)!!!
|
||||||
|
|
||||||
NOTE: Admin user (with password or passwordless) MUST exist
|
NOTE: ignore_startup_parameters MUST contain "extra_float_digits".
|
||||||
in the services.pgbouncer.authFile if authType other than any is used.
|
|
||||||
|
NOTE: Admin user (with password or passwordless) MUST exist in the
|
||||||
|
auth_file if auth_type other than "any" is used.
|
||||||
|
|
||||||
{option}`connectionStringFile` takes precedence over {option}`connectionString`
|
{option}`connectionStringFile` takes precedence over {option}`connectionString`
|
||||||
'';
|
'';
|
||||||
|
@ -116,35 +126,30 @@ in
|
||||||
|
|
||||||
serviceOpts = {
|
serviceOpts = {
|
||||||
after = [ "pgbouncer.service" ];
|
after = [ "pgbouncer.service" ];
|
||||||
serviceConfig = let
|
script = optionalString (cfg.connectionStringFile != null) ''
|
||||||
startScript = pkgs.writeShellScriptBin "pgbouncer-start" "${concatStringsSep " " ([
|
connectionString=$(${escapeShellArgs [
|
||||||
"${pkgs.prometheus-pgbouncer-exporter}/bin/pgbouncer_exporter"
|
(getExe' pkgs.coreutils "cat") "--" cfg.connectionStringFile
|
||||||
|
]})
|
||||||
|
'' + concatStringsSep " " ([
|
||||||
|
"exec -- ${escapeShellArg (getExe cfg.package)}"
|
||||||
"--web.listen-address ${cfg.listenAddress}:${toString cfg.port}"
|
"--web.listen-address ${cfg.listenAddress}:${toString cfg.port}"
|
||||||
"--pgBouncer.connectionString ${if cfg.connectionStringFile != null then
|
"--pgBouncer.connectionString ${if cfg.connectionStringFile != null
|
||||||
"$(head -n1 ${cfg.connectionStringFile})" else "${escapeShellArg cfg.connectionString}"}"
|
then "\"$connectionString\""
|
||||||
]
|
else "${escapeShellArg cfg.connectionString}"}"
|
||||||
++ optionals (cfg.telemetryPath != null) [
|
] ++ optionals (cfg.telemetryPath != null) [
|
||||||
"--web.telemetry-path ${escapeShellArg cfg.telemetryPath}"
|
"--web.telemetry-path ${escapeShellArg cfg.telemetryPath}"
|
||||||
]
|
] ++ optionals (cfg.pidFile != null) [
|
||||||
++ optionals (cfg.pidFile != null) [
|
"--pgBouncer.pid-file ${escapeShellArg cfg.pidFile}"
|
||||||
"--pgBouncer.pid-file= ${escapeShellArg cfg.pidFile}"
|
] ++ optionals (cfg.logLevel != null) [
|
||||||
]
|
|
||||||
++ optionals (cfg.logLevel != null) [
|
|
||||||
"--log.level ${escapeShellArg cfg.logLevel}"
|
"--log.level ${escapeShellArg cfg.logLevel}"
|
||||||
]
|
] ++ optionals (cfg.logFormat != null) [
|
||||||
++ optionals (cfg.logFormat != null) [
|
|
||||||
"--log.format ${escapeShellArg cfg.logFormat}"
|
"--log.format ${escapeShellArg cfg.logFormat}"
|
||||||
]
|
] ++ optionals (cfg.webSystemdSocket != false) [
|
||||||
++ optionals (cfg.webSystemdSocket != false) [
|
|
||||||
"--web.systemd-socket ${escapeShellArg cfg.webSystemdSocket}"
|
"--web.systemd-socket ${escapeShellArg cfg.webSystemdSocket}"
|
||||||
]
|
] ++ optionals (cfg.webConfigFile != null) [
|
||||||
++ optionals (cfg.webConfigFile != null) [
|
|
||||||
"--web.config.file ${escapeShellArg cfg.webConfigFile}"
|
"--web.config.file ${escapeShellArg cfg.webConfigFile}"
|
||||||
]
|
] ++ cfg.extraFlags);
|
||||||
++ cfg.extraFlags)}";
|
|
||||||
in
|
serviceConfig.RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
|
||||||
{
|
|
||||||
ExecStart = "${startScript}/bin/pgbouncer-start";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,12 @@
|
||||||
import ./make-test-python.nix ({ pkgs, ... } :
|
import ./make-test-python.nix ({ lib, pkgs, ... }: {
|
||||||
let
|
|
||||||
testAuthFile = pkgs.writeTextFile {
|
|
||||||
name = "authFile";
|
|
||||||
text = ''
|
|
||||||
"testuser" "testpass"
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
name = "pgbouncer";
|
name = "pgbouncer";
|
||||||
meta = with pkgs.lib.maintainers; {
|
|
||||||
|
meta = with lib.maintainers; {
|
||||||
maintainers = [ _1000101 ];
|
maintainers = [ _1000101 ];
|
||||||
};
|
};
|
||||||
nodes = {
|
|
||||||
one = { config, pkgs, ... }: {
|
|
||||||
|
|
||||||
|
nodes = {
|
||||||
|
one = { pkgs, ... }: {
|
||||||
systemd.services.postgresql = {
|
systemd.services.postgresql = {
|
||||||
postStart = ''
|
postStart = ''
|
||||||
${pkgs.postgresql}/bin/psql -U postgres -c "ALTER ROLE testuser WITH LOGIN PASSWORD 'testpass'";
|
${pkgs.postgresql}/bin/psql -U postgres -c "ALTER ROLE testuser WITH LOGIN PASSWORD 'testpass'";
|
||||||
|
@ -26,10 +18,7 @@ in
|
||||||
postgresql = {
|
postgresql = {
|
||||||
enable = true;
|
enable = true;
|
||||||
ensureDatabases = [ "testdb" ];
|
ensureDatabases = [ "testdb" ];
|
||||||
ensureUsers = [
|
ensureUsers = [{ name = "testuser"; }];
|
||||||
{
|
|
||||||
name = "testuser";
|
|
||||||
}];
|
|
||||||
authentication = ''
|
authentication = ''
|
||||||
local testdb testuser scram-sha-256
|
local testdb testuser scram-sha-256
|
||||||
'';
|
'';
|
||||||
|
@ -37,10 +26,19 @@ in
|
||||||
|
|
||||||
pgbouncer = {
|
pgbouncer = {
|
||||||
enable = true;
|
enable = true;
|
||||||
listenAddress = "localhost";
|
openFirewall = true;
|
||||||
databases = { test = "host=/run/postgresql/ port=5432 auth_user=testuser dbname=testdb"; };
|
settings = {
|
||||||
authType = "scram-sha-256";
|
pgbouncer = {
|
||||||
authFile = testAuthFile;
|
listen_addr = "localhost";
|
||||||
|
auth_type = "scram-sha-256";
|
||||||
|
auth_file = builtins.toFile "pgbouncer-users.txt" ''
|
||||||
|
"testuser" "testpass"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
databases = {
|
||||||
|
test = "host=/run/postgresql port=5432 auth_user=testuser dbname=testdb";
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1001,13 +1001,24 @@ let
|
||||||
metricProvider = {
|
metricProvider = {
|
||||||
services.postgresql.enable = true;
|
services.postgresql.enable = true;
|
||||||
services.pgbouncer = {
|
services.pgbouncer = {
|
||||||
# https://github.com/prometheus-community/pgbouncer_exporter#pgbouncer-configuration
|
|
||||||
ignoreStartupParameters = "extra_float_digits";
|
|
||||||
enable = true;
|
enable = true;
|
||||||
listenAddress = "*";
|
settings = {
|
||||||
databases = { postgres = "host=/run/postgresql/ port=5432 auth_user=postgres dbname=postgres"; };
|
pgbouncer = {
|
||||||
authType = "any";
|
listen_addr = "*";
|
||||||
maxClientConn = 99;
|
auth_type = "any";
|
||||||
|
max_client_conn = 99;
|
||||||
|
# https://github.com/prometheus-community/pgbouncer_exporter#pgbouncer-configuration
|
||||||
|
ignore_startup_parameters = "extra_float_digits";
|
||||||
|
};
|
||||||
|
databases = {
|
||||||
|
postgres = concatStringsSep " " [
|
||||||
|
"host=/run/postgresql"
|
||||||
|
"port=5432"
|
||||||
|
"auth_user=postgres"
|
||||||
|
"dbname=postgres"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
exporterTest = ''
|
exporterTest = ''
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue