Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nixos/postgresql: change option enableTCPIP to actually mean TCP/IP. #353707

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

hoh
Copy link

@hoh hoh commented Nov 4, 2024

This is an attempt at fixing #346013, started during NixCon 2024 with the help of @jfroche .


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.

New tests validate the new behavior.

Things done

  • Built on platform(s)
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • For non-Linux: Is sandboxing enabled in nix.conf? (See Nix manual)
    • sandbox = relaxed
    • sandbox = true
  • Tested, as applicable:
  • Tested compilation of all packages that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage
  • Tested basic functionality of all binary files (usually in ./result/bin/)
  • 24.11 Release Notes (or backporting 23.11 and 24.05 Release notes)
    • (Package updates) Added a release notes entry if the change is major or breaking
    • (Module updates) Added a release notes entry if the change is significant
    • (Module addition) Added a release notes entry if adding a new NixOS module
  • Fits CONTRIBUTING.md.

Add a 👍 reaction to pull requests you find important.

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`.
@github-actions github-actions bot added 6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS 8.has: module (update) This PR changes an existing module in `nixos/` labels Nov 4, 2024
Comment on lines +367 to +370
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'.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why setting the type to nullOr bool when the default is true ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines 374 to 383
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).
'';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be clearer if it was a list of strings later joined with comma in implementation

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@ofborg ofborg bot added 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild 10.rebuild-linux: 1-10 labels Nov 5, 2024
services.postgresql.settings =
{
hba_file = "${pkgs.writeText "pg_hba.conf" cfg.authentication}";
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 "";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that ipv6 localhost ::1 and 127.0.0.1 on ipv4 only systems?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the PostgreSQL documentation:

The default value is localhost, which allows only local TCP/IP “loopback” connections to be made.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Contributor

@wolfgangwalther wolfgangwalther Nov 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

@@ -472,12 +485,16 @@ in
'';
}) 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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.enableTCPIP gives a deprecation warning.
  • if enableTCPIP is 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 touch listen_addresses.

Does that make sense?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS 8.has: module (update) This PR changes an existing module in `nixos/` 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild 10.rebuild-linux: 1-10
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants