Introduction

PostgreSQL 18 is the latest major release of the world's most advanced open-source relational database. If you are building a backend API, a data pipeline, or a production web application on Ubuntu, this is the version you want on your server — not the older PostgreSQL that ships in Ubuntu's default repositories.

This guide walks you through installing PostgreSQL 18 on Ubuntu 24.04 or Ubuntu 22.04 from the official PostgreSQL APT repository (PGDG). You will add the repository, install the server, secure the default superuser, create a dedicated database user and database for your application, and optionally open remote access the safe way. Every command below is current and widely documented.

Who this is for: developers and system administrators who are comfortable in a Linux terminal and can run commands with sudo. Follow the steps in order and you will have a working, production-ready PostgreSQL 18 server in about ten minutes.

Prerequisites

  • Ubuntu 24.04 LTS or 22.04 LTS (server or desktop edition)
  • A user account with sudo privileges (or root access)
  • An internet connection that can reach apt.postgresql.org
  • About 250 MB of free disk space for the server and client tools

Step 1: Update your package index

Before installing anything new, refresh the local package index and bring the system up to date. Installing on a stale system is a classic source of broken dependencies and half-applied configurations, and this one command pair prevents most of it.

sudo apt update && sudo apt upgrade -y

apt update downloads the latest package lists from every configured repository. apt upgrade -y installs the available updates without asking for confirmation. Run them together so your base system is current before you add a third-party repository in the next steps.

Step 2: Install the prerequisites for the repository

To register the official PostgreSQL repository you need curl to download the signing key and ca-certificates so that HTTPS downloads are properly verified.

sudo apt install -y curl ca-certificates

curl fetches files over HTTP and HTTPS from the command line. ca-certificates provides the trusted root certificates curl needs to verify it is really talking to postgresql.org. The -y flag answers "yes" to the installation prompt automatically.

Step 3: Import the PostgreSQL signing key

APT verifies every package against a GPG key before installing it. Create the directory that holds the PostgreSQL repository key, then download the official key published by the PostgreSQL project.

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

install -d creates the directory that will hold the repository's signing key (it behaves like mkdir -p but is the conventional form in packaging scripts). The curl command downloads the official PostgreSQL signing key into that directory. The --fail flag makes curl exit with an error instead of silently saving an HTML error page if the download fails, so a broken download can never masquerade as a valid key.

Step 4: Add the official PostgreSQL (PGDG) repository

Now register the PostgreSQL Global Development Group repository. The command below detects your Ubuntu codename automatically (noble for 24.04, jammy for 22.04), so the same line works on both releases.

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'

This writes a new APT source file pointing at the official PostgreSQL repository. The signed-by option pins the repository to the key you downloaded in Step 3, so APT only trusts packages actually signed by PostgreSQL. $(lsb_release -cs) expands to your Ubuntu codename at runtime. The sh -c wrapper is required because the output redirection itself needs root privileges — plain sudo echo ... > file would fail with "permission denied" since the shell performs the redirection before sudo runs.

Step 5: Install PostgreSQL 18

Refresh the package lists so APT sees the new repository, then install PostgreSQL 18. Ubuntu's own repositories only carry older PostgreSQL versions, which is exactly why Steps 3 and 4 were necessary.

sudo apt update
sudo apt install -y postgresql-18

The second apt update picks up the package lists from the PGDG repository you just added. apt install -y postgresql-18 installs the database server, the client tools (psql and friends), and the standard contrib modules for version 18.

Step 6: Enable and start the PostgreSQL service

The installer registers a systemd service for you. Enable it so the database starts automatically on boot, start it now, and confirm it is healthy.

sudo systemctl enable --now postgresql
sudo systemctl status postgresql

systemctl enable --now does two jobs in one call: it enables the service to start at boot and starts it immediately. status shows whether the service is active (running) — press q to exit the pager it opens.

pg_lsclusters
psql --version

pg_lsclusters lists every PostgreSQL cluster on the machine. You should see the 18/main cluster on port 5432 with status online. psql --version confirms the client tools report version 18, proving you installed the new release and not an older one.

Step 7: Secure the postgres user and create your first database

PostgreSQL runs under a system user named postgres. Log in as that user — the first login uses peer authentication, so no password is needed yet — and lock down the installation.

sudo -u postgres psql

sudo -u postgres psql opens the interactive psql shell as the postgres operating-system user. Because the OS user matches the database superuser, peer authentication lets you straight in for this initial setup.

Inside psql, set a strong password on the superuser, then create a dedicated user and database for your application. Replace the placeholder passwords with real, generated ones.

ALTER USER postgres WITH PASSWORD 'StrongPassword123';
CREATE USER appuser WITH PASSWORD 'StrongPassword123';
CREATE DATABASE appdb OWNER appuser;
\q

ALTER USER sets a password on the postgres superuser so it is protected if password authentication is ever used for it. CREATE USER makes a new login role for your application. CREATE DATABASE ... OWNER appuser creates the appdb database and gives appuser full ownership of it — your application gets everything it needs without superuser privileges. \q quits psql. Never run your application as the postgres superuser: a dedicated user with limited rights is basic operational hygiene.

Step 8 (optional): Allow remote connections safely

By default PostgreSQL listens only on localhost. If an application server on another machine needs access, you must change two configuration files and open the firewall — but do it narrowly. Opening port 5432 to the whole internet is one of the fastest ways to get your database compromised; automated scanners find open databases within hours.

First, edit the main configuration file and find the listen_addresses line:

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

Change listen_addresses = 'localhost' to listen_addresses = '*'. This makes PostgreSQL accept connections on all network interfaces instead of only the loopback interface. Save with Ctrl+O, confirm with Enter, and exit with Ctrl+X.

Next, grant access to exactly one trusted client IP in the host-based authentication file. Replace 203.0.113.10 with the real IP address of your application server:

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

Add this line (typically near the other host entries):

host    all    all    203.0.113.10/32    scram-sha-256

This permits password-authenticated connections from that single IP address only, using the modern scram-sha-256 password scheme. Never put 0.0.0.0/0 here.

Finally, open the firewall for that IP alone and restart PostgreSQL so both configuration changes take effect:

sudo ufw allow from 203.0.113.10 to any port 5432
sudo systemctl restart postgresql

ufw allow from ... to any port 5432 opens the database port for the trusted IP and nobody else. systemctl restart postgresql reloads both configuration files. If you are not using UFW, apply the equivalent rule in whatever firewall you run — the principle is identical: one IP, one port.


Verify it worked

Run these checks to prove the server is up, the version is correct, and your new user and database work end to end.

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

The -c flag runs a single SQL command without opening the interactive shell. The output should show PostgreSQL 18.x — if it shows an older version, you installed from the wrong repository and should revisit Steps 4 and 5.

sudo -u postgres psql -d appdb -c "CREATE TABLE test (id SERIAL PRIMARY KEY, name TEXT);"
sudo -u postgres psql -d appdb -c "INSERT INTO test (name) VALUES ('hello');"
sudo -u postgres psql -d appdb -c "SELECT * FROM test;"
sudo -u postgres psql -d appdb -c "DROP TABLE test;"

This creates a table, inserts a row, reads it back, and cleans up. If all four commands succeed, the server stores and returns data correctly.

psql -h localhost -U appuser -d appdb -c "SELECT current_user;"

This connects over TCP as appuser and should print appuser. It proves password authentication and your new database both work — enter the password you set in Step 7 when prompted.

sudo ss -lnt | grep 5432

ss -lnt lists listening TCP sockets. You should see port 5432 on 127.0.0.1 (and on 0.0.0.0 if you completed Step 8), confirming the server is accepting connections.

Common issues & fixes

1. 'Unable to locate package postgresql-18'

This means APT cannot see the PGDG repository — either the source file was never created or you skipped the second apt update in Step 5.

Fix: confirm the source file exists and is not empty:

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

If the file is missing or empty, repeat Steps 3 and 4 exactly, then run sudo apt update again before retrying the install.

2. 'could not connect to server: No such file or directory'

The PostgreSQL service is not running, so the Unix socket psql expects does not exist.

Fix: start the service and check its status:

sudo systemctl start postgresql
sudo systemctl status postgresql

If it refuses to start, read the last lines of its log for the real reason:

sudo journalctl -u postgresql --no-pager | tail -30

3. 'FATAL: password authentication failed for user "appuser"'

Either the password was never set, or the password in your connection string does not match the one stored in the database. For local TCP connections the default pg_hba.conf requires scram-sha-256 password authentication, so a missing or wrong password always fails here.

Fix: log in as the postgres superuser and set the password again, carefully:

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

Then reconnect using exactly that password.

4. Remote connection refused or times out

One of three things is wrong: listen_addresses is still localhost, the pg_hba.conf entry does not match your client IP, or the firewall is blocking port 5432.

Fix: check each layer in order. Confirm listen_addresses = '*' in postgresql.conf, confirm your client IP appears in a host line in pg_hba.conf, and confirm the firewall rule with sudo ufw status. Restart the service after any configuration change:

sudo systemctl restart postgresql

5. 'FATAL: role "myuser" does not exist'

You ran psql as your OS user, and peer authentication tried to log you in as a database role matching your OS username — which was never created.

Fix: connect explicitly as an existing role:

psql -U appuser -h localhost -d appdb

Or create a role matching your OS username:

sudo -u postgres createuser myuser

Conclusion

You now have PostgreSQL 18 running on Ubuntu from the official repository, with a secured superuser, a dedicated application user and database, and — if you completed Step 8 — tightly scoped remote access. Keep the server healthy with regular apt upgrades, since PGDG publishes minor releases alongside upstream, and set up automated backups before any production data lands on it.

Database setup, hardening, and performance tuning are the kind of work we do every day — if you would rather have an expert handle your server setup, XpertBees can get your stack production-ready for you.