Skip to content
Products
AI Website Builder New VPS Hosting Cloud Servers Web Hosting Dedicated Servers Domains
Company
About Documentation Support Center Contact Get Started Login Client Area
ALL SYSTEMS OPERATIONAL
VPS

Install PostgreSQL on a VPS: Setup, Remote Access & Fixes

Getwebup 5 min read

Most of our VPS guides talk about MySQL because most WordPress and PHP stacks expect it. But if you're running a Django, Node, or Rails app — or you just prefer Postgres's stricter typing and JSONB support — you'll hit a different set of setup and connection headaches. Here's how to get PostgreSQL running on a fresh Ubuntu VPS, open it up safely for remote access, and fix the errors that trip people up most.

Installing PostgreSQL

On Ubuntu 22.04/24.04, the default repos usually carry a recent-enough version, but if you want the latest major release, pull it straight from the PostgreSQL APT repo instead of relying on whatever Ubuntu bundles.

sudo apt update
sudo apt install -y curl ca-certificates gnupg
sudo install -d /usr/share/postgresql-common/pgdg
curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo tee /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc
sudo sh -c 'echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
sudo apt update
sudo apt install -y postgresql-16

Check it's alive:

sudo systemctl status postgresql
sudo -u postgres psql -c "SELECT version();"

Creating a database and a real user

Don't run your app as the postgres superuser. Create a dedicated role and database per app — it keeps blast radius small if credentials ever leak.

sudo -u postgres psql

CREATE USER appuser WITH PASSWORD 'use-a-strong-password-here';
CREATE DATABASE appdb OWNER appuser;
GRANT ALL PRIVILEGES ON DATABASE appdb TO appuser;
\q

Test the local connection with the new role before moving on:

psql -U appuser -d appdb -h 127.0.0.1 -W

Symptom: "psql: error: connection to server ... failed: Connection refused"

Cause: By default, PostgreSQL only listens on localhost. If your app server or a GUI tool like pgAdmin/DBeaver is on a different machine, it can't reach port 5432 at all.

Fix: Edit postgresql.conf (usually /etc/postgresql/16/main/postgresql.conf) and set:

listen_addresses = '*'

Or lock it to a specific private IP instead of * if you want to be tighter about it. Then restart:

sudo systemctl restart postgresql

Symptom: "FATAL: no pg_hba.conf entry for host ..."

Cause: Even with listen_addresses open, Postgres checks pg_hba.conf for a rule that matches the connecting IP, database, and user before it lets the connection through. No matching line means an instant reject — this is the single most common Postgres connection error people hit on a fresh VPS.

Fix: Add a scoped rule in /etc/postgresql/16/main/pg_hba.conf. Don't use 0.0.0.0/0 unless you genuinely need it open to the world — scope it to your app server's IP or your office/VPN range:

# TYPE  DATABASE  USER     ADDRESS          METHOD
host    appdb     appuser  203.0.113.10/32  scram-sha-256

Reload (no restart needed for pg_hba changes):

sudo systemctl reload postgresql

Symptom: "FATAL: password authentication failed for user"

Cause: Either the password is genuinely wrong, or the auth method in pg_hba.conf is set to peer/ident instead of scram-sha-256/md5. Peer auth ignores the password entirely and checks the OS username instead — it's the default for local socket connections and confuses a lot of people testing from the app server itself.

Fix: For password-based connections (which is what your app needs), make sure the matching line uses scram-sha-256:

local   all       all                       peer
host    all       all       127.0.0.1/32    scram-sha-256
host    all       all       ::1/128         scram-sha-256

If you changed the password, reset it explicitly rather than assuming it took:

sudo -u postgres psql -c "ALTER USER appuser WITH PASSWORD 'new-password';"

Opening the firewall

Postgres listening isn't enough if UFW or your cloud provider's security group is blocking port 5432. Scope this the same way you scoped pg_hba.conf — don't open 5432 to the internet.

sudo ufw allow from 203.0.113.10 to any port 5432 proto tcp
sudo ufw status

If you're fronting the app on the same VPS as the database (the common case), you don't need to open 5432 externally at all — just let the app connect over 127.0.0.1 and skip remote access entirely. That's the safest setup by far.

Backups with pg_dump

Set up a daily dump before you need it, not after a bad migration wipes a table:

sudo -u postgres pg_dump appdb | gzip > /var/backups/appdb-$(date +%F).sql.gz

Restore with:

gunzip -c /var/backups/appdb-2026-07-20.sql.gz | sudo -u postgres psql appdb

Automate it with a cron entry and ship the file off the VPS with rclone or similar — a backup that lives only on the server it's protecting isn't much of a backup.

Quick reference: common errors

Error messageUsual causeFix location
Connection refusedPostgres not listening on that interfacepostgresql.conf → listen_addresses
No pg_hba.conf entry for hostNo matching access rulepg_hba.conf
Password authentication failedWrong password or peer/ident methodpg_hba.conf auth method + ALTER USER
Role "appuser" does not existUser created in wrong database context, or typo\du in psql to list roles
Too many connectionsmax_connections hit, or app not closing poolpostgresql.conf → max_connections, or use PgBouncer

Prevention checklist

  • Keep the database on the same private network as the app when you can — remote access should be the exception, not the default.
  • Scope every pg_hba.conf rule and firewall rule to a specific IP or range, never 0.0.0.0/0.
  • Use scram-sha-256, not md5, for any new setup — md5 is legacy at this point.
  • Automate pg_dump and actually test a restore occasionally; an untested backup is a guess.
  • If you expect more than a handful of concurrent app instances, put PgBouncer in front rather than raising max_connections indefinitely.

If you'd rather not manage any of this yourself, Getwebup's managed VPS plans include database setup and monitoring as part of onboarding — worth a look if PostgreSQL is powering a production app and you don't want 2 a.m. pages over a misconfigured pg_hba.conf.

Frequently asked questions

Can I run PostgreSQL and MySQL on the same VPS?

Yes, they run on different ports (5432 vs 3306) and don't conflict. Just make sure the VPS has enough RAM for both — each keeps its own buffer cache, so a small VPS running both under load will feel it faster than running just one.

Why does psql connect fine locally but fail from my app server?

Almost always a pg_hba.conf or firewall issue. Local connections often use the peer auth method over a Unix socket, which has nothing to do with how remote TCP connections are authenticated — check the host lines in pg_hba.conf specifically.

Is it safe to open port 5432 to the internet?

Not recommended. Scope pg_hba.conf and your firewall rule to the specific IP(s) that need access, or better, put the database behind a VPN or keep it on a private network the app server can reach without a public route.

How do I see what's using up my connections?

Run SELECT * FROM pg_stat_activity; as the postgres user. It shows every active connection, the query it's running, and how long it's been idle — useful for spotting an app that isn't closing its connection pool properly.

Do I need to restart PostgreSQL after every config change?

No. Changes to pg_hba.conf and most settings in postgresql.conf just need a reload (sudo systemctl reload postgresql). A few settings like shared_buffers or max_connections do require a full restart — the comments in postgresql.conf tell you which.

#postgresql #vps #database #pg-hba #remote-access #ubuntu

Keep reading

Chat with Support