119 lines
4.7 KiB
Bash
119 lines
4.7 KiB
Bash
#!/bin/bash
|
|
# =============================================================================
|
|
# Life OS - PROD Database Setup
|
|
# Backs up lifeos_dev (R1) and restores to lifeos_prod
|
|
# Run AFTER DEV is fully tested and confirmed working
|
|
# Run on: defiant-01 as root
|
|
# =============================================================================
|
|
|
|
set -e
|
|
|
|
DB_CONTAINER="lifeos-db"
|
|
DB_USER="postgres"
|
|
DEV_DB="lifeos_dev"
|
|
PROD_DB="lifeos_prod"
|
|
BACKUP_DIR="/opt/lifeos/backups"
|
|
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
|
BACKUP_FILE="$BACKUP_DIR/dev_to_prod_${TIMESTAMP}.sql"
|
|
|
|
section() {
|
|
echo ""
|
|
echo "=============================================="
|
|
echo " $1"
|
|
echo "=============================================="
|
|
}
|
|
|
|
# =============================================================================
|
|
# 1. Verify prerequisites
|
|
# =============================================================================
|
|
section "1. Verifying prerequisites"
|
|
|
|
if ! docker ps | grep -q "$DB_CONTAINER"; then
|
|
echo "ERROR: $DB_CONTAINER is not running"
|
|
exit 1
|
|
fi
|
|
echo "OK: $DB_CONTAINER is running"
|
|
|
|
mkdir -p "$BACKUP_DIR"
|
|
|
|
# =============================================================================
|
|
# 2. Backup current lifeos_prod (safety net)
|
|
# =============================================================================
|
|
section "2. Backing up current lifeos_prod (R0 safety copy)"
|
|
|
|
docker exec $DB_CONTAINER pg_dump -U $DB_USER $PROD_DB | gzip > "$BACKUP_DIR/prod_r0_backup_${TIMESTAMP}.sql.gz"
|
|
echo "OK: R0 prod backup saved to $BACKUP_DIR/prod_r0_backup_${TIMESTAMP}.sql.gz"
|
|
|
|
# =============================================================================
|
|
# 3. Backup lifeos_dev (source for PROD)
|
|
# =============================================================================
|
|
section "3. Backing up lifeos_dev (R1 source)"
|
|
|
|
docker exec $DB_CONTAINER pg_dump -U $DB_USER --clean --if-exists $DEV_DB > "$BACKUP_FILE"
|
|
echo "OK: DEV backup saved to $BACKUP_FILE"
|
|
|
|
# =============================================================================
|
|
# 4. Drop and recreate lifeos_prod with R1 data
|
|
# =============================================================================
|
|
section "4. Replacing lifeos_prod with lifeos_dev contents"
|
|
|
|
echo "WARNING: This will destroy the current lifeos_prod database."
|
|
echo "R0 backup is at: $BACKUP_DIR/prod_r0_backup_${TIMESTAMP}.sql.gz"
|
|
read -p "Continue? (yes/no): " CONFIRM
|
|
if [ "$CONFIRM" != "yes" ]; then
|
|
echo "Aborted."
|
|
exit 0
|
|
fi
|
|
|
|
# Drop and recreate prod database
|
|
docker exec $DB_CONTAINER psql -U $DB_USER -c "
|
|
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '$PROD_DB' AND pid <> pg_backend_pid();
|
|
"
|
|
docker exec $DB_CONTAINER psql -U $DB_USER -c "DROP DATABASE IF EXISTS $PROD_DB;"
|
|
docker exec $DB_CONTAINER psql -U $DB_USER -c "CREATE DATABASE $PROD_DB;"
|
|
|
|
# Restore DEV backup into PROD
|
|
docker exec -i $DB_CONTAINER psql -U $DB_USER -d $PROD_DB < "$BACKUP_FILE"
|
|
echo "OK: lifeos_prod now contains R1 schema + data from DEV"
|
|
|
|
# =============================================================================
|
|
# 5. Verify
|
|
# =============================================================================
|
|
section "5. Verification"
|
|
|
|
echo "PROD table row counts:"
|
|
docker exec $DB_CONTAINER psql -U $DB_USER -d $PROD_DB -c "
|
|
SELECT 'domains' as table_name, count(*) FROM domains UNION ALL
|
|
SELECT 'areas', count(*) FROM areas UNION ALL
|
|
SELECT 'projects', count(*) FROM projects UNION ALL
|
|
SELECT 'tasks', count(*) FROM tasks UNION ALL
|
|
SELECT 'notes', count(*) FROM notes UNION ALL
|
|
SELECT 'links', count(*) FROM links UNION ALL
|
|
SELECT 'daily_focus', count(*) FROM daily_focus UNION ALL
|
|
SELECT 'capture', count(*) FROM capture UNION ALL
|
|
SELECT 'context_types', count(*) FROM context_types
|
|
ORDER BY table_name;
|
|
"
|
|
|
|
# =============================================================================
|
|
# 6. Setup automated daily backup cron
|
|
# =============================================================================
|
|
section "6. Setting up automated daily backups"
|
|
|
|
CRON_LINE="0 3 * * * docker exec $DB_CONTAINER pg_dump -U $DB_USER $PROD_DB | gzip > $BACKUP_DIR/prod_\$(date +\\%Y\\%m\\%d).sql.gz && find $BACKUP_DIR -name 'prod_*.sql.gz' -mtime +30 -delete"
|
|
|
|
if crontab -l 2>/dev/null | grep -q "lifeos_prod"; then
|
|
echo "Backup cron already exists, skipping."
|
|
else
|
|
(crontab -l 2>/dev/null; echo "$CRON_LINE") | crontab -
|
|
echo "OK: Daily backup cron installed (3am, 30-day retention)"
|
|
fi
|
|
|
|
echo ""
|
|
echo "=============================================="
|
|
echo " PROD setup complete."
|
|
echo " lifeos_prod now has R1 schema + data."
|
|
echo " R0 backup: $BACKUP_DIR/prod_r0_backup_${TIMESTAMP}.sql.gz"
|
|
echo " Daily backups configured."
|
|
echo "=============================================="
|