# Production Deployment - Quick Start Guide **Goal**: Get the application running in production in under 30 minutes. This is a simplified, essential-steps-only guide. For comprehensive documentation, see: - [Complete Deployment Workflow](DEPLOYMENT_WORKFLOW.md) - [Production Deployment Guide](PRODUCTION_DEPLOYMENT.md) - [Ansible Deployment](ANSIBLE_DEPLOYMENT.md) --- ## Prerequisites - Ubuntu 22.04+ server with root access - Domain name pointing to server IP - Port 80 and 443 open in firewall --- ## Step 1: Initial Server Setup (10 minutes) ```bash # SSH into server ssh root@your-server.com # Update system apt update && apt upgrade -y # Install Docker curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh # Install Docker Compose apt install docker-compose-plugin -y # Install certbot for SSL apt install certbot -y # Create application user useradd -m -s /bin/bash appuser usermod -aG docker appuser ``` --- ## Step 2: SSL Certificate (5 minutes) ```bash # Create webroot directory mkdir -p /var/www/certbot # Get SSL certificate certbot certonly --webroot \ -w /var/www/certbot \ -d yourdomain.com \ --email your-email@example.com \ --agree-tos \ --non-interactive # Verify certificates ls -la /etc/letsencrypt/live/yourdomain.com/ ``` **Expected output**: `fullchain.pem` and `privkey.pem` files --- ## Step 3: Clone Application (2 minutes) ```bash # Switch to app user su - appuser # Clone repository git clone https://github.com/your-org/your-app.git /home/appuser/app cd /home/appuser/app # Checkout production branch git checkout main ``` --- ## Step 4: Generate Secrets (3 minutes) ```bash # Generate Vault encryption key php scripts/deployment/generate-vault-key.php # Save output - YOU MUST STORE THIS SECURELY! # Example output: vault_key_abc123def456... ``` **⚠️ CRITICAL**: Store this key in your password manager. You cannot recover it if lost. --- ## Step 5: Create Environment File (5 minutes) ```bash # Copy example cp .env.example .env.production # Edit configuration nano .env.production ``` **Minimal required configuration**: ```env # Application APP_ENV=production APP_DEBUG=false APP_URL=https://yourdomain.com # Database DB_HOST=database DB_PORT=3306 DB_NAME=app_production DB_USER=app_user DB_PASS=GENERATE_STRONG_PASSWORD_HERE # Vault VAULT_ENCRYPTION_KEY=YOUR_GENERATED_KEY_FROM_STEP_4 # Logging LOG_PATH=/var/log/app LOG_LEVEL=INFO # Admin Access ADMIN_ALLOWED_IPS=YOUR.SERVER.IP,127.0.0.1 ``` **Generate strong passwords**: ```bash # Generate DB password openssl rand -base64 32 # Generate JWT secret openssl rand -base64 64 ``` --- ## Step 6: Build and Start (3 minutes) ```bash # Build containers docker compose -f docker-compose.production.yml build # Start containers docker compose -f docker-compose.production.yml up -d # Check status docker compose -f docker-compose.production.yml ps ``` **Expected output**: All containers should be "Up" --- ## Step 7: Initialize Database (2 minutes) ```bash # Run migrations docker compose -f docker-compose.production.yml exec php php console.php db:migrate # Verify migration status docker compose -f docker-compose.production.yml exec php php console.php db:status ``` --- ## Step 8: Verify Health (1 minute) ```bash # Check health endpoint curl http://localhost/health/summary # Expected output (healthy): { "timestamp": "2025-01-15T10:00:00+00:00", "overall_status": "healthy", "overall_healthy": true, "summary": { "total_checks": 8, "healthy": 8, "warning": 0, "unhealthy": 0 } } ``` If unhealthy, check logs: ```bash docker compose -f docker-compose.production.yml logs php ``` --- ## Step 9: Configure Nginx Reverse Proxy ```bash # Exit to root user exit # Create Nginx config nano /etc/nginx/sites-available/app ``` **Nginx configuration**: ```nginx server { listen 80; server_name yourdomain.com; return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; server_name yourdomain.com; ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256'; location / { proxy_pass http://localhost:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location /health { proxy_pass http://localhost:8080/health; access_log off; } } ``` **Enable and restart**: ```bash # Enable site ln -s /etc/nginx/sites-available/app /etc/nginx/sites-enabled/ # Test configuration nginx -t # Restart Nginx systemctl restart nginx ``` --- ## Step 10: Final Verification ```bash # Test HTTPS endpoint curl -f https://yourdomain.com/health/summary # Test detailed health curl -f https://yourdomain.com/health/detailed # Test metrics (should be accessible) curl -f https://yourdomain.com/metrics ``` **✅ Success criteria**: - All curl commands return 200 OK - No SSL certificate warnings - Health endpoint shows all checks healthy --- ## Post-Deployment Tasks ### Setup Automatic Certificate Renewal ```bash # Test renewal certbot renew --dry-run # Certbot automatically creates cron job, verify: systemctl status certbot.timer ``` ### Setup Log Rotation ```bash # Create logrotate config nano /etc/logrotate.d/app ``` ``` /var/log/app/*.log { daily rotate 14 compress delaycompress notifempty missingok create 0644 appuser appuser sharedscripts postrotate docker compose -f /home/appuser/app/docker-compose.production.yml exec php php console.php cache:clear > /dev/null 2>&1 || true endscript } ``` ### Setup Monitoring (Optional but Recommended) ```bash # Install monitoring stack cd /home/appuser/app docker compose -f docker-compose.monitoring.yml up -d # Access Grafana # URL: http://your-server:3000 # Default credentials: admin/admin ``` ### Setup Backups ```bash # Create backup script nano /home/appuser/backup-production.sh ``` ```bash #!/bin/bash set -e BACKUP_DIR="/opt/backups" DATE=$(date +%Y%m%d_%H%M%S) # Backup database docker compose -f /home/appuser/app/docker-compose.production.yml \ exec -T database mysqldump -u app_user -p${DB_PASS} app_production | \ gzip > ${BACKUP_DIR}/db_${DATE}.sql.gz # Backup Vault tar -czf ${BACKUP_DIR}/vault_${DATE}.tar.gz /opt/vault # Keep only last 7 days find ${BACKUP_DIR} -name "*.gz" -mtime +7 -delete echo "Backup completed: ${DATE}" ``` ```bash # Make executable chmod +x /home/appuser/backup-production.sh # Add to crontab (daily at 2 AM) crontab -e ``` Add line: ``` 0 2 * * * /home/appuser/backup-production.sh >> /var/log/backup.log 2>&1 ``` --- ## Troubleshooting ### Container won't start ```bash # Check logs docker compose -f docker-compose.production.yml logs php # Common issues: # - Wrong database credentials → Check .env.production # - Port already in use → Check: netstat -tulpn | grep 8080 # - Permission issues → Run: chown -R appuser:appuser /home/appuser/app ``` ### Health checks failing ```bash # Check specific health check curl http://localhost/health/category/database # Common issues: # - Database not migrated → Run: php console.php db:migrate # - Cache not writable → Check: ls -la /var/cache/app # - Queue not running → Check: docker compose ps ``` ### SSL certificate issues ```bash # Check certificate validity openssl x509 -in /etc/letsencrypt/live/yourdomain.com/fullchain.pem -noout -dates # Renew certificate certbot renew --force-renewal # Restart Nginx systemctl restart nginx ``` ### Application errors ```bash # Check application logs docker compose -f docker-compose.production.yml logs -f php # Check Nginx logs tail -f /var/log/nginx/error.log # Check system logs journalctl -u nginx -f ``` --- ## Security Hardening (Do This After Deployment) ### 1. Firewall Configuration ```bash # Install UFW apt install ufw -y # Allow SSH ufw allow 22/tcp # Allow HTTP/HTTPS ufw allow 80/tcp ufw allow 443/tcp # Enable firewall ufw enable ``` ### 2. SSH Key-Only Authentication ```bash # Generate SSH key on local machine ssh-keygen -t ed25519 -C "your-email@example.com" # Copy to server ssh-copy-id root@your-server.com # Disable password authentication nano /etc/ssh/sshd_config ``` Set: ``` PasswordAuthentication no PermitRootLogin prohibit-password ``` Restart SSH: ```bash systemctl restart sshd ``` ### 3. Fail2Ban ```bash # Install fail2ban apt install fail2ban -y # Create jail for Nginx nano /etc/fail2ban/jail.d/nginx-limit.conf ``` ```ini [nginx-limit-req] enabled = true filter = nginx-limit-req logpath = /var/log/nginx/error.log maxretry = 10 findtime = 60 bantime = 3600 ``` ```bash # Restart fail2ban systemctl restart fail2ban ``` --- ## Deployment Updates (Ongoing) For deploying updates after initial setup: ```bash # SSH to server ssh appuser@your-server.com # Navigate to app cd /home/appuser/app # Pull latest code git pull origin main # Rebuild containers docker compose -f docker-compose.production.yml build # Run migrations (if any) docker compose -f docker-compose.production.yml exec php php console.php db:migrate # Restart containers docker compose -f docker-compose.production.yml up -d # Verify health curl -f http://localhost/health/summary ``` **For zero-downtime deployments**, use the automated script: ```bash ./scripts/deployment/blue-green-deploy.sh ``` --- ## Getting Help If you encounter issues not covered in this quick start: 1. **Check detailed documentation**: - [Complete Deployment Workflow](DEPLOYMENT_WORKFLOW.md) - [Production Deployment Guide](PRODUCTION_DEPLOYMENT.md) - [Troubleshooting Guide](PRODUCTION_DEPLOYMENT.md#troubleshooting) 2. **Check application logs**: ```bash docker compose -f docker-compose.production.yml logs -f ``` 3. **Check health endpoints**: ```bash curl http://localhost/health/detailed | jq ``` 4. **Check metrics**: ```bash curl http://localhost/metrics ``` --- ## Success Checklist ✅ Before considering deployment complete: - [ ] SSL certificate installed and valid - [ ] Application accessible via HTTPS - [ ] All health checks passing (green) - [ ] Database migrations applied successfully - [ ] Logs being written to `/var/log/app` - [ ] Automatic certificate renewal configured - [ ] Backup script running daily - [ ] Firewall configured (ports 22, 80, 443 only) - [ ] SSH key-only authentication enabled - [ ] Fail2Ban installed and monitoring - [ ] Monitoring stack running (optional) - [ ] Team has access to Vault encryption key - [ ] Database backup verified and restorable --- ## Next Steps After successful deployment: 1. **Setup Monitoring Alerts**: Configure Prometheus alerting rules 2. **Performance Tuning**: Review metrics and optimize based on actual traffic 3. **Security Audit**: Run security scan with tools like OWASP ZAP 4. **Documentation**: Document any custom configuration changes 5. **Team Training**: Ensure team knows deployment and rollback procedures 6. **Disaster Recovery**: Test backup restoration procedure --- ## Estimated Timeline - **Initial deployment (following this guide)**: 30 minutes - **Security hardening**: 15 minutes - **Monitoring setup**: 20 minutes - **Total time to production**: ~1 hour --- **You're ready for production! 🚀** For questions or issues, refer to the comprehensive guides linked throughout this document.