---
verify:
  image: images:debian/13
  network: true
  run_as: user
  given:
    - apt-get update
    - apt-get install -y curl ca-certificates gnupg
    - install -d /usr/share/postgresql-common/pgdg
    - curl -fsSL -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc https://www.postgresql.org/media/keys/ACCC4CF8.asc
    - . /etc/os-release
    - echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt ${VERSION_CODENAME}-pgdg main" > /etc/apt/sources.list.d/pgdg.list
    - apt-get update
    - apt-get install -y postgresql-15
    - pg_lsclusters -h | grep -q '^15[[:space:]]\+main.*online' || pg_ctlcluster 15 main start
    - pg_lsclusters -h | grep -q '^15[[:space:]]\+main.*online'
  blocks: all
  signal:
    type: exit
---
# Upgrade PostgreSQL 15 to 17 on Debian 13

This assumes PostgreSQL 15 is installed from the PGDG repository (apt.postgresql.org) with the default `15/main` cluster, and you want to move to 17 using Debian's `pg_upgradecluster`.

> Take a backup first. `pg_upgradecluster` keeps the old cluster until you drop it, but a dump is cheap insurance.

## Check what you have

```bash
pg_lsclusters
```

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

## Back up

```bash
sudo -u postgres pg_dumpall > ~/pg15-backup.sql
```

## Install PostgreSQL 17

```bash
sudo apt-get update
sudo apt-get install -y postgresql-17
```

Depending on your `postgresql-common` settings, installing 17 may create an empty `17/main` cluster. If it did, drop it so the upgrade can take its place:

```bash
if pg_lsclusters -h | grep -q '^17 \+main '; then
  sudo pg_dropcluster 17 main --stop
fi
```

## Upgrade

```bash
sudo pg_upgradecluster 15 main
```

This stops 15, copies the data into a new 17 cluster on port 5432, and starts it. The old cluster stays on 5433, stopped.

## Verify

```bash
pg_lsclusters -h | grep '^17'
sudo -u postgres psql -tAc 'show server_version' | cut -d. -f1
```

You should see the 17 cluster online on port 5432, and major version 17:

```output
17  main    5432 online postgres /var/lib/postgresql/17/main /var/log/postgresql/postgresql-17-main.log
17
```

## Clean up

Once you've checked your applications:

```bash
sudo pg_dropcluster 15 main
sudo apt-get purge -y postgresql-15
```
