DevOps
How to Enable PostgreSQL Remote Connections on Ubuntu (Safely)
Postgres ships listening on localhost for good reason. When you really need a remote client, coordinate postgresql.conf, pg_hba.conf, service restarts, and UFW the same way you would for Redis or MongoDB—tight rules first, party second.

Hey there—if you already walked through a fresh PostgreSQL install on Ubuntu, the next scary step is letting a real client reach the daemon without handing your data to the entire internet. Postgres defaults to localhost-only listeners because that posture survives contact with reality.
You are aiming for five minutes of focused edits: widen listen_addresses, teach pg_hba.conf which subnets may authenticate, restart, prove port 5432 is listening, then mirror the firewall rhythm I keep beside the Ubuntu nginx command paste board whenever UFW enters the story.
⏱️ Estimated time: 5–10 minutes
Security: exposing database ports
Opening database ports to the public internet is convenient for demos and risky in production. Prefer VPN, SSH tunnels, or IP allow-lists, enforce TLS where available, and use strong users and network rules.
Before you change anything
You need:
- PostgreSQL installed and running (reuse the install post above if this is a green box)
sudoaccess on the server- The server’s routable IP or hostname, plus the client IP you intend to allow
- A database role that may log in remotely once networking cooperates
If you like side-by-side stories, Redis remote access on Ubuntu shows the same pattern—widen bind, restrict who reaches the port, scream-test with systemd and logs.
Open postgresql.conf
Tell Postgres which interfaces may accept sockets by editing the main config:
sudo nano /etc/postgresql/[version]/main/postgresql.conf
Replace [version] with your cluster (for example 15 or 16). Snapshot the file first if production traffic depends on it.
Set listen_addresses
Find the listener directive:
listen_addresses = 'localhost'
Update it when you intend remote clients:
listen_addresses = '*'
'*' means every interface Postgres knows about—not “trust everyone,” just “listen everywhere.” Tighten the blast radius with pg_hba.conf, firewall rules, and VPC boundaries instead of dreaming that localhost alone will save you.
Save and exit (Ctrl + X, then Y, then Enter in nano).
Configure client authentication in pg_hba.conf
Authentication is a separate file:
sudo nano /etc/postgresql/[version]/main/pg_hba.conf
Append rules that mirror your actual networks—prefer explicit client IPs rather than 0.0.0.0/0.
Allow a single trusted workstation or bastion (recommended):
host all all your_client_ip/32 md5
Allow every IPv4 address (last resort demos only):
host all all 0.0.0.0/0 md5
Swap your_client_ip for the address that should dial in. Keep in mind that order matters: Postgres stops at the first matching pg_hba.conf line, so park the narrowest rules above broad ones.
Restart PostgreSQL and verify
Reload the service so both files take effect:
sudo service postgresql restart
Check health:
sudo service postgresql status
Confirm something is listening where you expect:
sudo netstat -tuln | grep 5432
You want 0.0.0.0:5432 (or the interface IP you targeted) rather than only 127.0.0.1:5432. Modern boxes also expose the same signal through ss -tuln | grep 5432 if netstat feels archaic on your image.
Open port 5432 in UFW (carefully)
If UFW protects the host, opening TCP 5432 follows the same muscle memory as other services—list apps, allow only what you need, then print verbose status. When I do not want to retype the UFW cadence from scratch, I keep the nginx-focused snippet nearby because it already documents the ufw allow / ufw status verbose loop I paste beside database work.
sudo ufw allow 5432/tcp
Tighten further with a source IP whenever your cloud provider or team policy allows:
sudo ufw allow from your_client_ip to any port 5432 proto tcp
MongoDB and friends tell the same story—compare with MongoDB remote connections if you want a parallel checklist for another engine.
Troubleshooting
When remote clients still fail:
- Logs:
sudo tail -f /var/log/postgresql/postgresql-[version]-main.logsurfaces syntax mistakes and auth rejections quickly. - Config typos: a stray quote in
postgresql.conforpg_hba.confprevents reloads from doing what you think. - Firewall layers: UFW might be open while a cloud security group still blocks 5432, or the client might be NATed to a different public IP than you allow-listed.
- Roles: confirm the Postgres user exists, may authenticate, and uses the password you expect from the remote machine—not
localhoston the client.
Frequently asked questions
Is it safe to set listen_addresses to '*'?
Star means every network interface can accept connections; the risk is not Postgres binding widely, it is weak pg_hba.conf or firewall rules. Pair wide bind with strict IP allow lists, VPN paths, or SSH tunnels so only intended clients reach port 5432.
What is the difference between postgresql.conf and pg_hba.conf?
postgresql.conf decides where the server listens. pg_hba.conf decides which client IPs, databases, and users may authenticate and which auth methods apply—both are required before remote tools succeed.
Why does this walkthrough use md5 in pg_hba.conf?
md5 password challenge-response still appears in older tutorials and clusters; Postgres now prefers scram-sha-256 for new installs. The flow is identical—swap the method to scram-sha-256 once all clients support it.
I allowed port 5432 in UFW—why does my client still time out?
Confirm Postgres restarted, netstat or ss shows 5432 listening on 0.0.0.0 or your IP, pg_hba.conf includes your client subnet, no cloud security group is blocking, and you targeted the server’s address rather than localhost from the remote host.
Should I expose PostgreSQL directly to the public internet?
Only for narrow demos. Production traffic should land on VPNs, private subnets, bastion SSH tunnels, or application tiers that proxy—never raw 5432 to the world without layered controls.
You should now have Postgres listening where you intend, authenticating the clients you listed, and guarded by the same firewall instincts you use everywhere else on the box. When TLS termination or HTTP-shaped routing enters the picture, layer nginx reverse proxy setup in front of the apps—not necessarily raw SQL—so the edge policy stays coherent.
Written by Shashikant Dwivedi
Engineer, occasional writer, full-time noticer. Based in Prayagraj, India. New essays land roughly twice a month.
Keep reading
Adjacent essays.

DevOps
Creating a PostgreSQL Superuser: Quick Linux Setup with psql
Jan 1, 2025 · 4 min

DevOps
Install Nginx on Ubuntu Server: apt, UFW, systemd, welcome page
Sep 14, 2024 · 5 min

DevOps
Install Redis on Ubuntu Server: Official APT Repo & Remote Access
Sep 1, 2025 · 5 min
The newsletter
New articles in your inbox.
Occasional articles on engineering, tooling, and software development practices. No marketing, no fluff — just the article, when it's ready.
Unsubscribe with one click. Your email never leaves the list.