I was running PostgreSQL 9.6 13.4 17.6 on FreeBSD and wanted to update that database to version 10 14.0 18 with minimal downtime. If you use pg_upgrade with the -k commandline option, database files are hard-linked to the new data directory, which is a time- and space-saving method. For this you need both the old and new binaries installed on the machine. Unfortunately, as every version of PostgreSQL is installed under the /usr/local hierarchy on FreeBSD, you can't have two different versions installed at the same time - unless we setup a temporary jail.
If you run one or more standby database servers, e.g. a streaming replication, then you'll need ssh access from the primary to all secondary servers, and rsync installed on both sides.
$ bsdinstall jail /var/jailThe installer comes up with several dialogs. During the installation
$ mount -t devfs none /var/jail/dev
$ pkg -c /var/jail install postgresql17-server
$ portmaster -o databases/postgresql18-client postgresql17-clientSelect the NLS, OPTIMIZED_CFLAGS, SSL, and ZSTD options.
$ portmaster -o databases/postgresql18-server postgresql17-serverSelect the LZ4, NLS, OPTIMIZED_CFLAGS, SSL, TZDATA, XML, and ZSTD options.
$ portmaster -o databases/postgresql18-contrib postgresql17-contribSelect the OPENSSL, XML, and ZSTD options.
$ pkg autoremove $ pkg clean $ rm -rv /usr/ports/distfiles/* /var/cache/pkg/*
$ service postgresql initdb
local all all trust
# ldd /var/jail/usr/local/bin/postgres
/var/jail/usr/local/bin/postgres:
libthr.so.3 => /lib/libthr.so.3 (0x800d1c000)
libintl.so.8 => /usr/local/lib/libintl.so.8 (0x800d47000)
libssl.so.8 => /var/jail/usr/lib/libssl.so.8 (0x800d54000)
libcrypto.so.8 => not found (0)
libm.so.5 => /lib/libm.so.5 (0x800fc6000)
libicui18n.so.64 => not found (0)
libicuuc.so.64 => not found (0)
libc.so.7 => /lib/libc.so.7 (0x800ff8000)
libcrypto.so.8 => not found (0)
[/var/jail/] libssl.so.8 /var/jail/usr/lib/libssl.so.8 libcrypto.so.8 /var/jail/lib/libcrypto.so.8 libicui18n.so.64 /var/jail/usr/local/lib/libicui18n.so.64 libicuuc.so.64 /var/jail/usr/local/lib/libicuuc.so.64 libicudata.so.64 /var/jail/usr/local/lib/libicudata.so.64
$ su - postgres
# kill `head -1 /var/db/postgres/data17/postmaster.pid`Repeat this on all secondaries as well.
# cp -aiv /var/db/postgres/data17 /var/db/postgres/data17.save
# export LB_LIBRARY_PATH="/var/jail/usr/local/lib"
# cp -aiv data17/postgresql.auto.conf . # cp -aiv data17/standby.signal .
# pg_checksums -d -P -v data18
# pg_upgrade -b /var/jail/usr/local/bin -B /usr/local/bin -d /var/db/postgres/data17 -D /var/db/postgres/data18 -j 2 -k -vIf everything went ok, pg_upgrade places
# pg_checksums -e -P -v data18
# exit
$ service postgresql start
$ psql -c "SELECT pg_create_physical_replication_slot('server2')" postgres postgres
$ service postgresql stop
$ rsync --archive --delete --hard-links --size-only --no-inc-recursive --verbose /var/db/postgres/data17 /var/db/postgres/data18 server2:/var/db/postgresRepeat this for all secondaries.
# mv -v postgresql.auto.conf standby.signal data18/
$ service postgresql start
$ PGUSER=postgres vacuumdb --all --analyzeIf you just updated to a PostgreSQL version before 14.0, pg_upgrade created a shell script instead:
$ PGUSER=postgres ./analyze_new_cluster.sh
$ umount /var/jail/dev $ chflags -R noschg /var/jail $ rm -r /var/jail /usr/freebsd-dist
$ rm -r analyze_new_cluster.sh delete_old_cluster.sh /var/db/postgres/data17