How to Install PostgreSQL 18 on Ubuntu 26.04 and Allow Remote Access

Install PostgreSQL 18 from the default repositories on an Ubuntu 26.04 server, create a user and a database for remote a…

Ubuntu 26.04PostgreSQL 18x86_64About 9 min

Verified guide

This guide was verified by creating a cloud server and running every command in it, from start to finish, exactly as written.

OS
Ubuntu 26.04.1 LTS · x86_64
Installed version
PostgreSQL 18.6 (18.6-0ubuntu0.26.04.1)
Test server
DigitalOcean · 1 vCPU / 1 GB RAM / 25 GB SSD (s-1vcpu-1gb, sgp1)
Last checked
2026-10-13

This guide contains affiliate links. If you sign up through them, Codesand may earn a commission. This doesn't affect the content or our assessments.

Install PostgreSQL 18 from the default repositories on an Ubuntu 26.04 server, create a user and a database for remote access, and then configure remote access and the firewall so that only your PC can connect.

1. Requirements

  • One Ubuntu 26.04 LTS server (1 GB of memory or more recommended)
  • SSH access with an account that has sudo privileges
  • The public IP address of the PC you will connect from (e.g. 203.0.113.10)

If you don't have a server, create the smallest DigitalOcean Droplet (1 vCPU · 1 GB). This Droplet is enough to install PostgreSQL 18. Every step in this guide was verified on a server created as a Droplet (1 vCPU · 1 GB memory · 25 GB SSD · Ubuntu 26.04 · Singapore).

2. Install PostgreSQL 18

The default Ubuntu 26.04 repositories include PostgreSQL 18. First, check the version that will be installed.

apt-cache policy postgresql | head -4
postgresql:
  Installed: (none)
  Candidate: 18+290ubuntu1
  Version table:

postgresql is a package that installs Ubuntu's default PostgreSQL version, so its version is shown as 18+290ubuntu1. The leading 18 is the PostgreSQL version. Update the package list, then install it.

sudo apt update
sudo apt install -y postgresql postgresql-contrib
Creating new PostgreSQL cluster 18/main ...
/usr/lib/postgresql/18/bin/initdb -D /var/lib/postgresql/18/main --auth-local peer --auth-host scram-sha-256 --no-instructions

Data page checksums are enabled.

During installation, output from creating the default cluster is displayed. Data page checksums are enabled. means that data page checksums are turned on. Data page checksums are a feature that checks, when data is read from disk, that the stored content has not been corrupted; they are turned on by default starting with PostgreSQL 18. On Ubuntu 26.04, postgresql-contrib is not a separate package but is included in the postgresql-18 package, so only postgresql appears in the list of packages to install.

When installation finishes, check the installed version. The 0ubuntu0.26.04.1 after the version means that the package comes from the default Ubuntu 26.04 repositories.

psql --version
psql (PostgreSQL) 18.6 (Ubuntu 18.6-0ubuntu0.26.04.1)

3. Check the service status

When the installation finishes, the default cluster 18/main is created automatically and runs on port 5432.

pg_lsclusters
Ver Cluster Port Status Owner    Data directory              Log file
18  main    5432 online postgres /var/lib/postgresql/18/main /var/log/postgresql/postgresql-18-main.log
sudo systemctl status postgresql@18-main --no-pager
● postgresql@18-main.service - PostgreSQL Cluster 18-main
     Loaded: loaded (/usr/lib/systemd/system/postgresql@.service; enabled-runtime; preset: enabled)
     Active: active (running) since Tue 2026-10-13 07:59:38 UTC; 12s ago
             ├─5158 "postgres: 18/main: io worker 0"
             ├─5159 "postgres: 18/main: io worker 1"
             ├─5160 "postgres: 18/main: io worker 2"

The process list shows three io worker processes. These are the worker processes for the asynchronous I/O feature added in PostgreSQL 18. This method is set by the io_method setting, and the default is worker.

sudo -u postgres psql -c "SHOW io_method;"
 io_method
-----------
 worker
(1 row)

Now check that you can connect to PostgreSQL. Right after installation, you can connect only as the Linux account postgres.

sudo -u postgres psql -c "SELECT version();"
                                                             version
---------------------------------------------------------------------------------------------------------------------------------
 PostgreSQL 18.6 (Ubuntu 18.6-0ubuntu0.26.04.1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 15.2.0-16ubuntu1) 15.2.0, 64-bit
(1 row)

Also check that data page checksums are turned on.

sudo -u postgres psql -c "SHOW data_checksums;"
 data_checksums
----------------
 on
(1 row)

4. Check the default security settings

Before you allow remote connections, check the defaults for how passwords are stored and which connections are allowed.

sudo -u postgres psql -c "SHOW password_encryption;"
 password_encryption
---------------------
 scram-sha-256
(1 row)

scram-sha-256 stores a hash instead of the password itself, and does not send the password as is when you connect. The default is already scram-sha-256, so you do not need to change it.

sudo grep -v -E '^#|^$' /etc/postgresql/18/main/pg_hba.conf
local   all             postgres                                peer
local   all             all                                     peer
host    all             all             127.0.0.1/32            scram-sha-256
host    all             all             ::1/128                 scram-sha-256
local   replication     all                                     peer
host    replication     all             127.0.0.1/32            scram-sha-256
host    replication     all             ::1/128                 scram-sha-256

pg_hba.conf is the file that sets who can connect from where. The local lines are for socket connections on the server and use peer authentication, which requires the Linux account name to match the database user name. The host lines are for TCP connections, and for now they allow password connections only from the server's own addresses (127.0.0.1, ::1). The admin account postgres has no password and can connect only through peer, so you cannot connect remotely as postgres. Keep it this way, and allow remote connections only for the dedicated user you create below.

5. Create a user and a database

It is safer for applications to connect as a dedicated user instead of the admin account postgres. Create the user appuser and the database appdb owned by this user. Be sure to replace the password with a value of your own.

sudo -u postgres psql -c "CREATE ROLE appuser WITH LOGIN PASSWORD 'change-this-password';"
sudo -u postgres psql -c "CREATE DATABASE appdb OWNER appuser;"
CREATE ROLE
CREATE DATABASE

Check that the users were created.

sudo -u postgres psql -c "\du"
                             List of roles
 Role name |                         Attributes
-----------+------------------------------------------------------------
 appuser   |
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS

To connect with a password, you must add -h localhost. This connects over TCP and checks the password.

psql -h localhost -U appuser -d appdb -c "\conninfo"
Password for user appuser:
            Connection Information
      Parameter       |         Value
----------------------+------------------------
 Database             | appdb
 Client User          | appuser
 Host                 | localhost
 Host Address         | ::1
 Server Port          | 5432
 Options              |
 Protocol Version     | 3.0
 Password Used        | true
 GSSAPI Authenticated | false
 Backend PID          | 5988
 SSL Connection       | true
 SSL Library          | OpenSSL
 SSL Protocol         | TLSv1.3
 SSL Key Bits         | 256
 SSL Cipher           | TLS_AES_256_GCM_SHA384
 SSL Compression      | false
 ALPN                 | postgresql
 Superuser            | off
 Hot Standby          | off
(19 rows)

In PostgreSQL 18, psql shows the result of \conninfo as a table. If Password Used is true, you connected with a password, and if SSL Connection is true, the connection is encrypted.

6. Allow remote connections

The default settings allow only localhost connections. To allow remote connections, you need to edit two files.

First, change listen_addresses in postgresql.conf so that the server also accepts connections on external addresses. '*' means that PostgreSQL accepts connections on all of the server's addresses.

sudo sed -i "s/^#listen_addresses = 'localhost'/listen_addresses = '*'/" /etc/postgresql/18/main/postgresql.conf
grep -n '^listen_addresses' /etc/postgresql/18/main/postgresql.conf
60:listen_addresses = '*'		# what IP address(es) to listen on;

Next, add one line to pg_hba.conf with the IP, user and database to allow. Replace 203.0.113.10 with the public IP of the PC you will connect from.

echo 'host    appdb    appuser    203.0.113.10/32    scram-sha-256' | sudo tee -a /etc/postgresql/18/main/pg_hba.conf
sudo systemctl restart postgresql
host    appdb    appuser    203.0.113.10/32    scram-sha-256

Check that port 5432 is now open on external addresses as well. If you see 0.0.0.0:5432, it is working.

sudo ss -tlnp | grep 5432
LISTEN 0      200          0.0.0.0:5432      0.0.0.0:*    users:(("postgres",pid=6219,fd=6))
LISTEN 0      200             [::]:5432         [::]:*    users:(("postgres",pid=6219,fd=7))

7. Configure the firewall (ufw)

Separately from the PostgreSQL settings, allow only your PC's IP to reach port 5432 in the firewall as well. Always allow SSH before you enable the firewall. If you enable the firewall without allowing SSH, your connection to the server is cut off. --force is an option that enables the firewall without a confirmation prompt.

sudo ufw allow OpenSSH
sudo ufw allow from 203.0.113.10 to any port 5432 proto tcp
sudo ufw --force enable
sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
5432/tcp                   ALLOW       203.0.113.10
OpenSSH (v6)               ALLOW       Anywhere (v6)

8. Check the connection from your PC

If psql isn't installed on your PC, you can run the PostgreSQL client with Docker and connect. Replace 203.0.113.20 with the server's IP. Because the --rm option is added, the container is deleted automatically when you end the session. -it is an option that attaches a terminal so that you can enter the password.

docker run --rm -it postgres:18-alpine psql -h 203.0.113.20 -U appuser -d appdb -c "SELECT current_user, inet_server_port(), ssl FROM pg_stat_ssl WHERE pid = pg_backend_pid();"
Password for user appuser:
 current_user | inet_server_port | ssl
--------------+------------------+-----
 appuser      |             5432 | t
(1 row)

If current_user is appuser, remote access works. The t (true) in ssl means that the connection is encrypted. Ubuntu's PostgreSQL package turns on SSL by default with a self-signed certificate during installation.

9. Troubleshooting

FATAL: Peer authentication failed for user "appuser"

This error occurs because connecting without -h uses peer authentication. Add -h localhost, as in psql -h localhost -U appuser -d appdb, to connect with a password.

connection to server at "203.0.113.20", port 5432 failed: Connection refused

This means that PostgreSQL is not accepting connections on external addresses. You get this error if you connect remotely before changing listen_addresses. Check with grep -n '^listen_addresses' /etc/postgresql/18/main/postgresql.conf that it is '*', and check that you ran sudo systemctl restart postgresql after changing it.

FATAL: no pg_hba.conf entry for host "203.0.113.10", user "postgres", database "appdb", SSL encryption

This means that the combination of IP, user and database you connected with is not in pg_hba.conf. This guide allows only appuser to connect to appdb, so this error is expected when you connect remotely as postgres. The same error is displayed twice, with SSL encryption and with no encryption, because the client tried once more without encryption after the encrypted connection was rejected.

FATAL: password authentication failed for user "appuser"

This means that the password is wrong. Check that you entered the password you set with CREATE ROLE in step 5.

10. Uninstall

To delete PostgreSQL and all of its data, run the commands below. Because the database files are deleted as well, back up any data you need with pg_dump first.

sudo DEBIAN_FRONTEND=noninteractive apt purge -y postgresql postgresql-18 postgresql-client-18 postgresql-contrib postgresql-common postgresql-client-common
sudo apt autoremove -y
sudo rm -rf /var/lib/postgresql /etc/postgresql

DEBIAN_FRONTEND=noninteractive is an option that proceeds with the default values without showing configuration questions while the packages are removed. The data directories are deleted by rm -rf on the last line.

Also delete the port 5432 rule you added to the firewall.

sudo ufw delete allow from 203.0.113.10 to any port 5432 proto tcp
Rule deleted

Check that no PostgreSQL packages remain. If 0 is displayed, everything has been deleted.

dpkg -l | grep -c postgresql
0

Try it yourself

No server yet? You can spin up an Ubuntu server in a few minutes with one of these providers. We verified this guide on DigitalOcean.