How to Install PostgreSQL 16 on Ubuntu

This guide walks you through installing PostgreSQL 16 on Ubuntu, configuring the database server for local and remote access, setting up users and databases, and managing the installation over time. By the end, you will have a fully functional PostgreSQL 16 server ready for development projects, web applications, or production workloads.

Specifically, PostgreSQL 16 is well-suited for applications requiring complex queries and transactions, including content management systems like WordPress and Drupal, e-commerce platforms, data analytics pipelines, and custom application backends. The installation uses the official PostgreSQL APT repository maintained by the PostgreSQL Global Development Group (PGDG), which provides the latest patch releases and security updates directly from the PostgreSQL team.

Compare PostgreSQL Versions for Ubuntu

Before proceeding, consider which PostgreSQL version best fits your requirements. The table below compares your options on Ubuntu:

PostgreSQL VersionAvailability on UbuntuChoose It WhenTrade-offs
PostgreSQL 15PGDG repository on 22.04/24.04You need MERGE command, improved logical replication, or LZ4/Zstandard compressionRequires external repository; not the default on any Ubuntu LTS
PostgreSQL 16Ubuntu 24.04 default, PGDG on 22.04General-purpose production with parallel query improvements and enhanced monitoringRequires PGDG repository on 22.04; default on 24.04
PostgreSQL 17Ubuntu 26.04 default, PGDG on 22.04/24.04Latest features including incremental backup and improved JSON supportNewest release; may have less ecosystem tooling support initially

The PGDG repository is recommended for most users because it provides the latest upstream releases with security patches directly from the PostgreSQL team. On Ubuntu 24.04, the default repositories also include PostgreSQL 16 for users who prefer Canonical-managed updates without additional repository configuration.

These steps cover Ubuntu 22.04 LTS (Jammy) and 24.04 LTS (Noble). The PostgreSQL APT repository does not yet have a branch for Ubuntu 26.04 LTS (Resolute). Users on Ubuntu 26.04 should install from the default Ubuntu repository, which includes PostgreSQL 17. This guide will be updated once PostgreSQL adds support for Ubuntu 26.04.

Import the PostgreSQL APT Repository

Ubuntu 24.04 includes PostgreSQL 16 in its default repositories. However, if you want the latest patch releases directly from the PostgreSQL team, or if you are on Ubuntu 22.04 where only PostgreSQL 14 is available by default, you should add the official PGDG repository.

Update Your System

First, update your package index and upgrade any outdated packages. This step ensures your system has the latest security patches and prevents dependency conflicts during installation:

sudo apt update && sudo apt upgrade

Install Required Packages

Next, install the packages needed to securely download and verify the PostgreSQL repository. The curl utility fetches the GPG key, gpg processes and converts it, and lsb-release identifies your Ubuntu version for repository configuration:

sudo apt install curl ca-certificates gpg lsb-release -y

Import the PostgreSQL GPG Key

The PostgreSQL team cryptographically signs all packages from their repository. Therefore, to verify package authenticity, import the official signing key into your system’s keyring:

curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo gpg --dearmor -o /usr/share/keyrings/postgresql.gpg

This command downloads the ASCII-armored key, converts it to binary format, and saves it to the keyrings directory where APT can reference it securely.

Add the PostgreSQL Repository

With the GPG key in place, add the official PostgreSQL repository to your system. The following command creates a repository configuration file in the modern DEB822 format, which offers better readability than the legacy single-line format:

echo "Types: deb
URIs: https://apt.postgresql.org/pub/repos/apt
Suites: $(lsb_release -cs)-pgdg
Components: main
Architectures: $(dpkg --print-architecture)
Signed-By: /usr/share/keyrings/postgresql.gpg" | sudo tee /etc/apt/sources.list.d/postgresql.sources

As a result, the command outputs the file contents, confirming successful creation:

Types: deb
URIs: https://apt.postgresql.org/pub/repos/apt
Suites: noble-pgdg
Components: main
Architectures: amd64
Signed-By: /usr/share/keyrings/postgresql.gpg

The $(lsb_release -cs) variable automatically detects your Ubuntu codename (jammy for 22.04 or noble for 24.04), ensuring the correct repository branch configuration. After adding the repository, refresh the package index:

sudo apt update

If successful, the output should include lines showing APT fetching from the PostgreSQL repository:

Get:1 https://apt.postgresql.org/pub/repos/apt noble-pgdg InRelease [107 kB]
Get:2 https://apt.postgresql.org/pub/repos/apt noble-pgdg/main amd64 Packages [575 kB]
...
Fetched 682 kB in 1s (734 kB/s)

Verify Package Source

Before installing, confirm that the PostgreSQL 16 package comes from the PGDG repository rather than Ubuntu’s default repositories:

apt-cache policy postgresql-16
postgresql-16:
  Installed: (none)
  Candidate: 16.11-1.pgdg24.04+1
  Version table:
     16.11-1.pgdg24.04+1 500
        500 https://apt.postgresql.org/pub/repos/apt noble-pgdg/main amd64 Packages

This output confirms the package will install from the PostgreSQL APT repository (apt.postgresql.org). Note that on Ubuntu 22.04, the version string shows 16.11-1.pgdg22.04+1 instead.

Install PostgreSQL 16

Once you configure the repository, install PostgreSQL 16 along with its client utilities. The postgresql-16 package includes the database server, while postgresql-client-16 provides command-line tools like psql for interacting with databases:

sudo apt install postgresql-16 postgresql-client-16

During installation, APT downloads PostgreSQL 16 along with all required dependencies. The package automatically creates a postgres system user, initializes a default database cluster in /var/lib/postgresql/16/main, and configures the PostgreSQL service to start automatically on boot.

Verify the Installation

After installation completes, verify that the PostgreSQL service is running:

systemctl status postgresql
● postgresql.service - PostgreSQL RDBMS
     Loaded: loaded (/usr/lib/systemd/system/postgresql.service; enabled; preset: enabled)
     Active: active (exited) since Mon 2025-01-01 10:00:00 UTC; 1min ago
    Main PID: 12345 (code=exited, status=0/SUCCESS)
        CPU: 15ms

The active (exited) status is normal for PostgreSQL. Essentially, the main service unit acts as a wrapper that manages individual database clusters, while the actual database server runs as a separate process. To further confirm the database accepts connections, query the server version:

sudo -u postgres psql -c "SELECT version();"
                                                   version                                                   
-------------------------------------------------------------------------------------------------------------
 PostgreSQL 16.11 (Ubuntu 16.11-1.pgdg24.04+1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0, 64-bit
(1 row)

Note that on Ubuntu 22.04, the package version string shows 16.11-1.pgdg22.04+1 instead. However, both versions install the same PostgreSQL 16.11 release.

If PostgreSQL does not start automatically, enable and start it with the following command:

sudo systemctl enable postgresql --now

Manage the PostgreSQL Service

Once installed, PostgreSQL runs as a systemd service, which you can manage using standard systemctl commands. Below are the most commonly used operations:

Stop the PostgreSQL server (for maintenance or configuration changes):

sudo systemctl stop postgresql

Start the PostgreSQL server:

sudo systemctl start postgresql

Restart the PostgreSQL server (required after postgresql.conf changes):

sudo systemctl restart postgresql

Alternatively, reload configuration without restarting (for pg_hba.conf changes and some postgresql.conf parameters):

sudo systemctl reload postgresql

Finally, check the service status:

systemctl status postgresql

Configure PostgreSQL 16

Access the PostgreSQL Shell

PostgreSQL uses role-based authentication. During installation, the system creates a superuser role named postgres along with a corresponding Linux system account. To access the PostgreSQL interactive shell, first switch to the postgres user:

sudo -i -u postgres

Once logged in as the postgres user, start the interactive SQL shell:

psql

Your terminal prompt changes to postgres=#, indicating you are now connected to the PostgreSQL database:

psql (16.11 (Ubuntu 16.11-1.pgdg24.04+1))
Type "help" for help.

postgres=#

To exit the psql shell, type:

\q

Afterward, type exit to return to your regular user account.

Alternatively, access the PostgreSQL shell directly without switching users by combining the commands:

sudo -u postgres psql

This approach saves time for quick database operations and eliminates the need to manage multiple shell sessions.

Create a New Database User

For security best practices, avoid using the postgres superuser for application connections. Instead, create dedicated users with appropriate privileges. Run the following command, replacing <username> with your desired username:

sudo -u postgres createuser --interactive <username>

The --interactive flag prompts you to specify whether the new user should have superuser, database creation, or role creation privileges:

Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) n
Shall the new role be allowed to create more new roles? (y/n) n

For a standard application user, answer “no” to all prompts to follow the principle of least privilege. Next, set a password for the new user:

sudo -u postgres psql -c "ALTER USER <username> WITH PASSWORD 'your_secure_password';"
ALTER ROLE

Create a New Database

Once you create a user, create a database and grant the user access to it. First, create the database:

sudo -u postgres createdb <database_name>

Next, grant the new user full privileges on this database:

sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE <database_name> TO <username>;"
GRANT

Finally, verify the grant succeeded by listing all databases and their access privileges:

sudo -u postgres psql -c "\l"
                                                   List of databases
   Name    |  Owner   | Encoding | Collate |  Ctype  | ICU Locale | Locale Provider |   Access privileges   
-----------+----------+----------+---------+---------+------------+-----------------+-----------------------
 postgres  | postgres | UTF8     | C.UTF-8 | C.UTF-8 |            | libc            | 
 template0 | postgres | UTF8     | C.UTF-8 | C.UTF-8 |            | libc            | =c/postgres          +
           |          |          |         |         |            |                 | postgres=CTc/postgres
 template1 | postgres | UTF8     | C.UTF-8 | C.UTF-8 |            | libc            | =c/postgres          +
           |          |          |         |         |            |                 | postgres=CTc/postgres
 myappdb   | postgres | UTF8     | C.UTF-8 | C.UTF-8 |            | libc            | =Tc/postgres         +
           |          |          |         |         |            |                 | postgres=CTc/postgres+
           |          |          |         |         |            |                 | myuser=CTc/postgres
(4 rows)

In this output, the Access privileges column shows that the user has connect (c), temporary table (T), and create (C) privileges on the database.

Enable Remote Access

By default, PostgreSQL only accepts connections from the local machine. To allow remote connections, you must modify two configuration files: postgresql.conf to change the listening address, and pg_hba.conf to configure client authentication.

Configure the Listening Address

First, open the main PostgreSQL configuration file:

sudo nano /etc/postgresql/16/main/postgresql.conf

Within this file, locate the listen_addresses setting (around line 60). By default, it is set to 'localhost'. Change it to allow connections from specific addresses or all interfaces:

For a specific IP address (more secure):

listen_addresses = 'localhost, 192.168.1.50'

For all network interfaces (use with caution):

listen_addresses = '*'

Once configured, save and close the file (Ctrl+O, Enter, Ctrl+X in nano).

Configure Client Authentication

Next, edit the host-based authentication file to specify which clients can connect and how they authenticate:

sudo nano /etc/postgresql/16/main/pg_hba.conf

Then, add a line at the end of the file to allow remote connections. The SCRAM-SHA-256 method is the most secure password authentication option and is recommended for all new deployments:

# TYPE  DATABASE        USER            ADDRESS                 METHOD
host    all             all             192.168.1.0/24          scram-sha-256

This configuration allows all users to connect to all databases from the 192.168.1.0/24 subnet using SCRAM-SHA-256 password authentication. Adjust the database, user, and address fields to match your security requirements:

  • User-Specific Access: Replace all with a specific username to restrict access.
  • Database-Specific Access: Specify a particular database instead of all.
  • Address Restrictions: Use specific IP addresses or CIDR ranges to limit connections.

Apply the Configuration Changes

After modifying both configuration files, restart PostgreSQL to apply the changes:

sudo systemctl restart postgresql

Then, verify that PostgreSQL now listens on the configured addresses:

ss -tlnp | grep 5432
LISTEN 0      244          0.0.0.0:5432      0.0.0.0:*    users:(("postgres",pid=12345,fd=7))

In this example, the 0.0.0.0:5432 output indicates PostgreSQL listens on all interfaces. If you configured a specific IP, you would see that address instead.

Configure UFW Firewall for PostgreSQL

If you plan to allow remote connections to PostgreSQL, configure your firewall to permit traffic on port 5432. This step is only necessary after you enable remote access in the PostgreSQL configuration. For local-only access, no firewall configuration is needed. For a comprehensive guide to firewall management, see our UFW firewall guide for Ubuntu.

First, ensure UFW is installed and enabled:

sudo apt install ufw -y
sudo ufw enable

Warning: Before enabling UFW on a remote server, ensure you allow SSH access with sudo ufw allow ssh. Enabling the firewall without an SSH rule locks you out of your server.

To allow PostgreSQL connections from a specific IP address (recommended for security):

sudo ufw allow from 192.168.1.100 to any port 5432

Alternatively, to allow connections from an entire subnet:

sudo ufw allow from 192.168.1.0/24 to any port 5432

After adding rules, verify your firewall configuration:

sudo ufw status numbered
Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 22/tcp                     ALLOW IN    Anywhere
[ 2] 5432                       ALLOW IN    192.168.1.0/24

If needed, you can remove a rule using the rule number shown in the output:

sudo ufw delete 2

Remember to replace the IP addresses and subnet examples with your actual network configuration. Additionally, avoid opening port 5432 to the entire internet (sudo ufw allow 5432) unless you implement additional security measures like SSL/TLS encryption and strong authentication.

Performance Tuning Basics

By default, PostgreSQL’s configuration is conservative to work on minimal systems. For better performance on production servers, consider adjusting these settings in /etc/postgresql/16/main/postgresql.conf:

  • shared_buffers: Sets the amount of memory PostgreSQL uses for shared memory buffers. A typical starting point is 25% of total RAM (e.g., shared_buffers = 2GB for an 8GB server).
  • work_mem: Controls memory for internal sorting and hashing operations per query. Start with 64MB for complex queries, but monitor total memory usage since each query can use this amount.
  • max_connections: Limits concurrent database connections. The default of 100 works for most applications; increase only if needed, as each connection consumes resources.
  • effective_cache_size: Tells the query planner how much memory is available for caching. Set to approximately 75% of total RAM (e.g., effective_cache_size = 6GB for an 8GB server).

After changing these settings, restart PostgreSQL:

sudo systemctl restart postgresql

Troubleshoot Common Issues

Connection Refused Errors

If you receive “connection refused” when trying to connect remotely:

psql: error: connection to server at "192.168.1.50", port 5432 failed: Connection refused
	Is the server running on that host and accepting TCP/IP connections?

To diagnose the issue, check these items in order:

  1. Check PostgreSQL status: Run systemctl status postgresql
  2. Verify listening address: Run ss -tlnp | grep 5432; if output shows only 127.0.0.1:5432, PostgreSQL is not configured for remote access
  3. Check firewall rules: Run sudo ufw status to verify port 5432 is allowed from your client IP
  4. Review pg_hba.conf: Ensure the file includes an entry for your client IP or subnet

Authentication Failed

If you see a password authentication error:

psql: error: connection to server at "192.168.1.50", port 5432 failed: FATAL:  password authentication failed for user "testuser"

This issue typically involves one of these causes:

  • Incorrect password: Reset it with ALTER USER username WITH PASSWORD 'newpassword';
  • Wrong authentication method: Check that pg_hba.conf specifies scram-sha-256 or md5 for password authentication
  • User does not exist: Verify with \du in psql to list all roles

Repository Issues

If apt update shows errors about the PostgreSQL repository:

E: The repository 'https://apt.postgresql.org/pub/repos/apt noble-pgdg Release' does not have a Release file.

First, verify your configuration file:

cat /etc/apt/sources.list.d/postgresql.sources

Ensure the Suites line contains your correct Ubuntu codename followed by -pgdg (e.g., noble-pgdg for Ubuntu 24.04 or jammy-pgdg for Ubuntu 22.04). If you are running Ubuntu 26.04 and see this error, the PostgreSQL APT repository does not yet support Ubuntu 26.04. Use the default Ubuntu repositories instead, which include PostgreSQL 17.

View PostgreSQL Logs

For detailed error information, review the PostgreSQL logs. The tail command displays the most recent entries:

sudo tail -50 /var/log/postgresql/postgresql-16-main.log

Update PostgreSQL 16

PostgreSQL 16 receives updates through standard APT package management. The PostgreSQL team releases minor versions (like 16.11, 16.12) that include bug fixes and security patches without breaking compatibility.

To update PostgreSQL to the latest patch release:

sudo apt update
sudo apt install --only-upgrade postgresql-16 postgresql-client-16

Notably, the --only-upgrade flag ensures the command only updates the packages if they already exist, preventing accidental installation on systems where PostgreSQL might have been removed.

After updating, verify the new version:

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

For related PostgreSQL versions, see our guide on installing PostgreSQL 15 on Ubuntu.

Remove PostgreSQL 16

When you need to uninstall PostgreSQL 16, you can remove the packages while preserving or deleting your data.

Remove Packages Only (Preserve Data)

To remove PostgreSQL while keeping your databases and configuration files for a potential reinstall:

sudo apt remove postgresql-16 postgresql-client-16

Complete Removal Including Configuration

To remove PostgreSQL and its configuration files (but not databases):

sudo apt purge postgresql-16 postgresql-client-16
sudo apt autoremove

Subsequently, the autoremove command cleans up dependencies that were installed with PostgreSQL but are no longer needed.

Remove Everything Including Databases

Warning: The following commands permanently delete all PostgreSQL databases and data. This action cannot be undone. Back up any important data first using pg_dump or pg_dumpall.

sudo apt purge postgresql-16 postgresql-client-16 postgresql-common
sudo apt autoremove
sudo rm -rf /var/lib/postgresql/
sudo rm -rf /etc/postgresql/

Remove the PostgreSQL Repository

Additionally, if you no longer need the PostgreSQL APT repository, remove it along with the GPG key:

sudo rm /etc/apt/sources.list.d/postgresql.sources
sudo rm /usr/share/keyrings/postgresql.gpg
sudo apt update

Then, verify the repository removal succeeded:

apt-cache policy postgresql-16
postgresql-16:
  Installed: (none)
  Candidate: (none)
  Version table:

This output confirms APT no longer has access to the PostgreSQL repository.

Conclusion

You have successfully installed PostgreSQL 16 on Ubuntu using the official PostgreSQL APT repository. This setup provides the latest PostgreSQL 16 patch releases and security updates directly from the PostgreSQL Global Development Group. The guide covered the complete installation process, basic configuration including user and database creation, firewall setup for remote access, and maintenance procedures for updates and removal.

Moving forward, for production environments, consider implementing additional security measures such as SSL/TLS encryption for client connections, regular automated backups using pg_dump or continuous archiving with WAL, and monitoring solutions to track database performance and health.

Additional Resources

For more information about PostgreSQL 16 and ongoing maintenance, refer to these official resources:

Leave a Comment