Home / Alt manpages / pg_createcluster(1)

  • pg_createcluster(1)
  • User command
  • linux

Create a Second PostgreSQL Cluster Safely

You will create a separate PostgreSQL cluster called reporting, keep it on a known port, verify its files and status, and remove it cleanly when the test is over. This uses pg_createcluster from postgresql-common, installed here as version 257build1.1, with PostgreSQL 16. Allow about fifteen minutes. You need a PostgreSQL server package, a shell, and sudo access.

A cluster is a complete PostgreSQL server instance, not merely another database. Creating one writes data under /var/lib/postgresql, configuration under /etc/postgresql, and a log under /var/log/postgresql. The examples change system state. Read each warning before running a command.

1. Check the installed version and existing clusters

These are ordinary read-only commands. Do not choose a version that is not installed, and do not reuse an existing cluster name for that version.

$ dpkg-query -W -f='${Package} ${Version}\n' postgresql-common postgresql-16
postgresql-common 257build1.1
postgresql-16 16.15-0ubuntu0.24.04.1
$ command -v pg_createcluster
/usr/bin/pg_createcluster
$ pg_lsclusters
Ver Cluster Port Status Owner    Data directory              Log file
16  main    5432 online postgres /var/lib/postgresql/16/main /var/log/postgresql/postgresql-16-main.log

Your list will differ. In the rest of this guide, 16 is the major version and reporting is a new name. Cluster names should not contain dashes because systemd integration warns about them.

2. Choose an isolated port and startup policy

The default port is the next free port starting at 5432. For a second cluster, an explicit port makes connection strings and checks less ambiguous. The example uses 55432; choose another unprivileged port if it is already occupied.

The default startup policy is auto. This means the cluster is managed with the PostgreSQL service and may start on boot. The command below selects manual instead and does not start the server. That is a safer first state for a test cluster.

Checkpoint: confirm the port is unused before creating anything:

$ ss -ltn | awk '$4 ~ /:55432$/ {print}'
$ pg_lsclusters

No output from the first command is the expected result. If another service owns the port, stop and choose a different one. Do not use /tmp as the socket directory for a real cluster: the manpage warns that anybody can create a socket there and impersonate the server.

3. Create the cluster without starting it

This is the state-changing step and requires elevated privileges. It creates a new data directory and configuration set. The authentication options are passed after -- to initdb. Supplying both local and host authentication methods avoids the documented trap where specifying only one can leave the other as trust.

$ sudo pg_createcluster --start-conf=manual --port=55432 16 reporting -- \
    --auth-local=peer --auth-host=scram-sha-256

Without --datadir, the data directory is /var/lib/postgresql/16/reporting. Without --logfile, the log is /var/log/postgresql/postgresql-16-reporting.log. The configuration directory is /etc/postgresql/16/reporting. The command also chooses the default database superuser, postgres, unless you provide --user with a non-root account.

Do not add --start to this first run. Starting a database is a separate operational decision, and the resulting service can accept connections before you have checked its authentication and port settings.

4. Verify the files and status

Check the command's result before starting the server:

$ pg_lsclusters
Ver Cluster    Port  Status Owner    Data directory                    Log file
16  main       5432  online postgres /var/lib/postgresql/16/main       /var/log/postgresql/postgresql-16-main.log
16  reporting  55432 down   postgres /var/lib/postgresql/16/reporting  /var/log/postgresql/postgresql-16-reporting.log
$ sudo grep -E '^(port|data_directory|listen_addresses)' /etc/postgresql/16/reporting/postgresql.conf
port = 55432
$ sudo cat /etc/postgresql/16/reporting/start.conf
manual

The exact spacing and the other configuration lines can vary. The useful checks are the new cluster name, port, down status, and manual startup policy. A failed creation may leave partial files; do not guess what is safe to reuse. Inspect the error, then remove the incomplete cluster with the cleanup command in step 6 if it is listed by pg_lsclusters.

5. Start and stop it deliberately

Starting the cluster is service-disrupting only for this new instance, but it still makes a database available to clients. Confirm the port and authentication configuration first. Then run the elevated command:

$ sudo pg_ctlcluster 16 reporting start
$ pg_lsclusters
Ver Cluster    Port  Status Owner    Data directory                    Log file
16  main       5432  online postgres /var/lib/postgresql/16/main       /var/log/postgresql/postgresql-16-main.log
16  reporting  55432 online postgres /var/lib/postgresql/16/reporting  /var/log/postgresql/postgresql-16-reporting.log

When you finish testing, stop this cluster explicitly. A normal stop uses PostgreSQL's fast shutdown mode:

$ sudo pg_ctlcluster 16 reporting stop
$ pg_lsclusters | grep -E '^16[[:space:]]+reporting[[:space:]]'
16  reporting  55432 down   postgres /var/lib/postgresql/16/reporting /var/log/postgresql/postgresql-16-reporting.log

Do not use pg_ctlcluster --force as routine recovery. Its documented escalation can use immediate shutdown and then kill the process, which can leave recovery work for the next start.

6. Remove a disposable test cluster

Warning

This is irreversible. pg_dropcluster deletes the cluster's data, WAL and tablespace directories, log, and configuration files. Make sure the name and version identify the disposable cluster, not main or a production instance.

$ pg_lsclusters
$ sudo pg_dropcluster --stop 16 reporting
$ pg_lsclusters

The --stop option makes cleanup proceed even if the test server is still running. If you need to preserve the data, stop and back it up instead; do not run this command. A successful final listing no longer contains 16 reporting.

Common traps

  • A cluster name is unique only within a PostgreSQL major version. Check both columns in pg_lsclusters.
  • The port is used for TCP and the PostgreSQL Unix socket's server setting. An available port is not permission to expose the cluster publicly; review listen_addresses before opening remote access.
  • start.conf controls the Debian PostgreSQL integration, not every possible low-level way to launch postgres. Treat disabled as an accident barrier, not a complete security boundary.
  • After editing start.conf on a systemd host, run sudo systemctl daemon-reload. For this guide, choosing manual during creation avoids that edit.

Done means

  • The requested PostgreSQL major version was installed and the cluster name was unused.
  • The cluster was created on an explicitly checked port with both authentication methods set.
  • pg_lsclusters showed the expected owner, data directory, port and status.
  • The server was started and stopped deliberately, rather than enabled accidentally at boot.
  • Any disposable test cluster was removed only after its data was confirmed expendable.