selfprivacy-nixos-config/postgresql/upgrade12to16.nix
2024-12-24 20:46:59 +03:00

135 lines
4.7 KiB
Nix

{ config, lib, pkgs, ... }:
let
cfg = config.services.postgresqlUpgrade12to16;
mkIf = lib.mkIf;
mkOption = lib.mkOption;
types = lib.types;
optional = lib.optional;
in
{
options.services.postgresqlUpgrade12to16 = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Enables an automatic one-shot upgrade from PostgreSQL 12 to 16 if a
version 12 data directory is found. This will run pg_upgrade and may
take time depending on database size. Use with caution.
'';
};
dataDir12 = mkOption {
type = types.str;
default = "/var/lib/postgresql/12";
description = "Location of the old PostgreSQL 12 data directory.";
};
dataDir16 = mkOption {
type = types.str;
default = "/var/lib/postgresql/16";
description = "Location of the new PostgreSQL 16 data directory.";
};
pleromaEnabled = mkOption {
type = types.bool;
default = false;
description = ''
Whether Pleroma service is present and needs to be stopped/started
during the PostgreSQL upgrade process.
'';
};
};
config = mkIf cfg.enable {
assertions = [
{
assertion = config.services.postgresql.package == pkgs.postgresql_16;
message = "PostgreSQL package must be set to postgresql_16 for the upgrade to work correctly.";
}
{
assertion = config.services.postgresql.dataDir == cfg.dataDir16;
message = "PostgreSQL data directory must be set to ${cfg.dataDir16} for the upgrade to work correctly. The current value is ${config.services.postgresql.dataDir}.";
}
];
systemd.services."postgresql-upgrade12to16" = {
description = "Upgrade PostgreSQL 12 database to PostgreSQL 16";
wantedBy = [ "multi-user.target" ];
before = [ "postgresql.service" ];
after = [ "network-online.target" ];
wants = [ "network-online.target" ];
serviceConfig = {
Type = "oneshot";
ExecStartPre =
# Stop Pleroma only if pleromaEnabled is true
optional cfg.pleromaEnabled "${pkgs.writeShellScript "postgresql-upgrade12to16-pre.sh" ''
if [ -d "${cfg.dataDir12}" ] && [ ! -d "${cfg.dataDir16}" ]; then
${pkgs.systemd}/bin/systemctl stop pleroma.service
fi
''
}";
ExecStart = "${pkgs.writeShellScript "postgresql-upgrade12to16.sh" ''
set -e
oldDataDir="${cfg.dataDir12}"
newDataDir="${cfg.dataDir16}"
# Only upgrade if old data directory exists, and the new one doesn't yet
if [ -d "$oldDataDir" ] && [ ! -d "$newDataDir" ]; then
echo "Detected PostgreSQL 12 data directory at $oldDataDir"
echo "Upgrading to PostgreSQL 16 data directory at $newDataDir"
# Stop the old PostgreSQL if it's running
if systemctl is-active --quiet postgresql.service; then
systemctl stop postgresql.service
fi
# Create the new data directory (if not already present)
mkdir -p "$newDataDir"
chown -R postgres:postgres "$(dirname "$newDataDir")"
# Create a temporary working directory
tempDir=$(mktemp -d)
chown -R postgres:postgres "$tempDir"
trap 'rm -rf "$tempDir"' EXIT
# Change to the temporary working directory
cd "$tempDir"
# Initialize the new PostgreSQL 16 data directory
${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql_16.out}/bin/initdb -D "$newDataDir" -U postgres
# Run pg_upgrade as the postgres user
${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql_16.out}/bin/pg_upgrade \
--old-datadir "$oldDataDir" \
--new-datadir "$newDataDir" \
--old-bindir ${pkgs.postgresql_12.out}/bin \
--new-bindir ${pkgs.postgresql_16.out}/bin \
--jobs "$(nproc)" \
--link \
--verbose
touch "$newDataDir/.sp_migrated"
echo "PostgreSQL upgrade from 12 to 16 completed."
else
echo "No PostgreSQL 12 data directory detected or already upgraded. Skipping."
fi
''}";
# Start Pleroma only if pleromaEnabled is true
ExecStartPost =
optional cfg.pleromaEnabled "${pkgs.writeShellScript "postgresql-upgrade12to16-post.sh" ''
if test -e "${cfg.dataDir16}/.sp_migrated"; then
${pkgs.systemd}/bin/systemctl start --no-block pleroma.service
rm -f "${cfg.dataDir16}/.sp_migrated"
fi
''
}";
};
};
};
}