/var/lib/postgresql/data to /var/lib/postgresql/18/docker.
For PostgreSQL 18, mount the volume at /var/lib/postgresql.
Keep the original volume and a tested backup throughout the migration.
See the PostgreSQL image documentation for its data directory layout.
Before you start
This procedure targets the single-database Docker Compose installation, with the default database user owning the Kaneo database. For Helm, Coolify, managed PostgreSQL, additional databases, custom roles, extensions, or tablespaces, plan a separate migration for that deployment. Apg_dump archive contains one database, not cluster-wide roles or tablespaces.
Inventory databases, roles, tablespaces, extensions, and their versions before migrating.
Install compatible extension files on PostgreSQL 18 before restoring.
The restore below assigns restored objects to the destination user and omits grants; deployments that need other owners or privileges need a different restore plan.
See the PostgreSQL upgrade documentation and your database provider’s instructions.
Prepare and validate the temporary Compose configuration in the next section before scheduling downtime.
Then stop every Kaneo instance and other writer before taking the final backup.
Follow Backups and recovery for the database, uploaded files, configuration, and a restore rehearsal.
For the final backup, omit the step that restarts Kaneo and keep all writers stopped until the new database has been checked.
Record your original Compose file, PostgreSQL image tag, volume name, and backup location.
PostgreSQL recommends using the newer version’s pg_dump for a major upgrade; the backup guide uses the PostgreSQL 16 container’s tool, so arrange a PostgreSQL 18 client with access to the old server if possible.
Use PostgreSQL 18 pg_restore for the resulting archive and rehearse the restore before cutover.
Do not run docker compose down -v or delete the original volume.
Create a PostgreSQL 18 database
From the deployment directory, save the following ascompose.pg18.yml.
It reads the same .env values as the installation guide and creates a separate volume.
Choose an unused volume name if kaneo-postgres18-migration already exists.
Never reuse an existing volume for this step.
POSTGRES_PASSWORD_FILE and Docker secrets, replace the POSTGRES_PASSWORD line in the temporary configuration with the following environment value, and add the service and top-level secret declarations:
POSTGRES_USER, POSTGRES_DB, the volume, and the health check.
Use the same secret file as the original deployment and leave POSTGRES_PASSWORD unset.
Adjust the file path if your original Compose file uses another location.
Before stopping writers, validate the temporary configuration without printing its resolved values:
ANALYZE on the restored database to collect planner statistics:
Switch the application
Stop the temporary PostgreSQL 18 container and the original PostgreSQL 16 container:compose.yml, change the PostgreSQL service image to postgres:18-alpine and its volume mount to postgres_data:/var/lib/postgresql.
Change the top-level postgres_data definition to refer to the volume used above: