
This guide covers how to install PostgreSQL 16 on Ubuntu 22.04 LTS using the official PGDG repository — the same method used in production environments. Commands are verified on Ubuntu 22.04 (Jammy). The original 2021 post covered Ubuntu 18.04 + PostgreSQL 11, both now EOL.
Environment note: Commands below are verified on Ubuntu 22.04 LTS (Jammy) + PostgreSQL 16. Original post (March 2021) covered Ubuntu 18.04 + PostgreSQL 11 — both are now EOL.
Quick install — copy, paste, done
bash
sudo apt install -y curl ca-certificates
sudo install -d /usr/share/postgresql-common/pgdg
sudo curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc \
--fail https://www.postgresql.org/media/keys/ACCC4CF8.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
Cluster starts automatically post-install. Verify in 10 seconds:
bash
sudo systemctl status postgresql
psql -U postgres -c "SELECT version();"
Why the official PGDG repo, not Ubuntu’s default apt
Ubuntu’s default apt ships a frozen PostgreSQL version tied to the OS release cycle. Ubuntu 22.04 ships PostgreSQL 14 — two major releases behind. Patching, new features, and security fixes come from upstream PostgreSQL’s PGDG repo only.
Always use PGDG. That is what production environments use.
Step-by-step with terminal output
1. Confirm Ubuntu version
bash
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 22.04.4 LTS
Release: 22.04
Codename: jammy
The codename jammy is used in the repo entry. Map:
| Ubuntu Version | Codename |
|---|---|
| 24.04 | noble |
| 22.04 | jammy |
| 20.04 | focal |
2. Add the PGDG signing key and repository
bash
sudo install -d /usr/share/postgresql-common/pgdg
sudo curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc \
--fail https://www.postgresql.org/media/keys/ACCC4CF8.asc
bash
sudo sh -c 'echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] \
https://apt.postgresql.org/pub/repos/apt jammy-pgdg main" \
> /etc/apt/sources.list.d/pgdg.list'
Verify the repo entry:
bash
$ cat /etc/apt/sources.list.d/pgdg.list
deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] \
https://apt.postgresql.org/pub/repos/apt jammy-pgdg main
3. Update apt and install PostgreSQL 16
bash
$ sudo apt update
Hit:1 https://apt.postgresql.org/pub/repos/apt jammy-pgdg InRelease
Hit:2 http://archive.ubuntu.com/ubuntu jammy InRelease
Hit:3 http://security.ubuntu.com/ubuntu jammy-security InRelease
Reading package lists... Done
$ sudo apt install -y postgresql-16
...
Creating new PostgreSQL cluster 16/main ...
config /etc/postgresql/16/main
data /var/lib/postgresql/16/main
locale en_US.UTF-8
socket /var/run/postgresql
port 5432
update-alternatives: using /usr/share/postgresql/16/man/man1/postmaster.1.gz
4. Verify installation and cluster status
bash
$ sudo systemctl status postgresql
● postgresql.service - PostgreSQL RDBMS
Loaded: loaded (/lib/systemd/system/postgresql.service; enabled)
Active: active (running)
$ pg_lsclusters
Ver Cluster Port Status Owner Data directory Log file
16 main 5432 online postgres /var/lib/postgresql/16/main /var/log/postgresql/postgresql-16-main.log
Connect as postgres and check version:
bash
$ sudo -u postgres psql
psql (16.3)
Type "help" for help.
postgres=# SELECT version();
version
-------------------------------------------------------------------------------------------------------------------------
PostgreSQL 16.3 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0, 64-bit
(1 row)
Cluster management — essential commands
bash
# Start / stop / restart
sudo systemctl start postgresql
sudo systemctl stop postgresql
sudo systemctl restart postgresql
# Reload config without restart (postgresql.conf changes)
sudo systemctl reload postgresql
# pg_ctlcluster alternative
sudo pg_ctlcluster 16 main start
sudo pg_ctlcluster 16 main stop
sudo pg_ctlcluster 16 main status
Post-install — production essentials
Set a password for the postgres superuser
bash
sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'your_strong_password';"
Allow TCP connections (postgresql.conf)
bash
sudo vi /etc/postgresql/16/main/postgresql.conf
# Change: listen_addresses = 'localhost' → 'localhost' for local only, '*' for all interfaces
Configure client authentication (pg_hba.conf)
bash
sudo vi /etc/postgresql/16/main/pg_hba.conf
# Add line for local network access:
# host all all 192.168.1.0/24 scram-sha-256
Reload after pg_hba.conf changes:
bash
sudo systemctl reload postgresql
Confirm it worked
bash
# Check data directory
$ sudo -u postgres psql -c "SHOW data_directory;"
data_directory
----------------------------------------
/var/lib/postgresql/16/main
(1 row)
# Check port
$ sudo -u postgres psql -c "SHOW port;"
port
------
5432
(1 row)
# Check log location
$ sudo -u postgres psql -c "SHOW log_directory;"
log_directory
---------------
log
(1 row)
Installing a specific older version
Need PostgreSQL 15, 14, or 13 on the same host?
bash
sudo apt install -y postgresql-15
# or
sudo apt install -y postgresql-14
List all installed clusters:
bash
pg_lsclusters
Each version runs on a different port (5432, 5433, 5434…) by default.
What’s next
- Install PostgreSQL 16 on RHEL 9 — Production-Grade Guide — if you also manage RHEL/CentOS environments
- psql Meta-Commands: Generic Information — first commands to run after connecting
- PostgreSQL Replication Setup: Master and Slave — next step after installation
