feat(sprint-6): Phase 1 — Production deployment infrastructure (IONOS)
- docker-compose.prod.yml: production Docker Compose with health checks, logging, restart policies, resource limits - deploy/nginx/cannamanage.conf: Nginx reverse proxy with TLS, CSP, security headers, rate limiting - deploy/.env.production.example: environment template for secrets - deploy/backup.sh: GPG-encrypted daily/weekly PostgreSQL backup with retention - deploy/deploy.sh: manual deploy script with health check verification - .gitea/workflows/deploy.yml: Gitea Actions CI/CD pipeline (test + deploy) - application-production.properties: Spring Boot production profile (no stacktraces, Swagger disabled, Stripe) - .gitignore: added .env to prevent accidental secret commits
This commit is contained in:
Executable
+47
@@ -0,0 +1,47 @@
|
||||
#!/bin/bash
|
||||
# =============================================================================
|
||||
# Cannamanage — Automated PostgreSQL Backup (GPG encrypted)
|
||||
# =============================================================================
|
||||
# Usage: ./deploy/backup.sh
|
||||
# Cron: 0 2 * * * /opt/cannamanage/deploy/backup.sh >> /var/log/cannamanage-backup.log 2>&1
|
||||
# =============================================================================
|
||||
set -euo pipefail
|
||||
|
||||
# Load environment
|
||||
if [ -f /opt/cannamanage/.env ]; then
|
||||
set -a
|
||||
source /opt/cannamanage/.env
|
||||
set +a
|
||||
fi
|
||||
|
||||
BACKUP_DIR="/opt/cannamanage/backups"
|
||||
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||||
DB_CONTAINER="cannamanage-db-1"
|
||||
GPG_RECIPIENT="${BACKUP_GPG_RECIPIENT:-cannamanage-backup}"
|
||||
RETENTION_DAYS="${BACKUP_RETENTION_DAYS:-7}"
|
||||
RETENTION_WEEKS="${BACKUP_RETENTION_WEEKS:-4}"
|
||||
|
||||
mkdir -p "$BACKUP_DIR/daily" "$BACKUP_DIR/weekly"
|
||||
|
||||
echo "[$(date)] Starting backup..."
|
||||
|
||||
# Dump database + compress + encrypt
|
||||
docker exec "$DB_CONTAINER" pg_dump -U "${DB_USER:-cannamanage}" "${DB_NAME:-cannamanage}" | \
|
||||
gzip | \
|
||||
gpg --encrypt --recipient "$GPG_RECIPIENT" --trust-model always \
|
||||
> "$BACKUP_DIR/daily/backup_${TIMESTAMP}.sql.gz.gpg"
|
||||
|
||||
BACKUP_SIZE=$(du -h "$BACKUP_DIR/daily/backup_${TIMESTAMP}.sql.gz.gpg" | cut -f1)
|
||||
echo "[$(date)] Daily backup completed: backup_${TIMESTAMP}.sql.gz.gpg ($BACKUP_SIZE)"
|
||||
|
||||
# Weekly backup on Sundays
|
||||
if [ "$(date +%u)" -eq 7 ]; then
|
||||
cp "$BACKUP_DIR/daily/backup_${TIMESTAMP}.sql.gz.gpg" "$BACKUP_DIR/weekly/"
|
||||
echo "[$(date)] Weekly backup copied"
|
||||
fi
|
||||
|
||||
# Retention: keep N daily, M weekly
|
||||
find "$BACKUP_DIR/daily" -name "*.sql.gz.gpg" -mtime +"$RETENTION_DAYS" -delete
|
||||
find "$BACKUP_DIR/weekly" -name "*.sql.gz.gpg" -mtime +$((RETENTION_WEEKS * 7)) -delete
|
||||
|
||||
echo "[$(date)] Backup completed successfully. Retention: ${RETENTION_DAYS}d daily, ${RETENTION_WEEKS}w weekly"
|
||||
Reference in New Issue
Block a user