Server Management
How to Install and Secure PostgreSQL
PostgreSQL is a powerful open-source relational database. This guide installs it on Ubuntu 24.04, enforces modern scram-sha-256 password authentication instead of the old md5, keeps it listening on localhost only, and gives each application its own least-privilege role.
Install PostgreSQL
Install the server and contrib extensions, then confirm the service is running.
sudo apt update sudo apt install -y postgresql postgresql-contrib sudo systemctl enable --now postgresql systemctl status postgresql --no-pager # verify it is active (running)
Listen on Localhost Only
Keep the server bound to the loopback interface so it is never reachable from the internet. This is the most important network control for a database.
sudo nano /etc/postgresql/*/main/postgresql.conf # Set: listen_addresses = 'localhost' # accept connections only from this machine
Enforce scram-sha-256 Authentication
Set the password hashing algorithm to scram-sha-256 (far stronger than md5) and require it in the client auth rules. New passwords are then stored as SCRAM hashes.
sudo nano /etc/postgresql/*/main/postgresql.conf # Set: password_encryption = scram-sha-256 # Then require it for local TCP connections: sudo nano /etc/postgresql/*/main/pg_hba.conf # Ensure the local host lines use scram-sha-256, e.g.: host all all 127.0.0.1/32 scram-sha-256 host all all ::1/128 scram-sha-256 sudo systemctl restart postgresql
Create a Dedicated Role and Database per App
Give each application its own role and database. The role owns its database and nothing else, following least privilege. Set the password AFTER enabling scram so it is hashed correctly.
sudo -i -u postgres psql -- Inside psql: CREATE ROLE myappuser WITH LOGIN PASSWORD 'CHANGE_ME_long_random_password'; CREATE DATABASE myapp OWNER myappuser; -- Make sure no broad public access remains on the new DB REVOKE ALL ON DATABASE myapp FROM PUBLIC; \q
Verify the Connection and Hashing
Connect as the new role over TCP to confirm scram auth works, and check that the stored secret is a SCRAM hash.
# -h 127.0.0.1 forces a TCP connection so the scram-sha-256 rule is exercised psql -h 127.0.0.1 -U myappuser -d myapp -c '\conninfo' # enter the password; should connect # Confirm the password is stored as a SCRAM hash, not md5: sudo -i -u postgres psql -c "SELECT rolname, substring(rolpassword for 14) FROM pg_authid WHERE rolname='myappuser';" # Expected prefix: SCRAM-SHA-256
Confirm It Is Not Listening Externally
Double-check the bind so the database is not exposed beyond the host.
sudo ss -tlnp | grep 5432 # should show 127.0.0.1:5432, NOT 0.0.0.0:5432
PostgreSQL now uses scram-sha-256 authentication, listens only on localhost, and gives each application a dedicated least-privilege role and database. If a remote app needs access, prefer an SSH tunnel or a private network over opening port 5432 to the world.