# Production Deployment Guide ## Overview This guide walks you through deploying the SaaS Platform on a production server with automatic SSL certificate generation using Let's Encrypt. ## Prerequisites ### Server Requirements - **OS**: Ubuntu 20.04+ / Debian 11+ / CentOS 8+ / RHEL 8+ - **RAM**: Minimum 4GB (8GB+ recommended) - **CPU**: 2+ cores recommended - **Storage**: 20GB+ available disk space - **Network**: Public IP address with ports 80 and 443 accessible ### Domain Requirements You must have a domain with the following DNS records configured: | Record Type | Name | Value | Purpose | |-------------|------|-------|---------| | A | `example.com` | `your-server-ip` | Main domain | | A | `console.example.com` | `your-server-ip` | Dashboard/Console | | A | `*.example.com` | `your-server-ip` | Wildcard for apps | **Important**: All three DNS records are **required** before running the deployment script. ### Verify DNS Configuration ```bash # Check main domain dig +short A example.com # Check console subdomain dig +short A console.example.com # Check wildcard (test with any subdomain) dig +short A test.example.com ``` All three should return your server's IP address. --- ## Quick Start ### 1. Clone the Repository ```bash # SSH into your server ssh user@your-server-ip # Clone the repository git clone https://github.com/yourusername/saas-platform.git cd saas-platform ``` ### 2. Run the Deployment Script ```bash chmod +x deploy.sh ./deploy.sh ``` ### 3. Follow the Prompts The script will ask for: 1. **Domain Name**: Enter your domain (e.g., `example.com`) - Script validates DNS records automatically - Checks for A records and wildcard support 2. **Email Address**: Enter your email for Let's Encrypt - Used for certificate expiration notifications - Required by Let's Encrypt 3. **Confirmation**: Review and confirm deployment ### 4. Wait for Deployment The script will: - ✅ Validate DNS records - ✅ Install Certbot (if not installed) - ✅ Generate Let's Encrypt SSL certificates - ✅ Configure Nginx with SSL/TLS - ✅ Create environment file with random secrets - ✅ Deploy hello world application - ✅ Start all Docker services - ✅ Setup automatic certificate renewal **Deployment time**: ~5-10 minutes --- ## What Gets Deployed ### Services | Service | Port | Description | |---------|------|-------------| | Nginx | 80, 443 | API Gateway, SSL termination | | PostgreSQL | 5432 | Primary database | | Redis | 6379 | Caching and pub/sub | | Auth Service | 3001 | Authentication API | | API Service | 3000 | Core business logic | | Realtime Service | 3002 | WebSocket server | | Dashboard | 5173 | React admin UI | | MinIO | 9000, 9001 | S3-compatible storage | | Prometheus | 9090 | Metrics collection | | Grafana | 3003 | Monitoring dashboards | ### URLs After deployment, the following URLs will be available: - **Main Site**: `https://example.com` (Hello World app) - **Dashboard**: `https://console.example.com` - **API**: `https://console.example.com/api` - **WebSocket**: `wss://console.example.com/ws` - **Health Check**: `https://console.example.com/health` ### Files Created ``` /data/appserver/ ├── .env # Environment configuration (KEEP SECURE!) ├── ssl/ │ ├── certificate.crt # SSL certificate (Let's Encrypt) │ ├── private.key # Private key (KEEP SECURE!) │ └── dhparam.pem # DH parameters ├── nginx/conf.d/ │ └── production.conf # Production Nginx config ├── apps/ │ └── hello-world/ # Hello World application │ └── index.html └── renew-certs.sh # Certificate renewal script ``` --- ## Post-Deployment Steps ### 1. Access the Dashboard 1. Visit `https://console.yourdomain.com` 2. You may see a brief loading screen on first visit 3. Create your admin account: - Email: `admin@yourdomain.com` - Password: Choose a strong password ### 2. Verify Hello World App Visit `https://yourdomain.com` to see the hello world application. ### 3. Check Service Health ```bash # Check all services are running docker-compose ps # Check specific service logs docker-compose logs -f api-service docker-compose logs -f auth-service docker-compose logs -f nginx # Check API health curl https://console.yourdomain.com/api/health ``` ### 4. Configure Monitoring (Optional) Access Grafana at `http://your-server-ip:3003` - Default credentials: `admin` / `admin` - Change password on first login - Pre-configured dashboards available --- ## Security Recommendations ### 1. Secure the .env File ```bash # The .env file contains sensitive passwords chmod 600 .env # Never commit .env to version control git add .env # DON'T DO THIS! ``` ### 2. Update Default Passwords The deployment script generates random passwords, but you should: 1. **Database Backup User**: Create a separate read-only backup user 2. **Grafana**: Change the default admin password 3. **pgAdmin**: Set a master password on first use ### 3. Enable Firewall ```bash # Ubuntu/Debian sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw allow 22/tcp # SSH sudo ufw enable # CentOS/RHEL sudo firewall-cmd --permanent --add-service=http sudo firewall-cmd --permanent --add-service=https sudo firewall-cmd --permanent --add-service=ssh sudo firewall-cmd --reload ``` ### 4. Setup Backups ```bash # Create backup script cat > backup.sh <<'EOF' #!/bin/bash BACKUP_DIR="/backups" DATE=$(date +%Y%m%d_%H%M%S) # Backup database docker exec saas-postgres pg_dump -U saas_user saas_platform > "$BACKUP_DIR/db_$DATE.sql" # Backup .env and configs tar -czf "$BACKUP_DIR/config_$DATE.tar.gz" .env nginx/ ssl/ # Keep only last 7 days find "$BACKUP_DIR" -name "*.sql" -mtime +7 -delete find "$BACKUP_DIR" -name "*.tar.gz" -mtime +7 -delete EOF chmod +x backup.sh # Add to crontab (daily at 2 AM) (crontab -l 2>/dev/null; echo "0 2 * * * /data/appserver/backup.sh") | crontab - ``` ### 5. Monitor Certificate Expiration Certificates auto-renew, but verify: ```bash # Check certificate expiration openssl x509 -in ssl/certificate.crt -noout -dates # Test renewal (dry run) sudo certbot renew --dry-run ``` --- ## SSL/TLS Certificate Management ### Automatic Renewal The deployment script configures automatic renewal via cron: - **Frequency**: Twice daily (12 AM and 12 PM) - **Script**: `renew-certs.sh` - **Logs**: `logs/cert-renewal.log` ### Manual Renewal ```bash # Stop Nginx to free port 80 docker stop saas-gateway # Renew certificate sudo certbot renew # Copy renewed certificates sudo cp /etc/letsencrypt/live/yourdomain.com/fullchain.pem ssl/certificate.crt sudo cp /etc/letsencrypt/live/yourdomain.com/privkey.pem ssl/private.key # Start Nginx docker start saas-gateway docker exec saas-gateway nginx -s reload ``` ### Check Renewal Status ```bash # View renewal logs cat logs/cert-renewal.log # List all certificates sudo certbot certificates ``` --- ## Troubleshooting ### DNS Records Not Propagating **Issue**: Script reports DNS records not found **Solutions**: 1. Wait 5-60 minutes for DNS propagation 2. Verify records in your DNS provider's dashboard 3. Use `dig @8.8.8.8 yourdomain.com` to check Google's DNS 4. Clear local DNS cache: `sudo systemd-resolve --flush-caches` ### Certificate Generation Failed **Issue**: Let's Encrypt certificate request fails **Common Causes**: 1. **Port 80 blocked**: Ensure firewall allows port 80 2. **Wrong IP**: DNS points to different IP than server 3. **Rate limit**: Let's Encrypt has rate limits (5 per week) **Solutions**: ```bash # Check if port 80 is accessible curl -I http://yourdomain.com # Verify DNS points to this server dig +short A yourdomain.com # Check Let's Encrypt rate limits # Wait 1 week or use staging server for testing ``` ### Services Not Starting **Issue**: Docker containers fail to start **Solutions**: ```bash # Check Docker daemon sudo systemctl status docker # View container logs docker-compose logs # Rebuild and restart docker-compose down docker-compose up -d --build # Check system resources free -h # Memory df -h # Disk space ``` ### Cannot Access Dashboard **Issue**: `https://console.yourdomain.com` not accessible **Solutions**: 1. **Check DNS**: `dig +short console.yourdomain.com` 2. **Check Nginx**: `docker logs saas-gateway` 3. **Check certificate**: `curl -vI https://console.yourdomain.com` 4. **Check firewall**: `sudo ufw status` ### Database Connection Errors **Issue**: Services cannot connect to database **Solutions**: ```bash # Check PostgreSQL is running docker exec saas-postgres pg_isready # Check database credentials in .env cat .env | grep POSTGRES # View database logs docker logs saas-postgres # Connect to database manually docker exec -it saas-postgres psql -U saas_user -d saas_platform ``` --- ## Updating the Platform ### Pull Latest Changes ```bash cd /data/appserver git pull origin main ``` ### Rebuild Services ```bash # Stop services docker-compose down # Rebuild docker-compose build # Start services docker-compose up -d ``` ### Database Migrations ```bash # Backup database first! ./backup.sh # Run migrations (if any) docker exec saas-api npm run migrate # Or restore from backup if needed cat backups/db_YYYYMMDD_HHMMSS.sql | docker exec -i saas-postgres psql -U saas_user -d saas_platform ``` --- ## Monitoring and Logs ### View All Service Logs ```bash # All services docker-compose logs -f # Specific service docker-compose logs -f api-service # Last 100 lines docker-compose logs --tail=100 api-service ``` ### Check Service Health ```bash # All services status docker-compose ps # Specific service health curl https://console.yourdomain.com/api/health curl https://console.yourdomain.com/auth/health # Database connection docker exec saas-postgres pg_isready ``` ### Monitor Resources ```bash # Container resource usage docker stats # System resources htop # Install: sudo apt install htop ``` ### Access Monitoring Dashboards - **Grafana**: `http://your-server-ip:3003` - **Prometheus**: `http://your-server-ip:9090` - **pgAdmin**: `http://your-server-ip:5050` --- ## Scaling Considerations ### Vertical Scaling Increase server resources: - Upgrade to a larger VM/instance - Add more RAM and CPU cores - Use SSD storage for database ### Horizontal Scaling For high traffic: 1. **Load Balancer**: Add multiple API/Auth service replicas 2. **Database**: Setup PostgreSQL replication 3. **Redis**: Use Redis Cluster 4. **Storage**: External S3 instead of MinIO ### Database Optimization ```bash # Increase PostgreSQL connections (in docker-compose.yml) environment: POSTGRES_MAX_CONNECTIONS: 200 # Add database indexes docker exec -it saas-postgres psql -U saas_user -d saas_platform CREATE INDEX idx_users_email ON __sys_users(email); ``` --- ## Uninstalling ### Stop and Remove All Services ```bash # Stop all containers docker-compose down # Remove volumes (WARNING: deletes all data!) docker-compose down -v # Remove images docker-compose down --rmi all # Remove SSL certificates sudo certbot delete --cert-name yourdomain.com ``` ### Clean Up Files ```bash cd /data/appserver rm -rf postgres_data redis_data minio_data rm .env ``` --- ## Support and Documentation - **Architecture**: See [ARCHITECTURE.md](./ARCHITECTURE.md) - **WebSocket API**: See [WEBSOCKET.md](./WEBSOCKET.md) - **API Documentation**: See [API_KEYS.md](../API_KEYS.md) - **Issues**: Report at https://github.com/yourusername/saas-platform/issues --- ## Deployment Checklist Before going to production: - [ ] DNS records configured (A, console, wildcard) - [ ] Server meets minimum requirements (4GB RAM, 2 CPU) - [ ] Firewall configured (ports 80, 443, 22) - [ ] Domain name verified with `dig` command - [ ] Email address ready for Let's Encrypt - [ ] Backup strategy planned - [ ] Monitoring dashboards configured - [ ] SSL certificates auto-renewal tested - [ ] Database backups scheduled - [ ] Admin account created - [ ] Security headers verified - [ ] Application deployment tested --- *Generated by the SaaS Platform Deployment Script*