Skip to content

Database Backup

Database Backup #17

Workflow file for this run

name: Database Backup
# Scheduled and on-demand PostgreSQL backups.
# - Runs every day at 03:00 UTC.
# - Can be triggered manually via the "Run workflow" button (workflow_dispatch).
# - Streams a compressed pg_dump to S3, enforces the retention policy, and
# verifies the freshest backup by restoring it into a throwaway database.
# - On failure, posts an alert to Slack (if SLACK_WEBHOOK_URL is configured).
on:
schedule:
# 03:00 UTC daily.
- cron: '0 3 * * *'
workflow_dispatch:
inputs:
verify:
description: 'Verify the latest backup after creating it'
type: boolean
default: true
verify_only:
description: 'Skip the backup and only verify the latest existing backup'
type: boolean
default: false
concurrency:
group: db-backup
cancel-in-progress: false
jobs:
backup:
name: Backup PostgreSQL
runs-on: ubuntu-latest
timeout-minutes: 30
env:
DATABASE_URL: ${{ secrets.BACKUP_DATABASE_URL }}
BACKUP_S3_BUCKET: ${{ secrets.BACKUP_S3_BUCKET }}
BACKUP_S3_PREFIX: ${{ vars.BACKUP_S3_PREFIX || 'aethermint/db' }}
BACKUP_S3_ENDPOINT: ${{ vars.BACKUP_S3_ENDPOINT }}
AWS_ACCESS_KEY_ID: ${{ secrets.BACKUP_AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.BACKUP_AWS_SECRET_ACCESS_KEY }}
AWS_REGION: ${{ vars.BACKUP_AWS_REGION || 'us-east-1' }}
RETAIN_DAILY: ${{ vars.RETAIN_DAILY || '7' }}
RETAIN_WEEKLY: ${{ vars.RETAIN_WEEKLY || '4' }}
RETAIN_MONTHLY: ${{ vars.RETAIN_MONTHLY || '6' }}
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
ALERT_EMAIL_WEBHOOK: ${{ secrets.ALERT_EMAIL_WEBHOOK }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install PostgreSQL 16 client
run: |
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/pgdg.gpg
sudo apt-get update
sudo apt-get install -y postgresql-client-16
- name: Verify AWS CLI
run: aws --version
- name: Run backup
run: |
ARGS=""
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
if [ "${{ inputs.verify_only }}" = "true" ]; then
ARGS="--verify-only"
elif [ "${{ inputs.verify }}" = "false" ]; then
ARGS="--no-verify"
fi
fi
chmod +x scripts/backup-db.sh
./scripts/backup-db.sh $ARGS
- name: Notify on failure
if: failure()
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
run: |
if [ -n "$SLACK_WEBHOOK_URL" ]; then
curl -fsS -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"🔴 AetherMint DB backup workflow failed — run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\"}" \
"$SLACK_WEBHOOK_URL" || echo "Slack notification failed"
else
echo "SLACK_WEBHOOK_URL not set; skipping Slack notification"
fi