From 61bdfb1a4b9b4dd96ed718046f65d2e7bb54cc4b Mon Sep 17 00:00:00 2001 From: Mike Reeves Date: Thu, 9 Apr 2026 10:29:10 -0400 Subject: [PATCH] Add daily PostgreSQL database backup - pg_dumpall piped through gzip, stored in /nsm/backup/ - Runs daily at 00:05 (4 minutes after config backup) - 7-day retention matching existing config backup policy - Skips gracefully if container isn't running --- salt/backup/config_backup.sls | 20 +++++++++++++ salt/backup/tools/sbin/so-postgres-backup | 36 +++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 salt/backup/tools/sbin/so-postgres-backup diff --git a/salt/backup/config_backup.sls b/salt/backup/config_backup.sls index a09c67b1b..c8e342463 100644 --- a/salt/backup/config_backup.sls +++ b/salt/backup/config_backup.sls @@ -32,3 +32,23 @@ so_config_backup: - daymonth: '*' - month: '*' - dayweek: '*' + +postgres_backup_script: + file.managed: + - name: /usr/sbin/so-postgres-backup + - user: root + - group: root + - mode: 755 + - source: salt://backup/tools/sbin/so-postgres-backup + +# Add postgres database backup +so_postgres_backup: + cron.present: + - name: /usr/sbin/so-postgres-backup > /dev/null 2>&1 + - identifier: so_postgres_backup + - user: root + - minute: '5' + - hour: '0' + - daymonth: '*' + - month: '*' + - dayweek: '*' diff --git a/salt/backup/tools/sbin/so-postgres-backup b/salt/backup/tools/sbin/so-postgres-backup new file mode 100644 index 000000000..c577f7b59 --- /dev/null +++ b/salt/backup/tools/sbin/so-postgres-backup @@ -0,0 +1,36 @@ +#!/bin/bash +# +# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one +# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at +# https://securityonion.net/license; you may not use this file except in compliance with the +# Elastic License 2.0. + +. /usr/sbin/so-common + +TODAY=$(date '+%Y_%m_%d') +BACKUPDIR=/nsm/backup +BACKUPFILE="$BACKUPDIR/so-postgres-backup-$TODAY.sql.gz" +MAXBACKUPS=7 + +mkdir -p $BACKUPDIR + +# Skip if already backed up today +if [ -f "$BACKUPFILE" ]; then + exit 0 +fi + +# Skip if container isn't running +if ! docker ps --format '{{.Names}}' | grep -q '^so-postgres$'; then + exit 0 +fi + +# Dump all databases and roles, compress +docker exec so-postgres pg_dumpall -U postgres | gzip > "$BACKUPFILE" + +# Retention cleanup +NUMBACKUPS=$(find $BACKUPDIR -type f -name "so-postgres-backup*" | wc -l) +while [ "$NUMBACKUPS" -gt "$MAXBACKUPS" ]; do + OLDEST=$(find $BACKUPDIR -type f -name "so-postgres-backup*" -printf '%T+ %p\n' | sort | head -n 1 | awk -F" " '{print $2}') + rm -f "$OLDEST" + NUMBACKUPS=$(find $BACKUPDIR -type f -name "so-postgres-backup*" | wc -l) +done