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

postgresql: Move socket dir to /run/postgresql #57677

Merged
merged 4 commits into from Mar 24, 2019

Conversation

aszlig
Copy link
Member

@aszlig aszlig commented Mar 15, 2019

The default, which is /tmp, has a few issues associated with it:

One being that it makes it easy for users on the system to spoof a PostgreSQL server if it's not running, causing applications to connect to their provided sockets instead of just failing to connect.

Another one is that it makes sandboxing of PostgreSQL and other services unnecessarily difficult. This is already the case if only PrivateTmp is used in a systemd service, so in order for such a service to be able to connect to PostgreSQL, a bind mount needs to be done from /tmp to some other path, so the service can access it. This pretty much defeats the whole purpose of PrivateTmp.

We regularly run into issues with this in the past already (one example would be #24317) and with the new systemd-confinement mode upcoming in #57519, it makes it even more tedious to sandbox services.

I've tested this change against all the postgresql NixOS VM tests and they still succeed and I also grepped through the source tree to replace other occasions where we might have /tmp hardcoded. Luckily there were very few occasions.

The default, which is /tmp, has a few issues associated with it:

One being that it makes it easy for users on the system to spoof a
PostgreSQL server if it's not running, causing applications to connect
to their provided sockets instead of just failing to connect.

Another one is that it makes sandboxing of PostgreSQL and other services
unnecessarily difficult. This is already the case if only PrivateTmp is
used in a systemd service, so in order for such a service to be able to
connect to PostgreSQL, a bind mount needs to be done from /tmp to some
other path, so the service can access it. This pretty much defeats the
whole purpose of PrivateTmp.

We regularily run into issues with this in the past already (one example
would be NixOS#24317) and with the new
systemd-confinement mode upcoming in
NixOS#57519, it makes it even more
tedious to sandbox services.

I've tested this change against all the postgresql NixOS VM tests and
they still succeed and I also grepped through the source tree to replace
other occasions where we might have /tmp hardcoded. Luckily there were
very few occasions.

Signed-off-by: aszlig <aszlig@nix.build>
Cc: @ocharles, @thoughtpolice, @danbst
@danbst
Copy link
Contributor

danbst commented Mar 15, 2019

👍 would be awesome if it was changed to /var/run/postgresql, as Debian/Ubuntu use that path by default. See https://sources.debian.org/src/postgresql-11/11.2-2/debian/patches/51-default-sockets-in-var.patch/ , but I guess /run and /var/run are mounted to each other in every distribution, so not a big deal.

Also, add release notes, because it can make old psql not to connect to new postgresql via UNIX socket.

@edolstra
Copy link
Member

I would stick to /run instead of /var/run, since the latter is obsolete.

@aszlig
Copy link
Member Author

aszlig commented Mar 15, 2019

Also, add release notes, because it can make old psql not to connect to new postgresql via UNIX socket.

Yep, that's why I added that label, just wanted to see first whether there is any opposition.

Copy link
Member

@thoughtpolice thoughtpolice left a comment

Choose a reason for hiding this comment

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

LGTM, pending a release note addition as @danbst asked.

This is a backwards-incompatible change and while it won't probably
affect a whole lot of users, it makes sense to give them a heads-up
anyway.

Signed-off-by: aszlig <aszlig@nix.build>
@aszlig
Copy link
Member Author

aszlig commented Mar 16, 2019

@thoughtpolice, @danbst: Done.

@danbst
Copy link
Contributor

danbst commented Mar 16, 2019

BTW, this should be only for Linux system, right? Does darwin platform have /run? cc @basvandijk

@aszlig
Copy link
Member Author

aszlig commented Mar 16, 2019

@danbst: Hm, good catch, but even if OSX would have /run, it probably won't have /run/postgresql. So I'm going to make this Linux-only.

We only have /run on modern GNU/Linux systems and it's not necessarily
the case for Mac OS X or *BSD, so let's add the patch only if
stdenv.isLinux.

Thanks to @danbst for catching this.

Signed-off-by: aszlig <aszlig@nix.build>
@flokli
Copy link
Contributor

flokli commented Mar 16, 2019

@aszlig what's the socket path that PHP defaults to when connecting to a local postgresql?

Is there a way to tweak this one, similar to how I did for mysql in 5bb85cd?

@puckipedia
Copy link
Contributor

This PR seems to have broken the build of hydra, since it doesn't use the systemd service to launch postgresql and as such, it doesn't have a /run/postgresql to put the socket into...

@flokli
Copy link
Contributor

flokli commented Mar 29, 2019

can we tweak the hydra module to simply enable the postgresql module through services.postgresql in the localDB case?

@flokli
Copy link
Contributor

flokli commented Mar 29, 2019

wait, I don't get it - the hydra module already uses the postgresql module, and this one should set up /run/postgresql through RuntimeDirectory = "postgresql"

@puckipedia
Copy link
Contributor

no, that part's fine. It's during doCheck that it fails: https://hydra.nixos.org/build/91221682

@flokli
Copy link
Contributor

flokli commented Mar 29, 2019

@puckipedia we also can't just mkdir -p /run/postgresql in hydra's preCheck, as the sandbox doesn't allow to write to /run.

We however might be able to tweak hydra's tests/ to pass -k /tmp when instructing postgresql commands, didn't check.

@danbst
Copy link
Contributor

danbst commented Mar 29, 2019

Very unfortunate situation. I tend to revert this, and reapply when Nix does allow creating /run/postgresql. It can even be a build setup hook for postgresql, but Nix doesn't allow /run directory....

@aszlig what do you think?

@aszlig
Copy link
Member Author

aszlig commented Mar 29, 2019

@danbst: Nix doesn't need to allow this, because you can simply set PGHOST during preCheck to use a different socket path.

@danbst
Copy link
Contributor

danbst commented Mar 29, 2019

I just see it as regression - previously it was possible to do pg_ctl -D ... start and psql, but now you have specify socket directory both for server and client. It was useful...

Probably the best approach would be to patch postgres server to create socket in unix_socket_dir, and if it is not set, then create in /run/user/$(id -u), and if it doesn't exist, then use /run/postgresql. And implement same search logic for psql - first search in host argument/PGHOST, and if not specified, then in /run/user/$(id -u), if not found then search in /run/postgresql. This would still require Nix to allow /run directory and require setup hook for postgresql, to make things flawless.

@danbst
Copy link
Contributor

danbst commented Mar 29, 2019

Added a discussion topic here https://www.postgresql.org/message-id/CANZg%2Byd2OdqxM%3DHwnrkT-QecNMqLKNp%2BbGO_2SirJGznGK6h_w%40mail.gmail.com

Meanwhile, we just have to mention in release notes that pg_ctl should use custom socket dir (XDG_RUNTIME_DIR for users, /tmp for nix build environment) both for client and server.

danbst added a commit to danbst/hydra that referenced this pull request Mar 29, 2019
In NixOS/nixpkgs#57677 default postgresql socket directory was changed
to `/run/postgresql`, which doesn't exist (and can't be created) in
Nix build environment. We'll use /tmp as socket dir explicitly then.

Fixes build failure https://hydra.nixos.org/build/91221682

Cc @aszlig @edolstra
@flokli
Copy link
Contributor

flokli commented Mar 30, 2019

@danbst can we either revert this PR, or add a fetchpatch https://github.com/NixOS/hydra/pull/648/commits/4171ab4c4fd576c516dc03ba64d1c7945f769af0.patch to get Hydra to build again?

@flokli flokli mentioned this pull request Mar 31, 2019
10 tasks
@tilpner
Copy link
Member

tilpner commented May 12, 2019

I believe this might also fix a race condition between systemd-tmpfiles (caused by boot.cleanTmpDir) and postgres, that causes the socket to be deleted on boot.

@flokli
Copy link
Contributor

flokli commented May 12, 2019

@tilpner another reason to run systemd-tmpfiles as part of sysinit.target, before every other "regular" service ;-)

see #56265 (comment) and following.

cc @aanderse @erikarvstedt

@LnL7
Copy link
Member

LnL7 commented Jul 2, 2019

This breaks postgres outside of NixOS, this shouldn't be patched but handled in the nixos modules instead IMHO.

@danbst
Copy link
Contributor

danbst commented Jul 3, 2019

@LnL7 true, but outside NixOS it is easy fixable with -h /tmp in client CLI arg, and -k /tmp server CLI arg. I agree this is less convenient, but sharing sockets through /tmp isn't generally safe in multiuser setup.

@LnL7
Copy link
Member

LnL7 commented Jul 3, 2019

That doesn't matter, the default usage is broken because of non-standard behaviour. If this was a change in postgresql it would be another story.

@edolstra
Copy link
Member

edolstra commented Jul 3, 2019

While I think getting rid of sockets in /tmp is great (including /tmp/.X11-unix and /tmp/.ICE-unix while we're at it), it would be better if this were done upstream rather than in NixOS-specific patches.

@tilpner
Copy link
Member

tilpner commented Jul 3, 2019

So revert this PR and pass -k /run/... from the module?

@aanderse
Copy link
Member

aanderse commented Jul 3, 2019

Is anyone in favor of a socket option (potentially readOnly) so we can stop using so many magic strings all over NixOS modules every time we want to refer to a socket? Other modules like mysql would benefit from this as well. If so, let me know and I can whip something up.

@danbst
Copy link
Contributor

danbst commented Jul 3, 2019

@LnL7 unfortunately, it was already "non-standard", depending on what is "standard". Ubuntu (and Debian afaik) uses /var/run/postgresql as a de-factor standard socket path (same as we do now).

@edolstra Upstream doesn't work to improve this. https://www.postgresql.org/message-id/25758.1553906401%40sss.pgh.pa.us

@tilpner no, because PG consists of "server" and "client". And PG wants both to have same config parameter. So either both use same location, or they don't communicate each other.

@edolstra
Copy link
Member

edolstra commented Jul 3, 2019

@danbst Well, Tom Lane isn't wrong about "a Babel of servers and clients that can't talk to each other", as this issue shows...

Having said that, the fact that Ubuntu/Debian already use /run/postgresql is probably more relevant to us than what upstream does.

@LnL7
Copy link
Member

LnL7 commented Jul 3, 2019

Unlike the apt packages, nix won't ensure these defaults are functional however.

flokli added a commit to flokli/nixpkgs that referenced this pull request Nov 21, 2019
This seems to be mostly a pre - NixOS#57677 relict. As postgresql sockets now
are not in /tmp anymore, isolate /tmp.
@flokli flokli mentioned this pull request Nov 21, 2019
10 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

10 participants