#!/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/"