Initial commit
This commit is contained in:
118
project-docs/setup_prod_database.sh
Normal file
118
project-docs/setup_prod_database.sh
Normal file
@@ -0,0 +1,118 @@
|
||||
#!/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 "=============================================="
|
||||
Reference in New Issue
Block a user