This guide walks you through deploying the SaaS Platform on a production server with automatic SSL certificate generation using Let's Encrypt.
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.
# 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.
# SSH into your server
ssh user@your-server-ip
# Clone the repository
git clone https://github.com/yourusername/saas-platform.git
cd saas-platform
chmod +x deploy.sh
./deploy.sh
The script will ask for:
Domain Name: Enter your domain (e.g., example.com)
Email Address: Enter your email for Let's Encrypt
Confirmation: Review and confirm deployment
The script will:
Deployment time: ~5-10 minutes
| 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 |
After deployment, the following URLs will be available:
https://example.com (Hello World app)https://console.example.comhttps://console.example.com/apiwss://console.example.com/wshttps://console.example.com/health/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
https://console.yourdomain.comadmin@yourdomain.comVisit https://yourdomain.com to see the hello world application.
# 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
Access Grafana at http://your-server-ip:3003
admin / admin# The .env file contains sensitive passwords
chmod 600 .env
# Never commit .env to version control
git add .env # DON'T DO THIS!
The deployment script generates random passwords, but you should:
# 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
# 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 -
Certificates auto-renew, but verify:
# Check certificate expiration
openssl x509 -in ssl/certificate.crt -noout -dates
# Test renewal (dry run)
sudo certbot renew --dry-run
The deployment script configures automatic renewal via cron:
renew-certs.shlogs/cert-renewal.log# 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
# View renewal logs
cat logs/cert-renewal.log
# List all certificates
sudo certbot certificates
Issue: Script reports DNS records not found
Solutions:
dig @8.8.8.8 yourdomain.com to check Google's DNSsudo systemd-resolve --flush-cachesIssue: Let's Encrypt certificate request fails
Common Causes:
Solutions:
# 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
Issue: Docker containers fail to start
Solutions:
# 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
Issue: https://console.yourdomain.com not accessible
Solutions:
dig +short console.yourdomain.comdocker logs saas-gatewaycurl -vI https://console.yourdomain.comsudo ufw statusIssue: Services cannot connect to database
Solutions:
# 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
cd /data/appserver
git pull origin main
# Stop services
docker-compose down
# Rebuild
docker-compose build
# Start services
docker-compose up -d
# 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
# All services
docker-compose logs -f
# Specific service
docker-compose logs -f api-service
# Last 100 lines
docker-compose logs --tail=100 api-service
# 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
# Container resource usage
docker stats
# System resources
htop # Install: sudo apt install htop
http://your-server-ip:3003http://your-server-ip:9090http://your-server-ip:5050Increase server resources:
For high traffic:
# 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);
# 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
cd /data/appserver
rm -rf postgres_data redis_data minio_data
rm .env
Before going to production:
dig commandGenerated by the SaaS Platform Deployment Script