#!/bin/bash # Production Deployment Script for Ubuntu Server # Based on Synology deployment lessons learned # Run this script from /opt/stiftung directory set -e echo "=== Stiftung Production Deployment (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 .env exists if [ ! -f ".env" ]; then echo "Error: .env file not found" echo "Copy .env.production to .env and configure it first" exit 1 fi # Validate critical environment variables echo "=== Validating Environment Configuration ===" if ! grep -q "SECRET_KEY=" .env || grep -q "SECRET_KEY=$" .env; then echo "Error: SECRET_KEY not set in .env file" exit 1 fi if ! grep -q "POSTGRES_PASSWORD=" .env || grep -q "POSTGRES_PASSWORD=$" .env; then echo "Error: POSTGRES_PASSWORD not set in .env file" exit 1 fi echo "Environment validation passed ✓" echo "=== Creating Required Directories ===" mkdir -p backups mkdir -p logs mkdir -p app/media mkdir -p app/static echo "=== Pulling latest changes ===" if [ -d ".git" ]; then git pull origin main else echo "Not a git repository, skipping git pull" fi echo "=== Building Docker images ===" docker compose -f docker-compose.prod.yml build --no-cache echo "=== Stopping existing containers ===" docker compose -f docker-compose.prod.yml down echo "=== Starting database first ===" docker compose -f docker-compose.prod.yml up -d db redis echo "=== Waiting for database to be ready ===" echo "This may take up to 60 seconds..." for i in {1..60}; do if docker compose -f docker-compose.prod.yml exec db pg_isready -U $POSTGRES_USER -d $POSTGRES_DB >/dev/null 2>&1; then echo "Database is ready! ✓" break fi if [ $i -eq 60 ]; then echo "Database failed to start within 60 seconds" docker compose -f docker-compose.prod.yml logs db exit 1 fi echo "Waiting for database... ($i/60)" sleep 1 done echo "=== Starting all services ===" docker compose -f docker-compose.prod.yml up -d echo "=== Waiting for web service to be ready ===" sleep 15 echo "=== Running migrations ===" docker compose -f docker-compose.prod.yml exec web python manage.py migrate echo "=== Collecting static files ===" docker compose -f docker-compose.prod.yml exec web python manage.py collectstatic --noinput echo "=== Setting up HelpBox system ===" echo "Creating initial help boxes for new features..." docker compose -f docker-compose.prod.yml exec web python manage.py shell << 'EOF' from stiftung.models import HelpBox from django.contrib.auth import get_user_model User = get_user_model() admin_user = User.objects.filter(is_superuser=True).first() if admin_user: # Create default help boxes for all creation pages help_boxes = [ { 'page_key': 'destinataer_new', 'title': 'Neuer Destinatär', 'content': '## Destinatär erstellen\n\nHier können Sie einen neuen Destinatär anlegen.\n\n**Wichtige Felder:**\n- Name (Pflichtfeld)\n- Kontaktdaten\n- Notizen\n\n*Tipp: Nutzen Sie die Notizen für wichtige Zusatzinformationen.*' }, { 'page_key': 'foerderung_new', 'title': 'Neue Förderung', 'content': '## Förderung erstellen\n\nErstellen Sie hier eine neue Förderung.\n\n**Beachten Sie:**\n- Destinatär auswählen\n- Betrag und Datum eingeben\n- Verwendungszweck dokumentieren\n\n*Die Förderung wird automatisch in die Berichte aufgenommen.*' }, { 'page_key': 'unterstuetzung_new', 'title': 'Neue Unterstützung', 'content': '## Unterstützung erstellen\n\nLegen Sie eine neue Unterstützung an.\n\n**Wichtige Informationen:**\n- Art der Unterstützung\n- Zeitraum\n- Begünstigter\n\n*Dokumentieren Sie alle relevanten Details für spätere Nachverfolgung.*' } ] for hb_data in help_boxes: help_box, created = HelpBox.objects.get_or_create( page_key=hb_data['page_key'], defaults={ 'title': hb_data['title'], 'content': hb_data['content'], 'is_active': True, 'created_by': admin_user, 'updated_by': admin_user } ) if created: print(f"Created help box for {hb_data['page_key']}") else: print(f"Help box for {hb_data['page_key']} already exists") else: print("No superuser found. Create one first with: docker compose exec web python manage.py createsuperuser") EOF echo "=== Verifying new features ===" echo "Testing 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"Total HelpBoxes: {count}") for hb in HelpBox.objects.all(): print(f"- {hb.page_key}: {hb.title} ({'Active' if hb.is_active else 'Inactive'})") EOF echo "=== Creating superuser (if needed) ===" echo "Run this manually if you need to create an admin user:" echo "docker compose -f docker-compose.prod.yml exec web python manage.py createsuperuser" echo "" echo "=== Checking service status ===" docker compose -f docker-compose.prod.yml ps echo "=== Testing application health ===" sleep 5 if curl -f -s http://localhost:8000/health/ > /dev/null; then echo "✓ Application health check passed" else echo "✗ Application health check failed" echo "Check logs: docker compose -f docker-compose.prod.yml logs web" fi echo "" echo "=== Deployment Complete! ===" echo "Application should be running 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 "New Features Available:" echo " ✓ HelpBox system on all creation pages" echo " ✓ Central HelpBox management" echo " ✓ Enhanced Förderung search" echo " ✓ Improved PDF exports" echo " ✓ Template cleanup system" echo "" echo "Next steps:" echo "1. Configure domain name and SSL certificate" echo "2. Set up monitoring and backups" echo "3. Create initial data and users" echo "4. Configure email settings for notifications" echo "" echo "For troubleshooting:" echo " - View logs: docker compose -f docker-compose.prod.yml logs -f web" echo " - Check containers: docker compose -f docker-compose.prod.yml ps" echo " - Access shell: docker compose -f docker-compose.prod.yml exec web bash"