How to Install PostgreSQL on Debian 13

By 

•

Updated on

•

9 min read

Cartoon elephant above the title PostgreSQL on Debian 13 on a light background with small geometric shapes

When you deploy an application that uses PostgreSQL, you need a running database server and a role that the application can use to connect. Debian 13 Trixie includes PostgreSQL 17 in its default repositories, so you can install it with apt without adding another repository.

This guide explains how to install PostgreSQL on Debian 13, log in to the default database, create roles and databases, and open the server to remote connections when the deployment requires it.

Quick Reference

For a printable quick reference, see the PostgreSQL cheatsheet .

TaskCommand
Install PostgreSQLsudo apt install postgresql
Open psql shellsudo -u postgres psql
Create an application rolesudo -u postgres createuser appuser
Set the role passwordsudo -u postgres psql -c '\password appuser'
Create a databasesudo -u postgres createdb --owner=appuser appdb
Show clusters and portspg_lsclusters
Restart the default clustersudo systemctl restart postgresql@17-main
Show the server versionsudo -u postgres psql -c "SHOW server_version;"
Show all databases\l (inside psql)
Show all roles\du (inside psql)

Prerequisites

You will need a Debian 13 server and a user with sudo privileges . The default installation accepts connections from the same host only. You can skip the remote access section if your application runs on the database server.

Step 1: Install PostgreSQL from the Debian Archive

The instructions below use PostgreSQL 17 from the Debian repositories. If your application requires another major version, use the PGDG installation method instead.

Start by updating the local package index:

Terminal
sudo apt update

Install the PostgreSQL server:

Terminal
sudo apt install postgresql

The postgresql package is a metapackage that installs postgresql-17. The contrib extensions, such as pg_trgm and hstore, are already part of postgresql-17. On Debian 13, postgresql-contrib is only a virtual package, so there is nothing extra to install.

On a fresh server, the installation creates a postgres system user and a cluster named main on port 5432. A cluster is a collection of databases managed by one PostgreSQL server process. The service starts automatically.

Check the installed client version:

Terminal
psql --version

The version should begin with 17. The minor version and Debian package revision depend on the updates available when you install it. This command shows the client version; we will check the server version after connecting.

Step 2: Verify the Service

PostgreSQL runs under systemd. Confirm the service is active:

Terminal
systemctl status postgresql
output
● postgresql.service - PostgreSQL RDBMS
     Loaded: loaded (/usr/lib/systemd/system/postgresql.service; enabled; preset: enabled)
     Active: active (exited)

The active (exited) state is normal for this unit. It manages the PostgreSQL clusters together, while each cluster runs under its own service, such as postgresql@17-main. Check the cluster status with:

Terminal
pg_lsclusters
output
Ver Cluster Port Status Owner    Data directory              Log file
17  main    5432 online postgres /var/lib/postgresql/17/main /var/log/postgresql/postgresql-17-main.log

The online state means the server is running. Notice that the data directory and log file paths include the major version. The examples below use version 17 and the main cluster. If you installed another version from PGDG, replace 17 with that version and check its port with pg_lsclusters.

Step 3: Connect to PostgreSQL

PostgreSQL on Debian uses peer authentication for Unix socket connections. This checks that the operating system username matches the database role name. The installation creates both a system user and a database superuser named postgres.

Open the psql shell as that system user:

Terminal
sudo -u postgres psql

The prompt changes to indicate you are inside the database:

output
postgres=#

The postgres=# prompt means you are connected to the postgres database as a superuser. To check the server version, run:

sql
SELECT version();

The result includes the server version, package revision, and build information. On the Debian archive installation, the major version should be 17. Type \q to leave psql and return to your terminal.

Step 4: Create a Role and a Database

Applications should connect with a dedicated role instead of the postgres superuser. We will create a role named appuser and a database named appdb. Replace these names with your own, keeping them consistent in the commands below.

Create the application role:

Terminal
sudo -u postgres createuser appuser

By default, createuser creates a role that can log in, without superuser, database creation, or role creation privileges.

Create a database owned by the new role:

Terminal
sudo -u postgres createdb --owner=appuser appdb

Set a password so the role can log in over TCP:

Terminal
sudo -u postgres psql -c '\password appuser'

The \password command prompts you to enter the new password twice. It keeps the password out of your shell history and SQL command text. Do not commit application credentials to version control. If you store them in a .env file, add that file to .gitignore.

Connect as the new role from the same host:

Terminal
psql -h localhost -U appuser -d appdb

Enter the password when prompted. Debian already enables scram-sha-256 password authentication for loopback TCP connections, so this works without editing pg_hba.conf. The -h localhost option selects TCP instead of the Unix socket.

Because appuser owns appdb, it can create tables in the default public schema. For more about roles and privileges, see our guide to PostgreSQL user management . Type \q to return to your terminal.

Step 5: Configure Socket Password Authentication (Optional)

You can skip this step if you connect with -h localhost. Without -h, psql uses a Unix socket, where Debian defaults to peer authentication. To let appuser authenticate with a password over that socket, open pg_hba.conf:

Terminal
sudo nano /etc/postgresql/17/main/pg_hba.conf

Add the following rule above the existing local all all peer rule. PostgreSQL uses the first matching rule, so the order matters:

/etc/postgresql/17/main/pg_hba.confconf
# TYPE  DATABASE   USER     METHOD
local   appdb      appuser  scram-sha-256

Reload PostgreSQL so the changes take effect:

Terminal
sudo systemctl reload postgresql@17-main

You can now connect with psql -U appuser -d appdb and enter the password. This rule only changes socket authentication for appuser connecting to appdb; the postgres administrator can still use peer authentication.

Step 6: Allow Remote Connections (Optional)

PostgreSQL listens on localhost by default. To accept connections from other hosts, edit postgresql.conf:

Terminal
sudo nano /etc/postgresql/17/main/postgresql.conf

Find the listen_addresses line, remove the leading # if present, and set it to the addresses the server should listen on. The following setting listens on every interface:

/etc/postgresql/17/main/postgresql.confconf
listen_addresses = '*'

Next, open the authentication configuration:

Terminal
sudo nano /etc/postgresql/17/main/pg_hba.conf

Add a rule that allows the application role to connect to its database from your private subnet. Replace 10.0.0.0/24 with your own subnet, or use a single client address such as 10.0.0.15/32:

/etc/postgresql/17/main/pg_hba.confconf
host    appdb      appuser  10.0.0.0/24  scram-sha-256

Restart the cluster to apply the listening address change. A reload alone is not enough for listen_addresses:

Terminal
sudo systemctl restart postgresql@17-main

If you use UFW and it is already enabled, allow TCP connections from the same source range:

Terminal
sudo ufw allow proto tcp from 10.0.0.0/24 to any port 5432

If you use another firewall or a cloud provider firewall, add the equivalent rule there. Restrict access to the smallest source range your application needs.

Debian enables TLS with a self-signed certificate, and psql uses it by default. The connection is encrypted, but the client does not verify the server’s identity. On an untrusted network, configure a trusted server certificate and connect with sslmode=verify-full, or use an SSH tunnel .

From the client machine, connect using the server’s address. For example, if the server uses 10.0.0.10:

Terminal
psql -h 10.0.0.10 -U appuser -d appdb

Enter the role password when prompted. If the client does not have psql, install the postgresql-client package on a Debian client first.

Installing Another Version from PGDG

The PostgreSQL Global Development Group repository provides other supported major versions. Use this method instead of Step 1 on a fresh server when you need a version such as PostgreSQL 18.

Update the package index and install postgresql-common:

Terminal
sudo apt update
sudo apt install postgresql-common

The package includes a script that sets up the PGDG repository. Run it:

Terminal
sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh

The script asks you to press Enter before it makes any changes. It adds the signing key and the repository definition, then refreshes the package index.

Install the major version your application requires, for example:

Terminal
sudo apt install postgresql-18

Continue from Step 2, replacing version 17 in the paths and service names with 18. On a fresh server, the new cluster normally uses port 5432.

If PostgreSQL is already installed, installing another major version does not create a cluster for it. Create the cluster manually:

Terminal
sudo pg_createcluster 18 main --start

The new cluster uses the next free port, normally 5433. Check pg_lsclusters and use the matching version, cluster name, and port.

Installing another version does not migrate your existing databases, and stopping the older cluster does not change the new cluster’s port. Back up your data and plan a migration before replacing an existing installation.

Useful psql Commands

The psql client has its own meta-commands for working with the database:

  • \l lists every database.
  • \c dbname connects to another database in the same session.
  • \dt lists tables in the current database.
  • \du lists every role.
  • \dn lists schemas.
  • \df lists functions.
  • \timing toggles query timing.
  • \? opens the help for meta-commands.
  • \q quits the shell.

Troubleshooting

psql: error: connection to server on socket ... failed
Check pg_lsclusters to see whether the cluster is running and which port it uses. Start the default cluster with sudo systemctl start postgresql@17-main if it is down. If the cluster uses another port, pass it to psql with -p. Check /var/log/postgresql/postgresql-17-main.log if startup fails.

Peer authentication failed
You connected over a Unix socket with an operating system username that does not match the database role. Use sudo -u postgres psql for administration, or psql -h localhost -U appuser -d appdb to connect as the application role with a password. You do not need to change a local rule to use TCP.

Role exists but cannot log in
The role lacks the LOGIN attribute. Grant it with ALTER ROLE appuser LOGIN; from a superuser session.

Port 5432 closed from a remote host
Check the listening address with ss -ltn | grep ':5432'. The output should include the server’s network interface or a wildcard address, rather than only loopback addresses. Confirm the cluster port with pg_lsclusters, then check the host and cloud firewall rules. A pg_hba.conf rejection produces a PostgreSQL error after the connection reaches the server.

Password authentication failed
Check that you are connecting to the intended server, port, database, and role. Review the first matching pg_hba.conf rule and the server log before resetting the password with sudo -u postgres psql -c '\password appuser'. A fresh installation stores passwords as SCRAM hashes, so an MD5 hash is a likely cause only for a role migrated from an older server.

In that case, set the password encryption method before assigning a new password. Open an administrator session:

Terminal
sudo -u postgres psql

Select SCRAM for this session:

sql
SET password_encryption = 'scram-sha-256';

Then enter the new password through the prompt:

Terminal
\password appuser

The new password is stored as a SCRAM hash. Type \q to leave the session, then reconnect as appuser.

Conclusion

Once your application can connect, set up regular backups with pg_dump and pg_restore . For configuration options beyond this guide, consult the PostgreSQL 17 documentation .

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 1000+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page