Barazo Docker Compose templates for self-hosting
barazo.forum
1#!/usr/bin/env bash
2# Barazo Backup Script
3#
4# Creates a compressed PostgreSQL backup with timestamp.
5# Optionally encrypts with age for off-server storage.
6#
7# Usage:
8# ./scripts/backup.sh # Plain backup (local storage only)
9# ./scripts/backup.sh --encrypt # Encrypted backup (requires BACKUP_PUBLIC_KEY)
10#
11# Environment:
12# BACKUP_DIR Backup directory (default: ./backups)
13# BACKUP_RETAIN_DAYS Days to keep old backups (default: 7)
14# BACKUP_PUBLIC_KEY age public key for encryption (required with --encrypt)
15# COMPOSE_FILE Docker Compose file (default: docker-compose.yml)
16
17set -euo pipefail
18
19BACKUP_DIR="${BACKUP_DIR:-./backups}"
20BACKUP_RETAIN_DAYS="${BACKUP_RETAIN_DAYS:-7}"
21COMPOSE_FILE="${COMPOSE_FILE:-docker-compose.yml}"
22ENCRYPT=false
23
24# Parse arguments
25for arg in "$@"; do
26 case "$arg" in
27 --encrypt) ENCRYPT=true ;;
28 --help|-h)
29 echo "Usage: $0 [--encrypt]"
30 echo ""
31 echo "Options:"
32 echo " --encrypt Encrypt backup with age (requires BACKUP_PUBLIC_KEY)"
33 echo ""
34 echo "Environment variables:"
35 echo " BACKUP_DIR Backup directory (default: ./backups)"
36 echo " BACKUP_RETAIN_DAYS Days to keep old backups (default: 7)"
37 echo " BACKUP_PUBLIC_KEY age public key for encryption"
38 echo " COMPOSE_FILE Docker Compose file (default: docker-compose.yml)"
39 exit 0
40 ;;
41 *)
42 echo "Unknown argument: $arg" >&2
43 exit 1
44 ;;
45 esac
46done
47
48# Validate encryption prerequisites
49if [ "$ENCRYPT" = true ] && [ -z "${BACKUP_PUBLIC_KEY:-}" ]; then
50 echo "Error: --encrypt requires BACKUP_PUBLIC_KEY environment variable" >&2
51 exit 1
52fi
53
54if [ "$ENCRYPT" = true ] && ! command -v age &>/dev/null; then
55 echo "Error: age is required for encryption. Install: https://github.com/FiloSottile/age" >&2
56 exit 1
57fi
58
59# Create backup directory
60mkdir -p "$BACKUP_DIR"
61
62TIMESTAMP=$(date +%Y%m%d-%H%M%S)
63BACKUP_FILE="$BACKUP_DIR/barazo-backup-$TIMESTAMP.sql.gz"
64
65echo "Starting backup at $(date)"
66
67# Check PostgreSQL is running
68if ! docker compose -f "$COMPOSE_FILE" exec -T postgres pg_isready -U "${POSTGRES_USER:-barazo}" &>/dev/null; then
69 echo "Error: PostgreSQL is not running" >&2
70 exit 1
71fi
72
73# Dump PostgreSQL
74echo "Dumping PostgreSQL..."
75docker compose -f "$COMPOSE_FILE" exec -T postgres \
76 pg_dump -U "${POSTGRES_USER:-barazo}" "${POSTGRES_DB:-barazo}" \
77 | gzip > "$BACKUP_FILE"
78
79BACKUP_SIZE=$(du -h "$BACKUP_FILE" | cut -f1)
80echo "Backup created: $BACKUP_FILE ($BACKUP_SIZE)"
81
82# Encrypt if requested
83if [ "$ENCRYPT" = true ]; then
84 echo "Encrypting backup..."
85 age -r "$BACKUP_PUBLIC_KEY" -o "${BACKUP_FILE}.age" "$BACKUP_FILE"
86 rm "$BACKUP_FILE"
87 BACKUP_FILE="${BACKUP_FILE}.age"
88 echo "Encrypted backup: $BACKUP_FILE"
89fi
90
91# Clean up old backups
92if [ "$BACKUP_RETAIN_DAYS" -gt 0 ]; then
93 DELETED=$(find "$BACKUP_DIR" -name "barazo-backup-*" -mtime +"$BACKUP_RETAIN_DAYS" -delete -print | wc -l | tr -d ' ')
94 if [ "$DELETED" -gt 0 ]; then
95 echo "Cleaned up $DELETED old backup(s) (older than $BACKUP_RETAIN_DAYS days)"
96 fi
97fi
98
99echo "Backup complete at $(date)"