{ config, pkgs, ... }: let project = "majxbigjafpzayzboxsf"; poolerHost = "aws-1-eu-west-1.pooler.supabase.com"; outDir = "/var/backup/fueltide-supabase"; # retain local dumps for this many days; borg handles offsite retention retainDays = 1; # match the upstream Supabase Postgres major version pg = pkgs.postgresql_17; in { sops.secrets.fueltide-supabase-db-password = { }; systemd.tmpfiles.rules = [ "d ${outDir} 0700 root root -" ]; systemd.services.fueltide-backup = { description = "Dump upstream Supabase database for ${project}"; path = [ pg pkgs.coreutils pkgs.findutils ]; serviceConfig = { Type = "oneshot"; User = "root"; LoadCredential = "db-password:${config.sops.secrets.fueltide-supabase-db-password.path}"; }; script = '' set -euo pipefail export PGPASSWORD PGPASSWORD=$(cat "$CREDENTIALS_DIRECTORY/db-password") export PGHOST="${poolerHost}" export PGPORT=5432 export PGUSER="postgres.${project}" export PGDATABASE=postgres TS=$(date -u +%Y%m%dT%H%M%SZ) OUT="${outDir}/$TS" mkdir -p "$OUT" chmod 700 "$OUT" # cluster roles (Supabase-managed roles already exist on a fresh project; # restore errors for those are expected and benign) pg_dumpall --roles-only --no-role-passwords > "$OUT/roles.sql" # schema: tables, functions, triggers, RLS policies, views, extensions pg_dump --schema-only --no-owner --no-privileges > "$OUT/schema.sql" # data: all rows (includes auth.users, storage.objects metadata, etc.) pg_dump --data-only --no-owner > "$OUT/data.sql" ( cd "$OUT" && sha256sum *.sql > sha256.txt ) find "${outDir}" -mindepth 1 -maxdepth 1 -type d \ -mtime +${toString retainDays} -exec rm -rf {} + ''; }; systemd.timers.fueltide-backup = { wantedBy = [ "timers.target" ]; timerConfig = { OnCalendar = "*-*-* 02:30:00"; Persistent = true; RandomizedDelaySec = "10m"; }; }; }