Files
stiftung-management-system/deploy-production/migrate-data.sh
2025-09-06 18:31:54 +02:00

235 lines
7.9 KiB
Bash

#!/bin/bash
# Data Migration Script from Synology to Ubuntu Server
# Run this script after the initial deployment is complete
set -e
echo "=== Stiftung Data Migration Script ==="
echo "This script migrates data from Synology NAS to Ubuntu Server"
# Check if running as stiftung user
if [ "$USER" != "stiftung" ]; then
echo "Error: This script must be run as the 'stiftung' user"
echo "Run: su - stiftung"
exit 1
fi
# Check if we're in the right directory
if [ ! -f "docker-compose.prod.yml" ]; then
echo "Error: docker-compose.prod.yml not found"
echo "Make sure you're in the /opt/stiftung directory"
exit 1
fi
# Check if containers are running
if ! docker compose -f docker-compose.prod.yml ps | grep -q "Up"; then
echo "Error: Containers are not running"
echo "Run: ./deploy.sh first"
exit 1
fi
echo "=== Step 1: Preparing for Migration ==="
# Create backup directory
mkdir -p migration-data
cd migration-data
echo "Please upload your backup files to /opt/stiftung/migration-data/"
echo "Expected files:"
echo " - full_backup_YYYYMMDD.json (Django data export)"
echo " - db_backup_YYYYMMDD.sql (PostgreSQL dump)"
echo " - media_backup_YYYYMMDD.tar.gz (Media files)"
echo ""
echo "Press Enter when files are uploaded..."
read
# Verify backup files exist
if ! ls full_backup_*.json >/dev/null 2>&1; then
echo "Error: No Django backup file found (full_backup_*.json)"
exit 1
fi
if ! ls db_backup_*.sql >/dev/null 2>&1; then
echo "Error: No database backup file found (db_backup_*.sql)"
exit 1
fi
if ! ls media_backup_*.tar.gz >/dev/null 2>&1; then
echo "Error: No media backup file found (media_backup_*.tar.gz)"
exit 1
fi
echo "✓ All backup files found"
echo "=== Step 2: Database Migration ==="
echo "Choose migration method:"
echo "1) Load Django JSON backup (recommended for clean migration)"
echo "2) Restore PostgreSQL dump (faster, but may have compatibility issues)"
echo "3) Skip database migration"
read -p "Enter choice (1-3): " migration_choice
case $migration_choice in
1)
echo "Loading Django JSON backup..."
# Copy JSON file to container
JSON_FILE=$(ls full_backup_*.json | head -1)
docker cp "$JSON_FILE" stiftung-web:/tmp/backup.json
# Load data
echo "This may take several minutes..."
docker compose -f ../docker-compose.prod.yml exec web python manage.py loaddata /tmp/backup.json
echo "✓ Django data loaded successfully"
;;
2)
echo "Restoring PostgreSQL dump..."
SQL_FILE=$(ls db_backup_*.sql | head -1)
# Get database credentials from .env
source ../.env
# Drop and recreate database to ensure clean state
docker compose -f ../docker-compose.prod.yml exec db psql -U postgres -c "DROP DATABASE IF EXISTS $POSTGRES_DB;"
docker compose -f ../docker-compose.prod.yml exec db psql -U postgres -c "CREATE DATABASE $POSTGRES_DB OWNER $POSTGRES_USER;"
# Restore data
docker cp "$SQL_FILE" stiftung-db:/tmp/backup.sql
docker compose -f ../docker-compose.prod.yml exec db psql -U $POSTGRES_USER -d $POSTGRES_DB -f /tmp/backup.sql
# Run migrations to ensure schema is up to date
docker compose -f ../docker-compose.prod.yml exec web python manage.py migrate
echo "✓ PostgreSQL data restored successfully"
;;
3)
echo "Skipping database migration"
;;
*)
echo "Invalid choice, skipping database migration"
;;
esac
echo "=== Step 3: Media Files Migration ==="
read -p "Restore media files? (y/n): " restore_media
if [[ $restore_media =~ ^[Yy]$ ]]; then
echo "Restoring media files..."
MEDIA_FILE=$(ls media_backup_*.tar.gz | head -1)
# Extract media files to the correct location
tar -xzf "$MEDIA_FILE" -C ../app/
# Fix permissions
chown -R stiftung:stiftung ../app/media/
echo "✓ Media files restored successfully"
fi
echo "=== Step 4: User Account Migration ==="
echo "Creating superuser account for production..."
echo "Note: You'll need to create a new superuser account"
echo "The old passwords won't work due to different SECRET_KEY"
read -p "Create new superuser now? (y/n): " create_user
if [[ $create_user =~ ^[Yy]$ ]]; then
docker compose -f ../docker-compose.prod.yml exec web python manage.py createsuperuser
fi
echo "=== Step 5: Post-Migration Tasks ==="
# Run any additional migrations for new features
echo "Running migrations for new features..."
docker compose -f ../docker-compose.prod.yml exec web python manage.py migrate
# Rebuild search indexes if needed
echo "Rebuilding search indexes..."
docker compose -f ../docker-compose.prod.yml exec web python manage.py shell << 'EOF'
try:
from django.core.management import call_command
call_command('rebuild_index', interactive=False)
print("Search indexes rebuilt successfully")
except:
print("No search indexes to rebuild")
EOF
# Verify HelpBox system
echo "Verifying HelpBox system..."
docker compose -f ../docker-compose.prod.yml exec web python manage.py shell << 'EOF'
from stiftung.models import HelpBox
count = HelpBox.objects.count()
print(f"HelpBoxes found: {count}")
if count == 0:
print("Creating default help boxes...")
from django.contrib.auth import get_user_model
User = get_user_model()
admin_user = User.objects.filter(is_superuser=True).first()
if admin_user:
help_boxes = [
('destinataer_new', 'Neuer Destinatär', '## Destinatär erstellen\n\nHier können Sie einen neuen Destinatär anlegen.'),
('foerderung_new', 'Neue Förderung', '## Förderung erstellen\n\nErstellen Sie hier eine neue Förderung.'),
('unterstuetzung_new', 'Neue Unterstützung', '## Unterstützung erstellen\n\nLegen Sie eine neue Unterstützung an.'),
]
for page_key, title, content in help_boxes:
HelpBox.objects.get_or_create(
page_key=page_key,
defaults={
'title': title,
'content': content,
'is_active': True,
'created_by': admin_user,
'updated_by': admin_user
}
)
print("Default help boxes created")
EOF
echo "=== Step 6: Verification ==="
echo "Verifying migration results..."
# Test database connectivity
if docker compose -f ../docker-compose.prod.yml exec web python manage.py check; then
echo "✓ Django system check passed"
else
echo "✗ Django system check failed"
fi
# Test web interface
if curl -f -s http://localhost:8000/health/ > /dev/null; then
echo "✓ Web interface is responding"
else
echo "✗ Web interface is not responding"
fi
# Count migrated objects
echo "Migration summary:"
docker compose -f ../docker-compose.prod.yml exec web python manage.py shell << 'EOF'
from django.apps import apps
for model in apps.get_models():
if hasattr(model, '_meta') and model._meta.app_label == 'stiftung':
count = model.objects.count()
print(f" {model.__name__}: {count} objects")
EOF
echo ""
echo "=== Migration Complete! ==="
echo ""
echo "Your application has been migrated from Synology to Ubuntu server."
echo ""
echo "What to test:"
echo "1. Login with your new superuser account"
echo "2. Verify all data is present and correct"
echo "3. Test HelpBox system on creation pages"
echo "4. Test PDF exports and reports"
echo "5. Verify Förderung search functionality"
echo ""
echo "Access your application at:"
echo " - Main app: http://217.154.84.225"
echo " - Admin: http://217.154.84.225/admin/"
echo " - HelpBox Admin: http://217.154.84.225/help-box/admin/"
echo ""
echo "If everything works correctly, you can:"
echo "1. Update your DNS to point to the new server"
echo "2. Set up SSL certificates"
echo "3. Decommission the old Synology deployment"
cd ..
echo "Migration data is preserved in: /opt/stiftung/migration-data/"