Обсуждение: Thoughts on a "global" client configuration?
Hi all, I want to move towards a world where we have sslmode=verify-full by default. (And maybe gssencmode=disabled, for that matter.) But changing defaults is risky for established users. I'm exploring the idea of a global configuration for libpq -- /etc/libpqrc, if you will -- that contains all of our connection options and lets people override our decisions. So new users and established users don't have to agree on what's best for their use cases, and we can make improvements without fearing that we've locked some subset of users into their "last version" of Postgres because they can't upgrade. I started on a proof of concept and very quickly hit a fork. Do I 1) introduce a completely new config file, or 2) adapt pg_service.conf to this use case? If you're interested in that proof of concept, I'd like to know which option you'd like to see first. Some thoughts on each are in the appendix below, if you've got time, but a quick straw-poll response is helpful too. Thanks! --Jacob = Appendix: Design Thoughts = I wanted my PoC to show the following: - a two-tier approach, so that administrators can set system-wide defaults in /etc and users can set user-wide overrides for those defaults in their home directory - backwards and forwards compatibility (we don't ever break old libpqs, but new libpqs can add new options safely) That last part is why I initially preferred option (1). I didn't want to have to figure out the cross-compatibility implications of adapting pg_service.conf. I thought we could use installation-specific /etc/postgresql/<version>/libpqrc files and have them be completely separate from the longstanding service concept. Unfortunately that has at least one design mistake, which is that the user-tier config file can't have a version-specific prefix. So I either put the version into the name (gross), or else I have to solve cross-compatibility anyway. If I adapt pg_service.conf, I get the tier system for free. But I would still have to invent some sort of forwards compatibility mechanism, and my ideas so far involve adding non-INI syntax to the beginning of the file, where it would be ignored by existing versions. It puts us closer to ssh_config territory. Not sure how well that would go over; there are other projects parsing this.
On Mon, Oct 6, 2025 at 2:06 PM Jacob Champion <jacob.champion@enterprisedb.com> wrote: > I want to move towards a world where we have sslmode=verify-full by > default. (And maybe gssencmode=disabled, for that matter.) But > changing defaults is risky for established users. > > I'm exploring the idea of a global configuration for libpq -- > /etc/libpqrc, if you will -- that contains all of our connection > options and lets people override our decisions. So new users and > established users don't have to agree on what's best for their use > cases, and we can make improvements without fearing that we've locked > some subset of users into their "last version" of Postgres because > they can't upgrade. I think the down side of this kind of system is that it makes life harder for people who want to write code that works everywhere. You have to take into account the possibility that the configuration file could be overriding the compiled-in defaults and messing up your extension/tool/utility. This is why we tend to want to avoid behavior-changing GUCs on the server side -- anybody who writes an extension now has to be prepared for every possible value of each of those settings, and it's not a lot of fun. Now, all that said, I'm not sure how serious that class of problems is in this case. In the case of a client application, even if it's intended as a general tool that might be used by many people on many systems, in most cases, the author of that tool probably shouldn't have strong opinions about what details ought to be in the connection string vs. what details ought to be taken from a configuration file somewhere. But there are counterexamples, such as our regression tests. It seems like those tests are never likely to be stable under every possible choice of settings that you might put in that file, and eventually somebody who is running a buildfarm machine will end up with a file installed that breaks something, and that will be annoying. Maybe that can be avoided with an opt-out, like ignoresystemdefaults=1 or something, but it's worth noting that our current service-file system avoids this problem by being strictly opt-in, and I kind of wonder if we ought to stick with that. Because the alternative to what you're describing here is to just change the defaults in some new major release, and let the chips fall where they may. People will have to adjust, and one way they might do that is by using a service file to recover the old defaults. Whether that's better or worse than trying to ease the migration with some mechanism like the one you propose here is a judgement call, but I don't think anybody thinks that sslmode=prefer is actually a good default any more. I can imagine votes for disable, verify-full, and maybe require, but prefer seems obviously silly. To be honest, I think part of the problem here has to do with our choice of syntax. For HTTP, you just change the URL from http to https and it's one extra character. Decorating every connection string with sslmode=none (if the default is verify-full and you're running on a trusted network) or sslmode=verify-full (if the default is none and you're not running on a trusted network) feels bad, especially if you have to type those connection strings by hand with any frequency. I can't help wondering how much of the resistance in this area (including mine, FWIW) is subtly influenced by the feeling that it's going to be really annoying when the default isn't what you want in a particular case. But despite that, I still think we should ask ourselves whether it isn't better to endure a hard compatibility break. Maybe it isn't, and a config file as you propose is indeed a better option. But it doesn't solve the problem of deciding what the default ought to be in the absence of a config file, and it does potentially create some new problems. -- Robert Haas EDB: http://www.enterprisedb.com
On 2025-10-08 We 10:39 AM, Robert Haas wrote: > On Mon, Oct 6, 2025 at 2:06 PM Jacob Champion > <jacob.champion@enterprisedb.com> wrote: >> I want to move towards a world where we have sslmode=verify-full by >> default. (And maybe gssencmode=disabled, for that matter.) But >> changing defaults is risky for established users. >> >> I'm exploring the idea of a global configuration for libpq -- >> /etc/libpqrc, if you will -- that contains all of our connection >> options and lets people override our decisions. So new users and >> established users don't have to agree on what's best for their use >> cases, and we can make improvements without fearing that we've locked >> some subset of users into their "last version" of Postgres because >> they can't upgrade. > I think the down side of this kind of system is that it makes life > harder for people who want to write code that works everywhere. You > have to take into account the possibility that the configuration file > could be overriding the compiled-in defaults and messing up your > extension/tool/utility. This is why we tend to want to avoid > behavior-changing GUCs on the server side -- anybody who writes an > extension now has to be prepared for every possible value of each of > those settings, and it's not a lot of fun. > > Now, all that said, I'm not sure how serious that class of problems is > in this case. In the case of a client application, even if it's > intended as a general tool that might be used by many people on many > systems, in most cases, the author of that tool probably shouldn't > have strong opinions about what details ought to be in the connection > string vs. what details ought to be taken from a configuration file > somewhere. But there are counterexamples, such as our regression > tests. It seems like those tests are never likely to be stable under > every possible choice of settings that you might put in that file, and > eventually somebody who is running a buildfarm machine will end up > with a file installed that breaks something, and that will be > annoying. Maybe that can be avoided with an opt-out, like > ignoresystemdefaults=1 or something, but it's worth noting that our > current service-file system avoids this problem by being strictly > opt-in, and I kind of wonder if we ought to stick with that. > > Because the alternative to what you're describing here is to just > change the defaults in some new major release, and let the chips fall > where they may. People will have to adjust, and one way they might do > that is by using a service file to recover the old defaults. Whether > that's better or worse than trying to ease the migration with some > mechanism like the one you propose here is a judgement call, but I > don't think anybody thinks that sslmode=prefer is actually a good > default any more. I can imagine votes for disable, verify-full, and > maybe require, but prefer seems obviously silly. > > To be honest, I think part of the problem here has to do with our > choice of syntax. For HTTP, you just change the URL from http to https > and it's one extra character. Decorating every connection string with > sslmode=none (if the default is verify-full and you're running on a > trusted network) or sslmode=verify-full (if the default is none and > you're not running on a trusted network) feels bad, especially if you > have to type those connection strings by hand with any frequency. I > can't help wondering how much of the resistance in this area > (including mine, FWIW) is subtly influenced by the feeling that it's > going to be really annoying when the default isn't what you want in a > particular case. > > But despite that, I still think we should ask ourselves whether it > isn't better to endure a hard compatibility break. Maybe it isn't, and > a config file as you propose is indeed a better option. But it doesn't > solve the problem of deciding what the default ought to be in the > absence of a config file, and it does potentially create some new > problems. > There's a lot to this POV, and it's made worse by the unattractiveness of both of Jacob's options. If we set the default at verify-full (that would be my vote), someone can undo that for a particular installation by setting PGSSLMODE=prefer globally on their system, without our inventing a new config file / section. cheers andrew -- Andrew Dunstan EDB: https://www.enterprisedb.com
On Wed, Oct 8, 2025 at 7:39 AM Robert Haas <robertmhaas@gmail.com> wrote: > Thanks for the feedback! > I think the down side of this kind of system is that it makes life > harder for people who want to write code that works everywhere. You > have to take into account the possibility that the configuration file > could be overriding the compiled-in defaults and messing up your > extension/tool/utility. There's truth in that, I think, from a support standpoint. It's a knob which can be used to improve or destroy, and we could probably expect to see a transition period where some bug reports are closed with "why did you put that in your configuration?" I need to put more thought into the interaction with existing postgresql:// URIs, as well. > But there are counterexamples, such as our regression > tests. It seems like those tests are never likely to be stable under > every possible choice of settings that you might put in that file, and > eventually somebody who is running a buildfarm machine will end up > with a file installed that breaks something, and that will be > annoying. I think this is already solved. We have PGSYSCONFDIR, which allows tests to pull configuration from the temporary installation directory instead (and makes pg_service.conf relocatable for all of our utilities). Both of my proposed solutions can make use of that. > Maybe that can be avoided with an opt-out, like > ignoresystemdefaults=1 or something An opt-out would be pretty easy to add if needed, and it would align with clients like OpenSSH (`-F none`) and OpenLDAP (`LDAPNOINIT=1`). But I'd want to pin down what the use cases are before adding one. > Because the alternative to what you're describing here is to just > change the defaults in some new major release, and let the chips fall > where they may. People will have to adjust, and one way they might do > that is by using a service file to recover the old defaults. Whether > that's better or worse than trying to ease the migration with some > mechanism like the one you propose here is a judgement call, My vote is "worse", because while everyone seems to agree that `prefer` is bad, no one seems to agree on what the replacement should be. So momentum on the list dies quickly. And it's not just sslmode that's in the crosshairs; even if we somehow got to agreement on a compatibility break there, the exact same discussion is going to happen with the next one. In my opinion, there _is_ no "best for everyone". But we can lower the cost of a "bad" choice (for less common use cases), to make room to adjust defaults and make them "best for new users", or "best for the community", or etc. Distribution packagers could further adjust them to what's best for their communities, too. > To be honest, I think part of the problem here has to do with our > choice of syntax. For HTTP, you just change the URL from http to https > and it's one extra character. I think a syntax discussion focuses too much on sslmode in particular, and not enough on other settings that would also be good to ratchet forward at some point: min_protocol_version, sslnegotiation, ssl_min_protocol_version, sslrootcert, etc. The idea that all of these client configuration options belong inside our resource locators, as opposed to a file on disk somewhere, is... peculiar. It's nice that they _can_ be part of the syntax, I guess, but they shouldn't really _have_ to be. Thanks, --Jacob
On Wed, Oct 8, 2025 at 1:40 PM Andrew Dunstan <andrew@dunslane.net> wrote: > If we set the default at verify-full (that would be my vote), someone > can undo that for a particular installation by setting PGSSLMODE=prefer > globally on their system I don't think we should ever tell users to set PGSSLMODE=prefer. It's really sticky, and you can't know that third-party code won't defer to it instead of overriding it when they see it defined. A quick Github code search turns up a few people doing exactly that. If we make the change at the default level instead, we remain in control of the override priority, so users will be reverting to the previous behavior instead of introducing new untested behavior. --Jacob
On Wed, Oct 8, 2025 at 5:09 PM Jacob Champion <jacob.champion@enterprisedb.com> wrote: > > Because the alternative to what you're describing here is to just > > change the defaults in some new major release, and let the chips fall > > where they may. People will have to adjust, and one way they might do > > that is by using a service file to recover the old defaults. Whether > > that's better or worse than trying to ease the migration with some > > mechanism like the one you propose here is a judgement call, > > My vote is "worse", because while everyone seems to agree that > `prefer` is bad, no one seems to agree on what the replacement should > be. So momentum on the list dies quickly. And it's not just sslmode > that's in the crosshairs; even if we somehow got to agreement on a > compatibility break there, the exact same discussion is going to > happen with the next one. I'm never going to be a fan of the idea of changing libpq defaults with any frequency, no matter what configuration options we have. If we change those defaults with any regularity, I think it will cause a lot of problems for a lot of people. When there's not agreement on what to change, leaving things unchanged is often the best answer, because it at least has the virtue of not causing random breakage. I also think that Andrew raises a good point about the use of environment variables. That seems like it serves much the same purpose as a global configuration file, so I'm not sure we should have both. -- Robert Haas EDB: http://www.enterprisedb.com
On Thu, Oct 9, 2025 at 5:28 AM Robert Haas <robertmhaas@gmail.com> wrote: > I'm never going to be a fan of the idea of changing libpq defaults > with any frequency, no matter what configuration options we have. If > we change those defaults with any regularity, I think it will cause a > lot of problems for a lot of people. Agreed. (My proposal doesn't advocate for "regular" breakage.) > When there's not agreement on > what to change, leaving things unchanged is often the best answer, I think that's how we get into situations like "everyone hates sslmode=require but no one will change it." I'm looking to add a tool to make agreement easier in the first place. (Maybe there's a better tool than a configuration file? But I'd like to see what a file looks like, because I'm not familiar with any other network client that requires you to put every setting into the URI you use to contact the server. If you know of one please tell me so I can study it.) > because it at least has the virtue of not causing random breakage. I > also think that Andrew raises a good point about the use of > environment variables. That seems like it serves much the same purpose > as a global configuration file, so I'm not sure we should have both. I prefer simplicity, too, but environment variables for libpq mean "this is a trusted setting that you should prefer to the default, even if it's worse". That's not a good fit for the security-related settings I'm concerned with changing. --Jacob
On Thu, Oct 9, 2025 at 11:09 AM Jacob Champion <jacob.champion@enterprisedb.com> wrote: > Agreed. (My proposal doesn't advocate for "regular" breakage.) I understand that, but you mentioned a few different settings ... which could hypothetically turn into changing the default for 1 of them every year or two. > > When there's not agreement on > > what to change, leaving things unchanged is often the best answer, > > I think that's how we get into situations like "everyone hates > sslmode=require but no one will change it." I'm looking to add a tool > to make agreement easier in the first place. That's a fair goal, but I'm not sure that I agree that the tool you're proposing actually has that effect. > (Maybe there's a better tool than a configuration file? But I'd like > to see what a file looks like, because I'm not familiar with any other > network client that requires you to put every setting into the URI you > use to contact the server. If you know of one please tell me so I can > study it.) That's a fair complaint, but on the other hand, specifying the use or non-use of TLS in the URI is completely normal. What's abnormal about our system is that (1) we've got all of these extra levels that don't exist for, say, HTTP and (2) our syntax is quite verbose. > I prefer simplicity, too, but environment variables for libpq mean > "this is a trusted setting that you should prefer to the default, even > if it's worse". That's not a good fit for the security-related > settings I'm concerned with changing. Can you expand on this thought? I don't think I understand. What makes the environment variables "trusted values that you should prefer to the default" rather than just "values that we want to use in this context"? -- Robert Haas EDB: http://www.enterprisedb.com
On Thu, Oct 9, 2025 at 9:02 AM Robert Haas <robertmhaas@gmail.com> wrote:
> I understand that, but you mentioned a few different settings ...
> which could hypothetically turn into changing the default for 1 of
> them every year or two.
I think we should avoid equating "we can change it more frequently
than never" with "we will break everyone all the time". A hypothetical
configuration file does not absolve us of our need to choose defaults
wisely and maintain good interoperability for the community.
> > I think that's how we get into situations like "everyone hates
> > sslmode=require but no one will change it." I'm looking to add a tool
> > to make agreement easier in the first place.
>
> That's a fair goal, but I'm not sure that I agree that the tool you're
> proposing actually has that effect.
And that's fair too; I don't expect to drive consensus without a
concrete proposal in hand.
> > (Maybe there's a better tool than a configuration file? But I'd like
> > to see what a file looks like, because I'm not familiar with any other
> > network client that requires you to put every setting into the URI you
> > use to contact the server. If you know of one please tell me so I can
> > study it.)
>
> That's a fair complaint, but on the other hand, specifying the use or
> non-use of TLS in the URI is completely normal. What's abnormal about
> our system is that (1) we've got all of these extra levels that don't
> exist for, say, HTTP and (2) our syntax is quite verbose.
This again tries to collapse the problem down to sslmode. Look at
gssencmode, sslnegotiation, sslrootcert: all things which IMHO do not
belong in the query string of a URI. We've put connection settings and
application settings at the same level, and to me, that's the abnormal
thing about our system. (Similar problem to the _pq_.* protocol option
debates, actually.)
When you tell your browser to adjust the meaning of "HTTPS" -- whether
it's adding a new root cert to the trust store, disallowing TLS 1.1,
etc. -- you generally do that in a different place from the URL bar,
and the "clients" making use of HTTPS URLs do not know about it. Our
relative fragmentation (when compared to the Web) probably puts us
closer to the SSH use case than a browser use case, because we
absolutely need per-host connection settings. But SSH still lets you
ratchet up defaults across all hosts with its ssh_config.
(I'm actually tempted to double down on the SSH comparison and say
that its host-matching configuration model might be an even _better_
fit for us than our opt-in services model. Because it'd allow every
libpq client to delegate the question of "how do I connect to X" to
us, if they wanted, without having to drill a service name through the
stack. I don't know how far I want to go down that path, in the
absence of people asking for it.)
> > I prefer simplicity, too, but environment variables for libpq mean
> > "this is a trusted setting that you should prefer to the default, even
> > if it's worse". That's not a good fit for the security-related
> > settings I'm concerned with changing.
>
> Can you expand on this thought? I don't think I understand. What makes
> the environment variables "trusted values that you should prefer to
> the default" rather than just "values that we want to use in this
> context"?
Sure: In the context of this thread, I want the configuration file to
be able to act as a pressure release valve for admins who absolutely
cannot follow us forward into verify-full by default, by allowing them
to return to the previous behavior. But setting a new environment
variable isn't guaranteed to return to the previous behavior, because
it's reasonable for applications to defer to trusted envvars if
they're set. (Think `${PGSSLMODE:-verify-full}`.)
In the case of PGSSLMODE=prefer, I think that's especially dangerous:
it will always _look_ like things have returned to the previous state,
because everything will still be requesting SSL, but you may have
actively downgraded the security of the application.
The worst-case persona, in my mind, is a new sysadmin who's panicking
because of a libpq5 upgrade in production on Debian, say maybe through
an indirect package dependency, and something has started failing that
wasn't caught in testing. Downgrading means losing whatever package
brought in the dependency, and they're definitely not equipped to
audit all their code to make sure that PGSSLMODE=prefer isn't going to
do something horrible. I want to give that sysadmin a safe way out.
--Jacob
On Thu, Oct 9, 2025 at 4:21 PM Jacob Champion
<jacob.champion@enterprisedb.com> wrote:
> This again tries to collapse the problem down to sslmode. Look at
> gssencmode, sslnegotiation, sslrootcert: all things which IMHO do not
> belong in the query string of a URI. We've put connection settings and
> application settings at the same level, and to me, that's the abnormal
> thing about our system. (Similar problem to the _pq_.* protocol option
> debates, actually.)
That's a really interesting observation. I've always found it a bit
odd that we put things like sslca and sslrootcert into the connection
string, so I think you have a point, here. Not sure I agree about
sslnegotiation or gssencmode, though -- those seem more like sslmode,
which I would argue does belong in the connection string.
> Sure: In the context of this thread, I want the configuration file to
> be able to act as a pressure release valve for admins who absolutely
> cannot follow us forward into verify-full by default, by allowing them
> to return to the previous behavior. But setting a new environment
> variable isn't guaranteed to return to the previous behavior, because
> it's reasonable for applications to defer to trusted envvars if
> they're set. (Think `${PGSSLMODE:-verify-full}`.)
I think this is aiming at quite a narrow target.
> The worst-case persona, in my mind, is a new sysadmin who's panicking
> because of a libpq5 upgrade in production on Debian, say maybe through
> an indirect package dependency, and something has started failing that
> wasn't caught in testing. Downgrading means losing whatever package
> brought in the dependency, and they're definitely not equipped to
> audit all their code to make sure that PGSSLMODE=prefer isn't going to
> do something horrible. I want to give that sysadmin a safe way out.
I would argue that this is a sign that calling every version libpq5 no
matter how much we've changed the behavior is completely insane. This
scenario gets a whole lot better if installing a new release of
PostgreSQL that behaves differently doesn't magically change the
behavior of any existing releases that are already installed.
At the risk of repeating myself, I also think that we need to consider
the flip side of this scenario: some system administrator who thinks
they know better throws something into a system-wide configuration
file and breaks things for, say, PostgreSQL developers running the
regression tests, or applications running on the machine that assume a
certain system-wide configuration that in reality need not prevail
everywhere. I sometimes worry too much about non-problems at times,
and this might be one of those times, so it would be good to hear from
more people, but I think we need to be convinced not only that this
proposal has enough upside to be worth pursuing but also that the
downsides won't be too painful.
--
Robert Haas
EDB: http://www.enterprisedb.com
On Fri, Oct 10, 2025 at 6:24 AM Robert Haas <robertmhaas@gmail.com> wrote:
> That's a really interesting observation. I've always found it a bit
> odd that we put things like sslca and sslrootcert into the connection
> string, so I think you have a point, here. Not sure I agree about
> sslnegotiation or gssencmode, though -- those seem more like sslmode,
> which I would argue does belong in the connection string.
I could see gssencmode=require as a separate scheme. I still object to
its being a query string parameter; I don't think our current
acceptance of "gssencmode=require sslmode=require" is a particularly
good thing.
Putting sslnegotiation at the same level, though, feels like the
ancient distinction between "sldap" (STARTTLS) and "ldaps" (implicit
TLS), which IMO was a confusing historical mistake. And HTTP's version
of sslmode=prefer (opportunistic encryption, a dead experiment) was
still part of the `http:` scheme. Clients didn't opt into that via
URL; they configured it out of band.
> > Sure: In the context of this thread, I want the configuration file to
> > be able to act as a pressure release valve for admins who absolutely
> > cannot follow us forward into verify-full by default, by allowing them
> > to return to the previous behavior. But setting a new environment
> > variable isn't guaranteed to return to the previous behavior, because
> > it's reasonable for applications to defer to trusted envvars if
> > they're set. (Think `${PGSSLMODE:-verify-full}`.)
>
> I think this is aiming at quite a narrow target.
I agree. But it does exist in the wild [1], and sslmode is one of our
most important security settings. So I'm pretty worried about
unilaterally switching to a stronger default, without giving people a
tool to navigate it, if that would actually result in much weaker
security for some percentage of users.
> > The worst-case persona, in my mind, is a new sysadmin who's panicking
> > because of a libpq5 upgrade in production on Debian, say maybe through
> > an indirect package dependency, and something has started failing that
> > wasn't caught in testing. Downgrading means losing whatever package
> > brought in the dependency, and they're definitely not equipped to
> > audit all their code to make sure that PGSSLMODE=prefer isn't going to
> > do something horrible. I want to give that sysadmin a safe way out.
>
> I would argue that this is a sign that calling every version libpq5 no
> matter how much we've changed the behavior is completely insane.
I think SONAME is the wrong hammer to reach for. Network compatibility
is more subtle than link-time ABI. But this has come up before, so I
want to explore it a bit. My guesses:
If we were to update to libpq.so.6 because of this -- without any
actual ABI changes -- then many people downstream aren't going to know
that they're opting into the new behavior anyway. For a true opt-in,
we'd need to actively break people at build time (libpq6.so.0?). Then
those people downstream will want to ask what amazing changes they've
gotten in exchange for this ecosystem fracture, and I suspect they'd
be less than impressed if we said "it makes sslmode stronger by
default".
Our maintainers will probably be less than impressed as well, now that
they get to keep two separate side-by-side binaries that are 99.999%
identical. (And I think there are dependency diamond problems, unless
we version all our symbols, but I haven't paid attention to modern
practices there.)
Maybe the least impressed will be any middleware maintainers who get
their connection strings from a layer above them. We're asking them to
opt into the new behavior at build time, but they can't know whether
it's safe, either. For them, it's _still_ a user-level decision; all
we've done is kicked the can, and nothing has actually improved.
All this to say, I think libpq6 should happen because of an ABI change
relevant to the code that links against us, not because of a user
compatibility change.
> This
> scenario gets a whole lot better if installing a new release of
> PostgreSQL that behaves differently doesn't magically change the
> behavior of any existing releases that are already installed.
We could probably do that if we really wanted, without breaking
SONAME. Our server already has its extensions tell it what version
they were compiled against, and our client could similarly use macro
tricks. Or symbol versioning.
But, as above, I still don't think that an opt-in at build time can
fix the general problem. It only delays the pain until the next time a
dependent package is built.
> At the risk of repeating myself, I also think that we need to consider
> the flip side of this scenario: some system administrator who thinks
> they know better throws something into a system-wide configuration
> file and breaks things for, say, PostgreSQL developers running the
> regression tests
(this is solved, though)
> or applications running on the machine that assume a
> certain system-wide configuration that in reality need not prevail
> everywhere.
I agree we need to consider this scenario; I'm just finding it hard to
treat it as anything other than "don't do that then, highly-privileged
system administrator!" I assume we would tell them the same thing
today if they exported PGSERVICE globally and broke applications that
relied on environment variables.
> I sometimes worry too much about non-problems at times,
> and this might be one of those times, so it would be good to hear from
> more people, but I think we need to be convinced not only that this
> proposal has enough upside to be worth pursuing but also that the
> downsides won't be too painful.
Agreed.
Thanks,
--Jacob
[1] https://github.com/search?q=%22PGSSLMODE%3A-require%22&type=code
On Mon, Oct 13, 2025 at 3:57 PM Jacob Champion <jacob.champion@enterprisedb.com> wrote: > Putting sslnegotiation at the same level, though, feels like the > ancient distinction between "sldap" (STARTTLS) and "ldaps" (implicit > TLS), which IMO was a confusing historical mistake. And HTTP's version > of sslmode=prefer (opportunistic encryption, a dead experiment) was > still part of the `http:` scheme. Clients didn't opt into that via > URL; they configured it out of band. The distinction in my mind is that sslmode, gssencmode, and sslnegotiation define what we're doing on the wire, whereas parameters like sslcert just define where local resources are to be found. Granted, that influences what we're doing on the wire in a different way, but you can move the file and update the value of sslcert and get the same results, because the connection fundamentally doesn't care where its local files are found, whereas flipping sslnegotiation or sslmode is a fundamental alteration to what the connection tries to do. How do you see it? > > I think this is aiming at quite a narrow target. > > I agree. But it does exist in the wild [1], and sslmode is one of our > most important security settings. So I'm pretty worried about > unilaterally switching to a stronger default, without giving people a > tool to navigate it, if that would actually result in much weaker > security for some percentage of users. I'm unconvinced that this is worth worrying about. I am a little surprised to see the number of hits that your search found, but I think people will (and should) update their code. > > I would argue that this is a sign that calling every version libpq5 no > > matter how much we've changed the behavior is completely insane. > > I think SONAME is the wrong hammer to reach for. Network compatibility > is more subtle than link-time ABI. But this has come up before, so I > want to explore it a bit. My guesses: > > If we were to update to libpq.so.6 because of this -- without any > actual ABI changes -- then many people downstream aren't going to know > that they're opting into the new behavior anyway. For a true opt-in, > we'd need to actively break people at build time (libpq6.so.0?). Then > those people downstream will want to ask what amazing changes they've > gotten in exchange for this ecosystem fracture, and I suspect they'd > be less than impressed if we said "it makes sslmode stronger by > default". My theory is that they'll be even less impressed if they try to use a supposedly-compatible library and it breaks a bunch of stuff, but I wonder what Christoph Berg (cc'd) thinks. -- Robert Haas EDB: http://www.enterprisedb.com
Re: Robert Haas > My theory is that they'll be even less impressed if they try to use a > supposedly-compatible library and it breaks a bunch of stuff, but I > wonder what Christoph Berg (cc'd) thinks. It would also hinder adoption of PG in more places. There are currently thousands of software products that link to libpq in some form, and it would take several years to have them all fixed if ABI/API compatibility were broken. Chasing the long tail there is hard; we get to witness that every year with upstreams that aren't compatible with PG18 yet. For some extensions, I'm still waiting to get my PG17 (or PG16!) patches merged. Christoph
On Mon, Oct 13, 2025 at 4:22 PM Christoph Berg <myon@debian.org> wrote: > Re: Robert Haas > > My theory is that they'll be even less impressed if they try to use a > > supposedly-compatible library and it breaks a bunch of stuff, but I > > wonder what Christoph Berg (cc'd) thinks. > > It would also hinder adoption of PG in more places. There are > currently thousands of software products that link to libpq in some > form, and it would take several years to have them all fixed if > ABI/API compatibility were broken. Chasing the long tail there is > hard; we get to witness that every year with upstreams that aren't > compatible with PG18 yet. For some extensions, I'm still waiting to > get my PG17 (or PG16!) patches merged. So you support calling it libpq.so.5 forever, no matter how much we change? -- Robert Haas EDB: http://www.enterprisedb.com
Re: Robert Haas > So you support calling it libpq.so.5 forever, no matter how much we change? I would say SONAME/ABI/API breakages are not a tool to promote better SSL settings. If we want to move to sslmode=verify-full by default, we should just do that. I don't see why adding extra ABI/API pain would make that transition any better for users. We can move to libpq6 if there are technical reasons, but the general pain will be long-lasting until the whole world has caught up. (Debian etc can switch pretty easily, but there's a gazillion of third-party things.) Christoph
On Mon, Oct 13, 2025 at 4:30 PM Christoph Berg <myon@debian.org> wrote: > Re: Robert Haas > > So you support calling it libpq.so.5 forever, no matter how much we change? > > I would say SONAME/ABI/API breakages are not a tool to promote better > SSL settings. If we want to move to sslmode=verify-full by default, we > should just do that. I don't see why adding extra ABI/API pain would > make that transition any better for users. > > We can move to libpq6 if there are technical reasons, but the general > pain will be long-lasting until the whole world has caught up. (Debian > etc can switch pretty easily, but there's a gazillion of third-party > things.) OK, good to know. I somehow can't get over how crazy it seems to hadcode the version to 5 forever, but, eh, [ old man yells at cloud emoji here ]. -- Robert Haas EDB: http://www.enterprisedb.com
On Mon, Oct 13, 2025 at 1:15 PM Robert Haas <robertmhaas@gmail.com> wrote: > The distinction in my mind is that sslmode, gssencmode, and > sslnegotiation define what we're doing on the wire, whereas parameters > like sslcert just define where local resources are to be found. > Granted, that influences what we're doing on the wire in a different > way, but you can move the file and update the value of sslcert and get > the same results, because the connection fundamentally doesn't care > where its local files are found, whereas flipping sslnegotiation or > sslmode is a fundamental alteration to what the connection tries to > do. How do you see it? I agree with your bucketing of wire-vs-non-wire parameters, but to me, that's not really the dividing line for what belongs in an "ideal" connection string. It's just an indication that something is off -- that there is no dividing line right now, and that's strange. I've been trying to frame this in terms of our URI structure, mostly because it highlights how odd our setup is. It's true that you don't type your client certificate path into your browser's location bar (it's not on the wire), but it's also true that you don't put the minimum TLS version there, or the OCSP fallback behavior (both on the wire). The latter two are still out-of-band decisions, separate from the name of the resource itself, even though they directly affect whether a browser can connect at all to certain hosts. That goes back to what I was saying earlier about ssh_config, and how its style might have been a better match for some of our use cases. Host matching lets the user say "oh yeah, that server is weird, connect this way" without forcing every application that uses SSH to understand that information. > I'm unconvinced that this is worth worrying about. I am a little > surprised to see the number of hits that your search found, but I > think people will (and should) update their code. I think one of the fundamental issues with sslmode=prefer is that the affected people are unlikely to notice they should update their code. SSL will continue to be used. Nothing will break, but active attacks will be silently enabled. And if someone affected by this comes to a list to report and/or complain, I think they're likely to be greeted by a chorus of "why would an informed sysadmin ever define PGSSLMODE=prefer? so insecure, PEBKAC, skill issue". I get that I'm coming at this from the paranoid-security-person side of things, but I feel like the ecosystem effects of officially recommending a bad PGSSLMODE as a compatibility hack are not being given the same scrutiny as the ecosystem effects of adding a configuration file. > My theory is that they'll be even less impressed if they try to use a > supposedly-compatible library and it breaks a bunch of stuff I agree with that, but also that's why I started this thread. I think both options (keeping sslmode=prefer by default, and unilaterally changing to something stronger) are untenable, and I'm trying to cut the knot. Some library I was looking at recently (can't remember which, or I'd link it) had an interesting approach to compatibility breaks. It 1) warned about the break in version X, if you relied on the behavior, 2) broke behavior by default in version X+1, but gave you the option to return to the prior functionality for a single release, and then 3) removed the deprecated behavior in version X+2. I don't think that exact plan would work for us, but if our back branches had client config files, you might imagine a world where we backported warnings for really important changes. "You're relying on default behavior that is about to change in PG30, and you need to explicitly opt into the old behavior now if you don't want to break when you upgrade." (Proof-of-concept on the way soon.) Thanks, --Jacob
On 08.10.25 16:39, Robert Haas wrote: > To be honest, I think part of the problem here has to do with our > choice of syntax. For HTTP, you just change the URL from http to https > and it's one extra character. Decorating every connection string with > sslmode=none (if the default is verify-full and you're running on a > trusted network) or sslmode=verify-full (if the default is none and > you're not running on a trusted network) feels bad, especially if you > have to type those connection strings by hand with any frequency. But even a browser has a default setting for which variant to use when you type in a domain name without a scheme. And in most cases, that default was changed at some point during the last 20 years.
On 06.10.25 20:05, Jacob Champion wrote: > I started on a proof of concept and very quickly hit a fork. Do I > 1) introduce a completely new config file, or > 2) adapt pg_service.conf to this use case? I've been thinking about this kind of thing for a long time, and my intuition has always been to have some kind of [default] section in pg_service.conf. That would probably be relatively easy. But: > - backwards and forwards compatibility (we don't ever break old > libpqs, but new libpqs can add new options safely) It might be worth elaborating exactly how this would be solved. If I look through my dotfiles history, this kind of thing has been a perennial problem. I don't have any specific ideas right now -- other than perhaps "ignore unknown parameters", which is surely not without problems. Depending on what we'd settle on here, that might inform whether it's feasible to stick this into pg_service.conf or whether it needs to be a separate thing.
On Wed, 15 Oct 2025 at 15:20, Peter Eisentraut <peter@eisentraut.org> wrote:
On 06.10.25 20:05, Jacob Champion wrote:
> I started on a proof of concept and very quickly hit a fork. Do I
> 1) introduce a completely new config file, or
> 2) adapt pg_service.conf to this use case?
I've been thinking about this kind of thing for a long time, and my
intuition has always been to have some kind of [default] section in
pg_service.conf. That would probably be relatively easy.
Maybe have a way to specify one or more "base" configurations for each service?
Something like (except please don't use the "extends" keyword, I've done enough Java already; pick some punctuation instead):
[default]
sslmode=require
[dev]
[service1] extends default
host=postgres.example.com
user=appuser
[service2] extends default
user=otherappuser
[service1-dev] extends default, dev
user=appuser
I don't know how big a deal it is that this is no longer an "INI" file.
On Wed, Oct 15, 2025 at 12:35 PM Isaac Morland <isaac.morland@gmail.com> wrote: > Maybe have a way to specify one or more "base" configurations for each service? For the use case I have in mind, my intention is that you shouldn't have to use a service at all to get these defaults to apply. > [service1] extends default > host=postgres.example.com > user=appuser Nested services is interesting as well. I don't think it solves my use case, because of a very subtle difference between defaults and services (I intend to go into more detail in the other email I'm typing up now). > I don't know how big a deal it is that this is no longer an "INI" file. We would almost certainly break some libpq-compatible software if we added new syntax. I don't know if that's a feature or a bug yet, but I do think it's avoidable, so I'm going to try to avoid it for now. Needs more thought. Thanks! --Jacob
On Wed, Oct 15, 2025 at 12:20 PM Peter Eisentraut <peter@eisentraut.org> wrote: > > - backwards and forwards compatibility (we don't ever break old > > libpqs, but new libpqs can add new options safely) > > It might be worth elaborating exactly how this would be solved. If I > look through my dotfiles history, this kind of thing has been a > perennial problem. I don't have any specific ideas right now -- other > than perhaps "ignore unknown parameters", which is surely not without > problems. Depending on what we'd settle on here, that might inform > whether it's feasible to stick this into pg_service.conf or whether it > needs to be a separate thing. Good timing. Here's a patchset that experiments with putting it all into pg_service.conf. = Roadmap = Patches 0001-0003 are small tweaks to make my life easier. I can pull them out separately if there's interest. 0004 implements a defaults section: [my-default-section] +=defaults sslmode=verify-full gssencmode=disable [other-service] ... 0005 implements forwards compatibility by marking specific defaults as ignorable: [default] +=defaults require_auth=scram-sha-256 channel_binding=require ?incredible_scram_feature=require 0006 implements PGNODEFAULTS to allow our test suites (and anything else) to turn off the new handling. This prevents a broken ~/.pg_service.conf from interfering with our tests. (A different way of solving that could be to point PGSERVICE to a blank file. I kind of liked the "turn it off" switch, though.) = Thoughts = I wanted to keep INI compatibility. I found a few clients that run pg_service.conf through a generic INI parser, which seems like an entirely reasonable thing to do. Going back to my earlier argument against environment variables, if we make people use this tool to get themselves out of a compatibility problem we introduce, and it then causes other existing parts of the Postgres ecosystem to break, I wouldn't feel great about that. (I could see an argument that breaking those clients would make it obvious that they can't apply the new defaults section correctly. But our old libpqs won't be able to apply the defaults section either, and we're presumably not going to accept breaking old libpqs.) I wanted to avoid stomping on existing service names. I could have gone the Windows route and generated a GUID or something, but instead I've allowed the user to choose any name they want for this section. They then mark it with the (maybe-too-cute?) magic string of "+=defaults", which 1) will cause earlier libpqs to fail if they accidentally try to select the section as a service, 2) is INI parseable (the key is "+"), and 3) kind of suggests what the section is meant to do: add these settings to the defaults. I've tried to avoid too much unbearable confusion by requiring that a defaults service be at the top of the file and have its marker first in the section. One subtlety that I hadn't considered was how the user and system files interact with one another. I want user defaults to override system defaults, if they are in conflict. But user services completely replace system services of the same name, so the code needs to keep the two behaviors separate. An emergent feature popped out of this while I was implementing the tests. You can now choose a default service, and the effect is that any settings listed there take precedence over the envvars. "Superdefaults." This is fragile, though -- setting a different service gets rid of those rather than merging them -- and I was idly wondering if that was something that could/should be made into its own first-class concept. The ability to ignore specific options was inspired by the ability of an ssh_config to IgnoreUnknown. Maybe you don't care if a nice-to-have option is ignored by older libpqs, but you maybe want to fail immediately if some security-critical option can't be honored (or if you just made a typo), and I think we should assume the latter. This feature would let you mark them accordingly. I'm not sure if all this is better than an architecture where the defaults and services are contained in different files. Since the syntax and behavior of the two types of sections is explicitly different, maybe combining them would be unnecessarily confusing for users? --Jacob
Вложения
- 0001-libpq-Simplify-newline-handling-in-t-006_service.patch
- 0002-libpq-Pin-sectionless-keyword-behavior-in-pg_service.patch
- 0003-libpq-Improve-unknown-keyword-message-for-pg_service.patch
- 0004-WIP-pg_service-implement-defaults-section.patch
- 0005-WIP-pg_service-implement-forwards-compatibility.patch
- 0006-WIP-pg_service-implement-PGNODEFAULTS.patch
> On Oct 16, 2025, at 07:19, Jacob Champion <jacob.champion@enterprisedb.com> wrote: > > I wanted to avoid stomping on existing service names. I could have > gone the Windows route and generated a GUID or something, but instead > I've allowed the user to choose any name they want for this section. > They then mark it with the (maybe-too-cute?) magic string of > "+=defaults", which > 1) will cause earlier libpqs to fail if they accidentally try to > select the section as a service, > 2) is INI parseable (the key is "+"), and > 3) kind of suggests what the section is meant to do: add these > settings to the defaults. I don’t have a strong option on the direction, so I was watching the discussion and waiting for the patch. Before reviewing the patch, I have a comment to the design. I am not convinced that the “=+defaults” approach is the best design. 1) Not self-documenting. Without documentation, hard to guess what it is exactly for. 2) Actually “default = true” will also causes earlier libpq to fail, but “default = true” is easier to understand. Something I want to clarify are: * If there are multiple default sections present, how will them be handled? * Do we want to support specifying a default section? For example: ``` [test_default] default = true X = Y … [prod_default] default = true X = Z … [service_a] default = test_default [service_b] default = prod_default ``` Best regards, Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/
On Wed, Oct 15, 2025 at 7:16 PM Chao Li <li.evan.chao@gmail.com> wrote: > I am not convinced that the “=+defaults” approach is the best design. > > 1) Not self-documenting. Without documentation, hard to guess what it is exactly for. > 2) Actually “default = true” will also causes earlier libpq to fail, but “default = true” is easier to understand. Yeah, I can talk a bit about my personal flip-flopping there. - I started with a "default=true" marker, and decided I didn't want to camp on something that could plausibly be a connection string option. - I switched to "!default=true!" and decided it was ugly. - Once I realized the subtlety of the merge vs replace behavior compared to services, I tried "+=", to try to evoke the merge idea. *If* we decide to support a configuration file, *and* we decide to choose the section+marker approach, I think the choice of marker would be a good thing to bikeshed. Something fairly self-documenting would be ideal. But the first two "ifs" are far from decided. > Something I want to clarify are: > > * If there are multiple default sections present, how will them be handled? This patchset rejects that (if I've implemented it correctly). One default section only. > * Do we want to support specifying a default section? This is similar to Isaac's service nesting proposal. I'm not excited about mixing the defaults section behavior with the service sections, because I think it would confuse users about which options take precedence when. At the moment, defaults defer to envvars, which defer to services. But a "default selection" feature doesn't "look" like it works that way, at least not to my eyes. And I'm not sure if users would ever want the ability to switch defaults per service (as opposed to just putting those options into the service). Isaac's nested services seem like a better way to go if organization and deduplication is the goal. Thanks! --Jacob
On 16.10.25 01:19, Jacob Champion wrote: > I'm not sure if all this is better than an architecture where the > defaults and services are contained in different files. Since the > syntax and behavior of the two types of sections is explicitly > different, maybe combining them would be unnecessarily confusing for > users? After studying this a bit more and reading your account, I'm now coming over to the side that a libpq defaults configuration file should be separate from the existing services file mechanism. First, just to have a clear naming. If someone wants to know where to set the default SSL version, an answer like /etc/postgresql/pg_service.conf doesn't make much sense. The two mechanisms have different audiences. Currently, a pg_service.conf entry is necessarily made in conjunction with some application program using it. I suspect a system-wide pg_service.conf file doesn't actually get much use. Conversely, a libpq defaults file is more the concern of the OS admin, and per-user configuration will be less common. The hierarchy of the settings from different sources becomes very complicated, as you already alluded to. A user-configured service will completely override a system-configured service, which makes some sense, but libpq defaults should merge on a per-parameter level. Also, I would expect that environment variables override libpq defaults, but with the services, it's the other way around. Consolidating all of that into one mechanism would be very confusing. If we have separate mechanisms with a clear hierarchy, like 0) compiled-in, 1) defaults file, 2) environment vars, 3) services, 4) explicit parameters, then it's clearer. And then you could also have different policies in the two kinds of files, like ignoring unknown settings in the defaults file, if that kind of thing were desired. We could still have the defaults file and the services file use the same format and parser, if that helps. On the question of ignoring unknown settings, or related compatibility questions. The core use case is altering the compiled-in defaults and giving users a way to effectively revert that. So ideally in most cases it won't get used at all. And normally you won't change the defaults of settings that were only recently introduced. So you might want to change the default of sslmode, but all versions in the field support that. Hypothetically, you might want to change the default of sslnegotiation someday, but if not all libpq versions in the field support that setting, then it's probably also too soon to change the default. So perhaps this problem regulates itself. Also, generally, you will only have one libpq version per system, so supporting many versions concurrently might not be needed. To that end, it would be important not to get this facility confused with a user preferences facility, or a per-remote-host configuration (like ssh_config). Maybe people want that too, but it should be designed differently. In fact, do we even need a per-user version of this? Maybe take the OpenSSL approach: There is only a global config file, and you can supply a different one with an environment variable. That should satisfy those who want different defaults for their local psql use. But for most other uses, the relevant user is some service account, for which dot files are always awkward anyway.
On Mon, Oct 13, 2025 at 10:22:53PM +0200, Christoph Berg wrote: > Re: Robert Haas > > My theory is that they'll be even less impressed if they try to use a > > supposedly-compatible library and it breaks a bunch of stuff, but I > > wonder what Christoph Berg (cc'd) thinks. > > It would also hinder adoption of PG in more places. There are > currently thousands of software products that link to libpq in some > form, and it would take several years to have them all fixed if > ABI/API compatibility were broken. Chasing the long tail there is > hard; we get to witness that every year with upstreams that aren't > compatible with PG18 yet. For some extensions, I'm still waiting to > get my PG17 (or PG16!) patches merged. The fact is is called libpq --- Post-QUEL, and not libpg, supports your analysis. ;-) -- Bruce Momjian <bruce@momjian.us> https://momjian.us EDB https://enterprisedb.com Do not let urgent matters crowd out time for investment in the future.