By default, a newly installed PostgreSQL server accepts connections only from the local machine. To allow a remote client to connect, configure both the network listener and host-based authentication:

  1. Configure PostgreSQL to listen for remote connections.
  2. Add a pg_hba.conf rule that permits the remote client to authenticate.

Configure PostgreSQL to Listen for Remote Connections

In this example, the PostgreSQL server is named pg-server.example.test and has the documentation address 203.0.113.10. The remote client has the documentation address 203.0.113.25.

When a remote client tries to connect before the listener is configured, the connection is refused:

$ psql -h pg-server.example.test -p 5432 -U postgres -d postgres
psql: error: connection to server at "pg-server.example.test" (203.0.113.10), port 5432 failed: Connection refused
Is the server running on that host and accepting TCP/IP connections?

By default, PostgreSQL listens only on loopback addresses. Confirm the listening addresses on the server:

# ss -ltnp | grep 5432
LISTEN 0 200 127.0.0.1:5432 0.0.0.0:* users:(("postgres",pid=2039980,fd=8))
LISTEN 0 200 [::1]:5432 [::]:* users:(("postgres",pid=2039980,fd=7))

The first address in each line is the local listening address. 127.0.0.1 and ::1 are loopback addresses, so remote clients cannot reach them. 

The server’s postmaster.pid file also records the listen address:

# cat /u01/pg/postmaster.pid
2350229
/u01/pg
1791443245
5432
/run/postgresql
localhost
131 163886
ready

The localhost entry confirms that PostgreSQL was started with a localhost-only listen address. 

This behavior is caused by the following setting in postgresql.conf:

# grep listen /u01/pg/postgresql.conf
#listen_addresses = 'localhost' # what IP address(es) to listen on;

The setting is commented out, so PostgreSQL uses localhost by default. Uncomment it and set it to the server’s LAN address if PostgreSQL should listen on that interface only, or to * if it should listen on all local interfaces:

listen_addresses = '*'

Because listen_addresses is applied at server startup, restart PostgreSQL after changing it. Reloading the configuration is not sufficient:

# systemctl restart postgresql-18.service

After the restart, verify the listener:

# ss -ltnp | grep 5432
LISTEN 0 200 0.0.0.0:5432 0.0.0.0:* users:(("postgres",pid=2350229,fd=7))
LISTEN 0 200 [::]:5432 [::]:* users:(("postgres",pid=2350229,fd=8))

The output confirms that PostgreSQL is listening on all local IPv4 and IPv6 interfaces.

The postmaster.pid file shows that the server was started with listen_addresses = '*':

# sed -n '1,8p' /u01/pg/postmaster.pid
2350229
/u01/pg
1791443245
5432
/run/postgresql
*
131 163886
ready

The server log confirms that PostgreSQL is listening on all IPv4 and IPv6 addresses:

2026-10-08 07:07:25.950 GMT [2350229] LOG: listening on IPv4 address "0.0.0.0", port 5432
2026-10-08 07:07:25.950 GMT [2350229] LOG: listening on IPv6 address "::", port 5432

The remote client can now reach the server at 203.0.113.10:5432. The next connection attempt may fail with an HBA error, which means that the network listener is working but access has not yet been authorized:

$ psql -h pg-server.example.test -p 5432 -U postgres -d postgres
psql: error: connection to server at "pg-server.example.test" (203.0.113.10), port 5432 failed: FATAL: no pg_hba.conf entry for host "203.0.113.25", user "postgres", database "postgres", no encryption

Configure Host-Based Authentication for Remote Clients

HBA means host-based authentication. The pg_hba.conf file controls who can connect, from where, to which database, as which PostgreSQL role, and how the role must authenticate.

For this PostgreSQL 18 installation, inspect the active rules with:

# grep -vE '^[[:space:]]*(#|$)' /u01/pg/pg_hba.conf
local all all peer
host all all 127.0.0.1/32 scram-sha-256
host all all ::1/128 scram-sha-256
local replication all peer
host replication all 127.0.0.1/32 scram-sha-256
host replication all ::1/128 scram-sha-256

These rules allow local Unix-socket connections through peer authentication and local TCP connections through scram-sha-256. None of them permits the remote client 203.0.113.25.

If you are as lazy as me, you can use these three rules to let any IPv4 or IPv6 client, or a local Unix socket, connect without a password:

host all all 0.0.0.0/0 trust
host all all ::/0 trust
local all all trust

It is wonderfully convenient and spectacularly unsafe: anyone who can reach the server can connect to any database as any role without a password. Use these rules only in your own testing environment, never in production. A more secure rule that can be used in production looks like this:

host postgres postgres 203.0.113.25/32 scram-sha-256

The fields mean:

  • host: applies to TCP/IP connections.
  • The first postgres: the database name.
  • The second postgres: the PostgreSQL role name.
  • 203.0.113.25/32: only this client IPv4 address. You can also allow clients from the broader 203.0.113.0/16 network by using that CIDR range instead.
  • scram-sha-256: require SCRAM password authentication.

Reload the HBA configuration after saving the file. A reload is sufficient for pg_hba.conf; a full restart is not required:

# systemctl reload postgresql-18.service

Set a password for the role if one has not already been configured:

# sudo -u postgres psql -c "ALTER ROLE postgres WITH PASSWORD 'yuanyao';"

The client can now connect and enter the password at the prompt:

$ psql -h pg-server.example.test -p 5432 -U postgres -d postgres
Password for user postgres:
psql (18.6)
Type "help" for help.
# \conninfo
Connection Information
Parameter | Value
----------------------+----------------
Database | postgres
Client User | postgres
Host | pg-server.example.test
Host Address | 203.0.113.10
Server Port | 5432
Options |
Protocol Version | 3.0
Password Used | true
GSSAPI Authenticated | false
Backend PID | 9790
SSL Connection | false
Superuser | on
Hot Standby | off
(13 rows)

For a one-time test, the password can be supplied through PGPASSWORD:

$ PGPASSWORD='yuanyao' psql -h pg-server.example.test -p 5432 -U postgres -d postgres

It can also be included in a connection URI, although storing passwords in shell history or command lines can expose them:

$ psql "postgresql://postgres:yuanyao@pg-server.example.test:5432/postgres"

Leave a Reply

I’m Yuan

Welcome to the blog of a database performance maven. Feel free to contact me to share and discuss database knowledge.

My Oracle Book

My 26 Oracle Certifications

A screenshot from certview.oracle.com

My MySQL Book

MySQL 8.0 Operations and Optimization

Let’s connect