From d532eda1096fa3d8f95a79b256bd9291d0d21d57 Mon Sep 17 00:00:00 2001 From: "Chinmay D. Pai" Date: Mon, 30 Sep 2024 12:01:57 +0530 Subject: [PATCH] feat: add service for postgresql with upgrade and backup * replace per-app postgresql configuration with a single, global postgres setup * add backup configuration to backup using restic * add cluster upgrade script based on the NixOS Manual: https://nixos.org/manual/nixos/stable/#module-services-postgres-upgrading Signed-off-by: Chinmay D. Pai --- modules/nixos/services/postgresql/default.nix | 97 +++++++++++++++++++ .../nixos/services/vaultwarden/default.nix | 3 - systems/x86_64-linux/bicboye/default.nix | 6 ++ 3 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 modules/nixos/services/postgresql/default.nix diff --git a/modules/nixos/services/postgresql/default.nix b/modules/nixos/services/postgresql/default.nix new file mode 100644 index 0000000..9dc8c7f --- /dev/null +++ b/modules/nixos/services/postgresql/default.nix @@ -0,0 +1,97 @@ +{ + config, + lib, + pkgs, + ... +}: { + options.snowflake.services.postgresql = { + enable = lib.mkEnableOption "Enable postgresql service"; + + package = lib.mkOption { + type = lib.types.package; + default = pkgs.postgresql_14; + description = "Package to use as a root directory for the static site"; + }; + + backup.enable = lib.mkEnableOption "Enable backup service for postgresql databases"; + upgrade.enable = lib.mkEnableOption "Enable upgrade-pg-cluster script for postgresql"; + }; + + config = let + cfg = config.snowflake.services.postgresql; + in + lib.mkIf cfg.enable { + services.postgresql = { + enable = true; + package = cfg.package; + }; + + snowflake.services.backup.config.postgresql = let + compressSuffix = ".zstd"; + compressCmd = "${pkgs.zstd}/bin/zstd -c"; + + baseDir = "/tmp/postgres-backup"; + + mkSqlPath = prefix: suffix: "/${baseDir}/all${prefix}.sql${suffix}"; + curFile = mkSqlPath "" compressSuffix; + prevFile = mkSqlPath ".prev" compressSuffix; + inProgressFile = mkSqlPath ".in-progress" compressSuffix; + in + lib.mkIf cfg.backup.enable { + dynamicFilesFrom = '' + set -e -o pipefail + + mkdir -p ${baseDir} + + # Ensure that the backup folder is only readable by the postgres user + umask 0077 + + if [ -e ${curFile} ]; then + rm -f ${prevFile} + mv ${curFile} ${prevFile} + fi + + ${config.security.sudo.package}/bin/sudo -u postgres ${config.services.postgresql.package}/bin/pg_dumpall \ + | ${compressCmd} \ + > ${inProgressFile} + + mv ${inProgressFile} ${curFile} + + echo ${curFile} + ''; + }; + + # NOTE: login with `sudo su -` and run `upgrade-pg-cluster` to perform + # the upgrade. Ensure that you run `VACUUMDB` commands after the upgrade, + # and then update the postgres package version in the service config. + environment.systemPackages = lib.mkIf cfg.upgrade.enable [ + (let + newPostgres = pkgs.postgresql_16.withPackages (ps: [ + # Immich requires pgvecto-rs + ps.pgvecto-rs + ]); + in + pkgs.writeScriptBin "upgrade-pg-cluster" '' + set -eux + # It's perhaps advisable to stop all services that depend on postgresql + systemctl stop postgresql + + export NEWDATA="/var/lib/postgresql/${newPostgres.psqlSchema}" + + export NEWBIN="${newPostgres}/bin" + + export OLDDATA="${config.services.postgresql.dataDir}" + export OLDBIN="${config.services.postgresql.package}/bin" + + install -d -m 0700 -o postgres -g postgres "$NEWDATA" + cd "$NEWDATA" + sudo -u postgres $NEWBIN/initdb -D "$NEWDATA" + + sudo -u postgres $NEWBIN/pg_upgrade \ + --old-datadir "$OLDDATA" --new-datadir "$NEWDATA" \ + --old-bindir $OLDBIN --new-bindir $NEWBIN \ + "$@" + '') + ]; + }; +} diff --git a/modules/nixos/services/vaultwarden/default.nix b/modules/nixos/services/vaultwarden/default.nix index daeba0e..45e988f 100644 --- a/modules/nixos/services/vaultwarden/default.nix +++ b/modules/nixos/services/vaultwarden/default.nix @@ -51,9 +51,6 @@ }; services.postgresql = { - # NOTE: To upgrade postgresql to a newer version, refer: - # https://nixos.org/manual/nixos/stable/#module-services-postgres-upgrading - package = pkgs.postgresql_14; ensureDatabases = ["vaultwarden"]; ensureUsers = [ { diff --git a/systems/x86_64-linux/bicboye/default.nix b/systems/x86_64-linux/bicboye/default.nix index 2e5e9bf..015a380 100644 --- a/systems/x86_64-linux/bicboye/default.nix +++ b/systems/x86_64-linux/bicboye/default.nix @@ -158,6 +158,12 @@ adminUser = "chinmay"; }; + postgresql = { + enable = true; + backup.enable = true; + upgrade.enable = true; + }; + vaultwarden = { enable = true; domain = "bw.deku.moe";