nixos/postgresql: change option enableTCPIP to actually mean TCP/IP.#353707
nixos/postgresql: change option enableTCPIP to actually mean TCP/IP.#353707hoh wants to merge 4 commits intoNixOS:masterfrom
enableTCPIP to actually mean TCP/IP.#353707Conversation
Setting the option `services.postgresql.enableTCPIP` to `false` did not disable TCP/IP. Instead, this makes PostgreSQL listen on `localhost`. This was confusing, as a security minded user may want to disable TCP/IP entirely, even for localhost. It also prevented running multiple instances of PostgreSQL on the same host without manually assigning distinct TCP/IP ports. This commit adds a new option, `services.postgres.listenAddresses`, that defaults to `localhost`. The default behaviour of `services.postgresql` is maintained: the service listens on localhost using TCP/IP with the new default `enableTCPIP = null`. A warning informs users that setting `enableTCPIP = true` now only listens on localhost. Setting `listenAddresses` is now required to listen on all or multiple interfaces. This option follows the upstream PostgreSQL syntax for `liste_addresses`.
| Whether PostgreSQL should listen on network interfaces. | ||
| If 'false', the database can only be accessed via its Unix | ||
| domain socket. | ||
| A value of 'null' defaults to 'true'. |
There was a problem hiding this comment.
Why setting the type to nullOr bool when the default is true ?
There was a problem hiding this comment.
The new default is null. This has the same behavior as true but this makes it possible to show a warning only to users who have this option configured, not to users who left the default values.
| listenAddresses = mkOption { | ||
| type = types.str; | ||
| default = "localhost"; | ||
| description = '' | ||
| The TCP/IP address(es) on which the server is to listen for connections from client applications. | ||
| The value takes the form of a comma-separated list of host names and/or numeric IP addresses. | ||
| The special entry * corresponds to all available IP interfaces. | ||
|
|
||
| See the PostgreSQL documentation on [listen_address](https://www.postgresql.org/docs/16/runtime-config-connection.html#GUC-LISTEN-ADDRESSES). | ||
| ''; |
There was a problem hiding this comment.
It would be clearer if it was a list of strings later joined with comma in implementation
There was a problem hiding this comment.
I agree with this, however I am not sure whether the Nixpkgs policy is to map the settings of the services as close as possible ("The value takes the form of a comma-separated list of host names and/or numeric IP addresses") or to provide a more abstract interface.
On a similar topic, other packages use alternative names for this such as hosts, bind, listen, interface, ports, ... listen_addresses is the name of the setting in PostgreSQL (and a few other services).
There was a problem hiding this comment.
I think it you want to keep it like this, I suggest you change the type from string to lib.types.commas which are comma separated strings, which provide an additional check that the definition is valid (see nixos manual).
There was a problem hiding this comment.
I would prefer update this branch with a list of strings (or IP addresses if there is a type for that) if that is compatible with the Nixpkgs policy.
| ident_file = "${pkgs.writeText "pg_ident.conf" cfg.identMap}"; | ||
| log_destination = "stderr"; | ||
| listen_addresses = if cfg.enableTCPIP then "*" else "localhost"; | ||
| listen_addresses = if (cfg.enableTCPIP != false) then cfg.listenAddresses else ""; |
There was a problem hiding this comment.
| listen_addresses = if (cfg.enableTCPIP != false) then cfg.listenAddresses else ""; | |
| listen_addresses = lib.optionalString (cfg.enableTCPIP != false) cfg.listenAddresses; |
|
|
||
| listenAddresses = mkOption { | ||
| type = types.str; | ||
| default = "localhost"; |
There was a problem hiding this comment.
Is that ipv6 localhost ::1 and 127.0.0.1 on ipv4 only systems?
There was a problem hiding this comment.
According to the PostgreSQL documentation:
The default value is localhost, which allows only local TCP/IP “loopback” connections to be made.
Co-authored-by: Sandro <sandro.jaeckel@gmail.com>
Co-authored-by: Sandro <sandro.jaeckel@gmail.com>
Co-authored-by: Sandro <sandro.jaeckel@gmail.com>
There was a problem hiding this comment.
Depending on what goes in first, we need to either adjust here or #352966, where we move all the postgres tests into nixos/tests/postgresql and make sure to run them against all PG versions etc.
There was a problem hiding this comment.
Thanks for linking to that PR, I didn't know about it. Do you think it would be relevant to test the behavior of these options with all PG versions ? My understanding is that this is not affected by the different versions.
There was a problem hiding this comment.
Do you think it would be relevant to test the behavior of these options with all PG versions ?
No, I don't think so. But I haven't made up my mind about where to draw the line, yet.
The "and make sure to run them against all PG versions" was meant as a description for that PR, not necessarily as a requirement for this one.
The requirement is*, that we have it in the same folder eventually, so that we're getting pinged via ci/OWNERS :)
* And that we have it working nicely via passthru, but you already have that in principle, I think. Just avoiding the long relative path would be good (see my PR, too, for how to).
There was a problem hiding this comment.
#352966 has been merged, so you could rebase and move the file to nixos/tests/postgresql/ accordingly.
There was a problem hiding this comment.
Thanks, I will look into that.
| }) cfg.ensureUsers; | ||
|
|
||
| warnings = lib.optional (cfg.enableTCPIP == true) '' | ||
| Behaviour of `services.postgresql.enableTCPIP` changed from binding on all interfaces to binding on localhost in addition to the unix socket. |
There was a problem hiding this comment.
This is wrong: there's now an option called listenAddresses that controls where to listen.
Generally, I'm wondering if we shouldn't just deprecate the enableTCPIP option and give users fine-grained control over the listen address part.
In fact, we don't even need a listenAddresses option, we can just define the option in the freeform settings type (I mean settings.listen_addresses).
I.e.
options.services.postgresql.enableTCPIPgives a deprecation warning.- if
enableTCPIPis set, keep the old behavior (and remove it after a while - given that this is a rather central piece, we may want to go that route). - when it's
null, don't touchlisten_addresses.
Does that make sense?
|
conflicting |
This is an attempt at fixing #346013, started during NixCon 2024 with the help of @jfroche .
Setting the option
services.postgresql.enableTCPIPtofalsedid not disable TCP/IP. Instead, this makes PostgreSQL listen onlocalhost.This was confusing, as a security minded user may want to disable TCP/IP entirely, even for localhost.
It also prevented running multiple instances of PostgreSQL on the same host without manually assigning distinct TCP/IP ports.
This commit adds a new option,
services.postgres.listenAddresses, that defaults tolocalhost.The default behaviour of
services.postgresqlis maintained: the service listens on localhost using TCP/IP with the new defaultenableTCPIP = null.A warning informs users that setting
enableTCPIP = truenow only listens on localhost. SettinglistenAddressesis now required to listen on all or multiple interfaces. This option follows the upstream PostgreSQL syntax forliste_addresses.New tests validate the new behavior.
Things done
nix.conf? (See Nix manual)sandbox = relaxedsandbox = truenix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage./result/bin/)Add a 👍 reaction to pull requests you find important.