Upgrading Postgresql on NixOS
I fail to remember this every time, so I'm putting it here forever!
I typically run this outside a NixOS Container, hence the weird uid/gid business.
NOTE: Update your Nix configuration with the new and old path /postgres version valuesprior to performing these tasks, but do NOT perform the switch. We will do that as needed.a part of the below process.
# Set variables
pgsql_old=16
pgsql_new=17
pgsql_basepath=/var/lib/postgresql
postgres_uid=71
postgres_gid=71
# Stop postgres service
systemctl stop postgresql.service
# Or, in my case, stop the container
nixos-container stop <container-name>
# Delete existing new directory if it exists, then create empty
### DANGER - HERE BE DRAGONS ###
### MAKE SURE YOU HAVE BACKUPS ###
rm -rfv "$pgsql_basepath/$pgsql_new"
install -d -m 0700 -o postgres$postgres_uid -g $postgres_gid "$pgsql_basepath/$pgsql_new"
# If running inside a base host that doesn't have the postgres user, create it temporarily
if [ ! $(getent group postgres) ]; then
tempgroup=true
groupadd -rg $postgres_gid postgres
fi
if [ ! $(getent passwd postgres) ]; then
tempuser=true
useradd -rg postgres -u $postgres_uid postgres
fi
# Initialize new database
nix-shell -p "/var/lib/postgresql/17"postgresql_${pgsql_new}_jit" --command "sudo -u postgres /nix/store/infd8iz1j1n8shfvcgf6cdqcavynaya3-postgresql-and-plugins-17.5/bin/initdb -D /var/lib/postgresql/17$pgsql_basepath/$pgsql_new"
# Locate postgres binaries for upgrade
PGBINOLD=$(nix-shell -p "postgresql_${pgsql_old}_jit" --command 'dirname $(which postgres)')
PGBINNEW=$(nix-shell -p "postgresql_${pgsql_new}_jit" --command 'dirname $(which postgres)')
# Change to old postgres directory for pg_upgrade
cd "$pgsql_basepath/$pgsql_old"
# Run upgrade. Be sure to watch output, it will print more instructions for you, likely a vacuum.
nix-shell -p "postgresql_${pgsql_new}_jit" --command "sudo -u postgres /nix/store/infd8iz1j1n8shfvcgf6cdqcavynaya3-postgresql-and-plugins-17.5/bin/pg_upgrade -k -b /nix/store/9rl8l079qbn42a69f26qrq1hm9zs8jj6-postgresql-and-plugins-16.9/bin$PGBINOLD -B /nix/store/infd8iz1j1n8shfvcgf6cdqcavynaya3-postgresql-and-plugins-17.5/bin$PGBINNEW -d /var/lib/postgresql/16$pgsql_basepath/$pgsql_old -D /var/lib/postgresql/17$pgsql_basepath/$pgsql_new"
# Back to homedir...
cd
# Run the switch. This will start your service or container.
nixos-rebuild switch
# Run post tasks. Adjust based on the output of the upgrade command.
nix-shell -p "postgresql_${pgsql_new}_jit" --command "sudo -u postgres vacuumdb --all --analyze-in-stages"
# Destroy old cluster
### DANGER - HERE BE DRAGONS ###
### MAKE SURE YOU HAVE BACKUPS ###
rm -rfv "$pgsql_basepath/$pgsql_old"