{ config, lib, pkgs, ... }: with lib; let cfgs = config.services.podman-postgresql; conf = import ./vars.nix; in { options = { services.podman-postgresql = mkOption { description = mdDoc "Configure a single database postgresql instance running in podman."; default = {}; type = types.attrsOf (types.submodule ({ config, ... }: { options = let name = config._module.args.name; in { enable = mkEnableOption (mdDoc "podman-postgresql"); image = mkOption { description = mdDoc "The postgresql image to use."; type = types.str; default = "docker.io/library/postgres:alpine"; example = "docker.io/library/postgres:15-alpine"; }; database = mkOption { description = "The name of the database to be created."; type = types.str; default = name; }; user = mkOption { description = "The owner of the database."; type = types.str; default = name; }; passwordFile = mkOption { description = "The password file for the database user."; type = types.path; }; port = mkOption { description = "The port to serve postgresql on the host."; type = types.int; example = 54320; }; backupPath = mkOption { description = "The path to backup the database to."; type = types.str; default = "/var/backup/postgresql"; }; backupInterval = mkOption { description = "The interval to backup the database"; type = types.str; default = "hourly"; example = "daily"; }; }; })); }; }; config = mkIf (any (cfg: cfg.enable) (attrValues cfgs)) { virtualisation.oci-containers.containers = mkMerge (mapAttrsToList (_: cfg: { "postgresql-${cfg.database}" = { image = cfg.image; ports = [ "${(toString cfg.port)}:5432" ]; environment = { POSTGRES_USER = cfg.user; POSTGRES_DB = cfg.database; POSTGRES_PASSWORD_FILE = cfg.passwordFile; }; volumes = [ "/var/lib/postgresql/${cfg.database}:/var/lib/postgresql/data" "${cfg.passwordFile}:${cfg.passwordFile}" ]; extraOptions = conf.podman.extraOptions ++ [ "--health-cmd=pg_isready -d ${cfg.database} -U ${cfg.user}" "--health-start-period=10s" ]; }; }) cfgs); system.activationScripts = mkMerge (mapAttrsToList (_: cfg: { "makePsql${cfg.database}Dirs" = lib.stringAfter [ "var" ] '' mkdir -p "/var/lib/postgresql/${cfg.database}" "${cfg.backupPath}/${cfg.database}" ''; }) cfgs); systemd = mkMerge (mapAttrsToList (_: cfg: { services."podman-postgresql-${cfg.database}-backup" = { description = "Backup of ${cfg.database} database"; requisite = [ "podman-postgresql-${cfg.database}.service" ]; serviceConfig = { ExecStart = "${pkgs.bash}/bin/bash -c '${pkgs.podman}/bin/podman exec postgresql-${cfg.database} pg_dumpall -c -U ${cfg.user} | ${pkgs.zstd}/bin/zstd -o ${cfg.backupPath}/${cfg.database}/\$(${pkgs.coreutils}/bin/date +%%F_%%R).sql.zst'" ; Type = "oneshot"; }; }; timers."podman-postgresql-${cfg.database}-backup" = { timerConfig = { OnCalendar = cfg.backupInterval; }; wantedBy = [ "podman-postgresql-${cfg.database}.service" ]; }; }) cfgs); }; } # vim: set et ts=2 sw=2 ai: