Thread: Starting a PostgreSQL server on a dynamic port (parameter port=0)

Starting a PostgreSQL server on a dynamic port (parameter port=0)

From
a.mitrokhin@postgrespro.ru
Date:
Hello.


Postgres does not allow starting the server with port=0, which prevents
it from obtaining an arbitrary free port from the kernel.


~$ LANG=C pg_ctl -D data -o "-c port=0" start
2025-07-10 05:27:02.785 GMT [702503] FATAL:  0 is outside the valid
range for parameter "port" (1 .. 65535)


This makes it unreliable to start the server in my tests without the
risk of port conflicts with already running programs, unless resorting
to an unreliable and race-condition-prone procedure of reserving ports
in advance.


Could you please fix this?



On Thu, 10 Jul 2025 at 12:15, <a.mitrokhin@postgrespro.ru> wrote:
>
> Hello.
>
>
> Postgres does not allow starting the server with port=0, which prevents
> it from obtaining an arbitrary free port from the kernel.
>
>
> ~$ LANG=C pg_ctl -D data -o "-c port=0" start
> 2025-07-10 05:27:02.785 GMT [702503] FATAL:  0 is outside the valid
> range for parameter "port" (1 .. 65535)
>
>
> This makes it unreliable to start the server in my tests without the
> risk of port conflicts with already running programs, unless resorting
> to an unreliable and race-condition-prone procedure of reserving ports
> in advance.
>
>
> Could you please fix this?


Regression tests somehow solve this problem without any patch, so why
this should be fixed?

-- 
Best regards,
Kirill Reshke



Re: Starting a PostgreSQL server on a dynamic port (parameter port=0)

From
a.mitrokhin@postgrespro.ru
Date:
Kirill Reshke писал(а) 2025-07-10 14:46:
> On Thu, 10 Jul 2025 at 12:15, <a.mitrokhin@postgrespro.ru> wrote:
>> 
>> Hello.
>> 
>> 
>> Postgres does not allow starting the server with port=0, which 
>> prevents
>> it from obtaining an arbitrary free port from the kernel.
>> 
>> 
>> ~$ LANG=C pg_ctl -D data -o "-c port=0" start
>> 2025-07-10 05:27:02.785 GMT [702503] FATAL:  0 is outside the valid
>> range for parameter "port" (1 .. 65535)
>> 
>> 
>> This makes it unreliable to start the server in my tests without the
>> risk of port conflicts with already running programs, unless resorting
>> to an unreliable and race-condition-prone procedure of reserving ports
>> in advance.
>> 
>> 
>> Could you please fix this?
> 
> 
> Regression tests somehow solve this problem without any patch, so why
> this should be fixed?

This has nothing to do with Postgres regression tests. The issue is
the practical benefit of using a dynamic port, which we're depriving
ourselves of.

If you're not interested in this behavior, you'll never use it. But
there are cases where it can be very convenient. Why artificially
restrict functionality that is simple, doesn't conflict with anything,
and has no negative side effects?



On Thu, 2025-07-10 at 15:29 +0700, a.mitrokhin@postgrespro.ru wrote:
> > > Postgres does not allow starting the server with port=0, which prevents
> > > it from obtaining an arbitrary free port from the kernel.
>
> This has nothing to do with Postgres regression tests. The issue is
> the practical benefit of using a dynamic port, which we're depriving
> ourselves of.
>
> If you're not interested in this behavior, you'll never use it. But
> there are cases where it can be very convenient. Why artificially
> restrict functionality that is simple, doesn't conflict with anything,
> and has no negative side effects?

I have never wished for such a feature, and I can see negative side
effects.  If the server listens on a different port than you expect,
it is easier to connect to the wrong server by mistake.

Yours,
Laurenz Albe




On 10.07.25 10:53, Laurenz Albe wrote:
> I have never wished for such a feature, and I can see negative side
> effects.  If the server listens on a different port than you expect,
> it is easier to connect to the wrong server by mistake.

Moreover, there's a risk that postgres could potentially hijack the port
of an application that's not currently running, but has a fixed port
configuration assigned to it. This could, in turn, prevent the
application from starting up successfully.

I can understand why it might be attractive for some scenarios, but the
risks and consequences could outweigh the benefits.

Best, Jim



Re: Starting a PostgreSQL server on a dynamic port (parameter port=0)

From
"David G. Johnston"
Date:
On Thursday, July 10, 2025, <a.mitrokhin@postgrespro.ru> wrote:

If you're not interested in this behavior, you'll never use it. But
there are cases where it can be very convenient. Why artificially
restrict functionality that is simple, doesn't conflict with anything,
and has no negative side effects?

Then figure out how to do it on all the OSes we support and propose a patch.  Maybe it’s simple enough to include.  Maybe not.  If it is simple e on an OS one cares about a shell script around pg_ctl is a simple way to leverage it so it’s still a fairly low priority to add into core.

David J.

Re: Starting a PostgreSQL server on a dynamic port (parameter port=0)

From
"Euler Taveira"
Date:
On Thu, Jul 10, 2025, at 10:21 AM, David G. Johnston wrote:
> On Thursday, July 10, 2025, <a.mitrokhin@postgrespro.ru> wrote:
>>
>> If you're not interested in this behavior, you'll never use it. But
>> there are cases where it can be very convenient. Why artificially
>> restrict functionality that is simple, doesn't conflict with anything,
>> and has no negative side effects?
>
> Then figure out how to do it on all the OSes we support and propose a
> patch.  Maybe it’s simple enough to include.  Maybe not.  If it is
> simple e on an OS one cares about a shell script around pg_ctl is a
> simple way to leverage it so it’s still a fairly low priority to add
> into core.
>

I don't think it is just a matter of operating system supports it. Linux and
Windows supports port 0 but FreeBSD does not.

The RFC 63335 [1] that is referred in the IANA document [2] says:

Reserved: Reserved port numbers are not available for regular
assignment; they are "assigned to IANA" for special purposes.
Reserved port numbers include values at the edges of each range,
e.g., 0, 1023, 1024, etc., which may be used to extend these
ranges or the overall port number space in the future.

Some operating systems like Linux and Windows decided to use it to
automatically assign a free port. I don't think it is a good idea for
production. The main reason is security, we had some reports[3][4] in the past.
Some services like apache and nginx that don't allow you to use port 0.

IMO it could be supported for development purposes. However, the test suite
(pg_regress and TAP tests) already has some logic to assign a port from the
private range (49152-65535) and is capable of assigning another port if the
current port is in use. Maybe the OP has a case that the current approach is
not ideal.

[1] https://www.rfc-editor.org/rfc/rfc6335.html
[2] https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml
[3] https://medium.com/@ian.barwise/socket-programming-the-bizarre-tcp-ip-port-0-saga-b5c302d04299
[4] https://nvd.nist.gov/vuln/detail/cve-2023-27567#:~:text=Description,rule%20can%20crash%20the%20kernel.


--
Euler Taveira
EDB   https://www.enterprisedb.com/



a.mitrokhin@postgrespro.ru writes:
> Postgres does not allow starting the server with port=0, which prevents
> it from obtaining an arbitrary free port from the kernel.

Others have already pointed out problems with this proposal, but
the one I see is: what do you do next?  How will clients know
what port to connect to?

The only way I could see to do that is to read the port out of
postmaster.pid, which works only for clients running as the same
userid as the postmaster, which is surely an unfit-for-production
approach.

If you're only interested in this for testing purposes, we
already have perfectly good free-port-selection algorithms
embedded in our test harnesses.  For that matter, in a test
environment it's usually best (most secure) to use a Unix
socket in a private directory, in which case there is little
need to worry about port number conflicts in the first place.

            regards, tom lane



Re: Starting a PostgreSQL server on a dynamic port (parameter port=0)

From
a.mitrokhin@postgrespro.ru
Date:
Tom Lane писал(а) 2025-07-10 21:41:
> a.mitrokhin@postgrespro.ru writes:
>> Postgres does not allow starting the server with port=0, which
>> prevents
>> it from obtaining an arbitrary free port from the kernel.
>
> Others have already pointed out problems with this proposal, but
> the one I see is: what do you do next?  How will clients know
> what port to connect to?
>
> The only way I could see to do that is to read the port out of
> postmaster.pid, which works only for clients running as the same
> userid as the postmaster, which is surely an unfit-for-production
> approach.
>
> If you're only interested in this for testing purposes, we
> already have perfectly good free-port-selection algorithms
> embedded in our test harnesses.  For that matter, in a test
> environment it's usually best (most secure) to use a Unix
> socket in a private directory, in which case there is little
> need to worry about port number conflicts in the first place.
>

I looked at get_free_port(). Here's how it works:
     - It selects a port from the range 10200..32767,
     - Checks that the port is not in use, and
     - Verifies there’s no file created for that reserved port.

There’s a race condition between bind() and the actual process
launch, and it’s not handled (I don’t think there’s a simple
solution with this approach). The port could be taken by any
connection in the system or by another developer running their
own tests on the same host (and they likely have their own
directory with port reservation files).

It would be much simpler to just start the server and use the
port assigned by the OS kernel. The vast majority of test
scenarios would work fine this way (I believe).