Files
multitenetsaas/docs/deployment/production-deployment.md
AHMET YILMAZ b3fff546e9
Some checks failed
System Monitoring / Health Checks (push) Has been cancelled
System Monitoring / Performance Monitoring (push) Has been cancelled
System Monitoring / Database Monitoring (push) Has been cancelled
System Monitoring / Cache Monitoring (push) Has been cancelled
System Monitoring / Log Monitoring (push) Has been cancelled
System Monitoring / Resource Monitoring (push) Has been cancelled
System Monitoring / Uptime Monitoring (push) Has been cancelled
System Monitoring / Backup Monitoring (push) Has been cancelled
System Monitoring / Security Monitoring (push) Has been cancelled
System Monitoring / Monitoring Dashboard (push) Has been cancelled
System Monitoring / Alerting (push) Has been cancelled
Security Scanning / Dependency Scanning (push) Has been cancelled
Security Scanning / Code Security Scanning (push) Has been cancelled
Security Scanning / Secrets Scanning (push) Has been cancelled
Security Scanning / Container Security Scanning (push) Has been cancelled
Security Scanning / Compliance Checking (push) Has been cancelled
Security Scanning / Security Dashboard (push) Has been cancelled
Security Scanning / Security Remediation (push) Has been cancelled
project initialization
2025-10-05 02:37:33 +08:00

18 KiB

Production Deployment Guide

This guide provides comprehensive instructions for deploying the Multi-Tenant SaaS Platform to production environments.

Prerequisites

Infrastructure Requirements

  • Server: Cloud VPS or dedicated server with minimum specifications
  • OS: Ubuntu 20.04 LTS or CentOS 8+
  • RAM: 16GB+ recommended
  • CPU: 8+ cores recommended
  • Storage: 200GB+ SSD storage
  • Network: 1Gbps+ bandwidth

Software Requirements

  • Python: 3.9+
  • Node.js: 16+
  • PostgreSQL: 13+
  • Redis: 6+
  • Nginx: 1.18+
  • Supervisor: Process management
  • Certbot: SSL certificates
  • Fail2ban: Security

Malaysian Requirements

  • Domain: Malaysian domain (.com.my, .my)
  • SSL: Valid SSL certificate
  • Data Center: Malaysian cloud region
  • Payment Gateway: Malaysian payment providers
  • Compliance: PDPA and KKM compliance

Server Preparation

1. System Update and Security

# Update system packages
sudo apt update && sudo apt upgrade -y

# Install security packages
sudo apt install -y ufw fail2ban unattended-upgrades

# Configure firewall
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw enable

# Configure automatic security updates
sudo dpkg-reconfigure -plow unattended-upgrades

2. Create Application User

# Create application user
sudo adduser --system --group --home /opt/multi-tenant-saas multi-tenant

# Set up sudo access for deployment
sudo visudo
# Add: multi-tenant ALL=(ALL) NOPASSWD:/usr/bin/systemctl restart gunicorn, /usr/bin/systemctl restart nginx

3. Install Required Software

# Install Python and development tools
sudo apt install -y python3-pip python3-venv python3-dev build-essential

# Install Node.js
curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -
sudo apt install -y nodejs

# Install PostgreSQL
sudo apt install -y postgresql postgresql-contrib

# Install Redis
sudo apt install -y redis-server

# Install Nginx
sudo apt install -y nginx

# Install Supervisor
sudo apt install -y supervisor

# Install Certbot
sudo apt install -y certbot python3-certbot-nginx

Database Setup

1. PostgreSQL Configuration

# Configure PostgreSQL
sudo -u postgres psql

# Create database and user
CREATE DATABASE multi_tenant_saas_prod;
CREATE USER multi_tenant_prod_user WITH PASSWORD 'strong-password-here';
GRANT ALL PRIVILEGES ON DATABASE multi_tenant_saas_prod TO multi_tenant_prod_user;
ALTER USER multi_tenant_prod_user CREATEDB;

# Configure PostgreSQL settings
sudo vim /etc/postgresql/13/main/postgresql.conf
# Update:
# shared_buffers = 256MB
# effective_cache_size = 1GB
# maintenance_work_mem = 64MB
# checkpoint_completion_target = 0.9
# wal_buffers = 16MB
# default_statistics_target = 100
# random_page_cost = 1.1
# effective_io_concurrency = 200
# work_mem = 4MB
# min_wal_size = 1GB
# max_wal_size = 4GB

# Restart PostgreSQL
sudo systemctl restart postgresql

2. Redis Configuration

# Configure Redis
sudo vim /etc/redis/redis.conf
# Update:
# maxmemory 512mb
# maxmemory-policy allkeys-lru
# save 900 1
# save 300 10
# save 60 10000

# Restart Redis
sudo systemctl restart redis

Application Deployment

1. Deploy Application Code

# Switch to application user
sudo su - multi-tenant

# Clone repository
git clone https://github.com/your-org/multi-tenant-saas.git /opt/multi-tenant-saas
cd /opt/multi-tenant-saas

# Create virtual environment
python3 -m venv venv
source venv/bin/activate

# Install dependencies
pip install -r requirements.txt
pip install gunicorn psycopg2-binary

# Install frontend dependencies
cd frontend
npm install
npm run build
cd ..

# Set up environment
cp .env.production .env
vim .env

2. Environment Configuration

# Production environment variables
DEBUG=False
SECRET_KEY=your-production-secret-key-here
DATABASE_URL=postgresql://multi_tenant_prod_user:strong-password@localhost:5432/multi_tenant_saas_prod
REDIS_URL=redis://localhost:6379/0
ALLOWED_HOSTS=your-domain.com,www.your-domain.com
CORS_ALLOWED_ORIGINS=https://your-domain.com,https://www.your-domain.com

# Malaysian configuration
TIMEZONE=Asia/Kuala_Lumpur
CURRENCY=MYR
SST_RATE=0.06
DEFAULT_COUNTRY=Malaysia

# Security settings
SECURE_BROWSER_XSS_FILTER=True
SECURE_CONTENT_TYPE_NOSNIFF=True
SECURE_HSTS_INCLUDE_SUBDOMAINS=True
SECURE_HSTS_PRELOAD=True
SECURE_HSTS_SECONDS=31536000
SECURE_SSL_REDIRECT=True
SESSION_COOKIE_SECURE=True
CSRF_COOKIE_SECURE=True

3. Database Migrations

# Run migrations
python manage.py migrate --settings=config.production

# Create superuser
python manage.py createsuperuser --settings=config.production

# Load initial data
python manage.py load_initial_data --settings=config.production

# Collect static files
python manage.py collectstatic --settings=config.production --noinput

Web Server Configuration

1. Nginx Configuration

# Create Nginx configuration
sudo vim /etc/nginx/sites-available/multi-tenant-saas
server {
    listen 80;
    server_name your-domain.com www.your-domain.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name your-domain.com www.your-domain.com;

    ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    # Security headers
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # Static files
    location /static/ {
        alias /opt/multi-tenant-saas/staticfiles/;
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # Media files
    location /media/ {
        alias /opt/multi-tenant-saas/media/;
        expires 1y;
        add_header Cache-Control "public";
    }

    # Frontend
    location / {
        root /opt/multi-tenant-saas/frontend/build;
        try_files $uri $uri/ /index.html;
        expires 1h;
        add_header Cache-Control "public";
    }

    # API
    location /api/ {
        proxy_pass http://unix:/run/gunicorn.sock;
        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;
        proxy_connect_timeout 30s;
        proxy_send_timeout 30s;
        proxy_read_timeout 30s;
    }

    # WebSocket
    location /ws/ {
        proxy_pass http://unix:/run/gunicorn.sock;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        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;
    }

    # Health check
    location /health/ {
        proxy_pass http://unix:/run/gunicorn.sock;
        access_log off;
    }
}

2. Enable Site and Test

# Enable site
sudo ln -s /etc/nginx/sites-available/multi-tenant-saas /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Process Management

1. Gunicorn Configuration

# Create Gunicorn configuration
sudo vim /opt/multi-tenant-saas/gunicorn.conf.py
bind = 'unix:/run/gunicorn.sock'
workers = 4
worker_class = 'sync'
worker_connections = 1000
timeout = 30
keepalive = 5
max_requests = 1000
max_requests_jitter = 100
preload_app = True
reload = False
daemon = False
user = 'multi-tenant'
group = 'multi-tenant'
raw_env = [
    'DJANGO_SETTINGS_MODULE=config.production',
    'PYTHONPATH=/opt/multi-tenant-saas',
]

2. Create Systemd Service

# Create Gunicorn service
sudo vim /etc/systemd/system/gunicorn.service
[Unit]
Description=Multi-Tenant SaaS Platform Gunicorn
After=network.target postgresql.service redis.service

[Service]
Type=notify
User=multi-tenant
Group=multi-tenant
WorkingDirectory=/opt/multi-tenant-saas
Environment=PATH=/opt/multi-tenant-saas/venv/bin
ExecStart=/opt/multi-tenant-saas/venv/bin/gunicorn --config gunicorn.conf.py config.wsgi:application
ExecReload=/bin/kill -s HUP $MAINPID
KillMode=mixed
TimeoutStopSec=5
PrivateTmp=true
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target

3. Enable and Start Services

# Enable and start Gunicorn
sudo systemctl daemon-reload
sudo systemctl enable gunicorn
sudo systemctl start gunicorn

# Check status
sudo systemctl status gunicorn

SSL Certificate Setup

1. Obtain SSL Certificate

# Stop Nginx temporarily
sudo systemctl stop nginx

# Obtain SSL certificate
sudo certbot certonly --standalone -d your-domain.com -d www.your-domain.com

# Start Nginx
sudo systemctl start nginx

2. Set Up Auto-Renewal

# Test auto-renewal
sudo certbot renew --dry-run

# Set up cron job for auto-renewal
sudo crontab -e
# Add: 0 12 * * * /usr/bin/certbot renew --quiet

Malaysian Configuration

1. Payment Gateway Setup

# Configure Malaysian payment gateways
sudo vim /opt/multi-tenant-saas/config/payments.py
PAYMENT_GATEWAYS = {
    'touch_n_go': {
        'enabled': True,
        'environment': 'production',
        'api_key': os.environ.get('TOUCH_N_GO_API_KEY'),
        'secret': os.environ.get('TOUCH_N_GO_SECRET'),
        'merchant_id': os.environ.get('TOUCH_N_GO_MERCHANT_ID'),
    },
    'grabpay': {
        'enabled': True,
        'environment': 'production',
        'api_key': os.environ.get('GRABPAY_API_KEY'),
        'secret': os.environ.get('GRABPAY_SECRET'),
        'merchant_id': os.environ.get('GRABPAY_MERCHANT_ID'),
    },
    'online_banking': {
        'enabled': True,
        'banks': ['maybank2u', 'cimb_clicks', 'rhbb'],
    }
}

2. SST Configuration

# Configure SST settings
sudo vim /opt/multi-tenant-saas/config/sst.py
SST_SETTINGS = {
    'enabled': True,
    'rate': 0.06,
    'registration_number': os.environ.get('SST_REGISTRATION_NUMBER'),
    'currency': 'MYR',
    'invoice_prefix': 'SST',
    'tax_inclusive': True,
}

3. Timezone and Localization

# Set system timezone
sudo timedatectl set-timezone Asia/Kuala_Lumpur

# Configure application timezone
sudo vim /opt/multi-tenant-saas/config/settings.py
TIME_ZONE = 'Asia/Kuala_Lumpur'
LANGUAGE_CODE = 'en-my'
USE_I18N = True
USE_L10N = True
USE_TZ = True

Monitoring and Logging

1. Application Logging

# Create log directory
sudo mkdir -p /var/log/multi-tenant-saas
sudo chown multi-tenant:multi-tenant /var/log/multi-tenant-saas

# Configure logging
sudo vim /opt/multi-tenant-saas/config/logging.py
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}',
            'style': '{',
        },
        'simple': {
            'format': '{levelname} {message}',
            'style': '{',
        },
    },
    'handlers': {
        'file': {
            'level': 'INFO',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': '/var/log/multi-tenant-saas/django.log',
            'maxBytes': 10485760,  # 10MB
            'backupCount': 5,
            'formatter': 'verbose',
        },
        'console': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'simple',
        },
    },
    'loggers': {
        'django': {
            'handlers': ['file', 'console'],
            'level': 'INFO',
            'propagate': False,
        },
        'multi_tenant_saas': {
            'handlers': ['file', 'console'],
            'level': 'INFO',
            'propagate': False,
        },
    },
}

2. System Monitoring

# Install monitoring tools
sudo apt install -y htop iotop nethogs

# Set up log rotation
sudo vim /etc/logrotate.d/multi-tenant-saas
/var/log/multi-tenant-saas/*.log {
    daily
    missingok
    rotate 30
    compress
    delaycompress
    notifempty
    create 0640 multi-tenant multi-tenant
    postrotate
        systemctl reload gunicorn
    endscript
}

Backup and Recovery

1. Database Backup

# Create backup script
sudo vim /opt/multi-tenant-saas/scripts/backup-database.sh
#!/bin/bash
BACKUP_DIR="/opt/multi-tenant-saas/backups"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/database_backup_$DATE.sql"

# Create backup directory
mkdir -p $BACKUP_DIR

# Create database backup
pg_dump -h localhost -U multi_tenant_prod_user -d multi_tenant_saas_prod -f $BACKUP_FILE

# Compress backup
gzip $BACKUP_FILE

# Keep only last 30 days of backups
find $BACKUP_DIR -name "*.sql.gz" -mtime +30 -delete

echo "Database backup completed: $BACKUP_FILE.gz"

2. Automated Backups

# Make backup script executable
sudo chmod +x /opt/multi-tenant-saas/scripts/backup-database.sh

# Set up cron job for daily backups
sudo crontab -e
# Add: 0 2 * * * /opt/multi-tenant-saas/scripts/backup-database.sh

Security Hardening

1. Application Security

# Set proper file permissions
sudo chown -R multi-tenant:multi-tenant /opt/multi-tenant-saas
sudo chmod -R 750 /opt/multi-tenant-saas
sudo chmod 600 /opt/multi-tenant-saas/.env

# Secure sensitive files
sudo chmod 600 /etc/nginx/sites-available/multi-tenant-saas
sudo chmod 600 /etc/systemd/system/gunicorn.service

2. Database Security

# Configure PostgreSQL security
sudo -u postgres psql

# Remove public access
REVOKE ALL PRIVILEGES ON DATABASE multi_tenant_saas_prod FROM PUBLIC;
REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA public FROM PUBLIC;
REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public FROM PUBLIC;
REVOKE ALL PRIVILEGES ON SCHEMA public FROM PUBLIC;

# Grant only to application user
GRANT CONNECT ON DATABASE multi_tenant_saas_prod TO multi_tenant_prod_user;
GRANT USAGE ON SCHEMA public TO multi_tenant_prod_user;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO multi_tenant_prod_user;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO multi_tenant_prod_user;

Performance Optimization

1. Database Optimization

# Create database indexes
sudo -u postgres psql -d multi_tenant_saas_prod

# Create indexes for common queries
CREATE INDEX CONCURRENTLY idx_core_tenant_schema_name ON core_tenant(schema_name);
CREATE INDEX CONCURRENTLY idx_core_user_username ON core_user(username);
CREATE INDEX CONCURRENTLY idx_core_user_email ON core_user(email);
CREATE INDEX CONCURRENTLY idx_core_user_tenant ON core_user(tenant_id);

# Analyze tables for better query planning
ANALYZE;

2. Application Optimization

# Configure Django settings for production
sudo vim /opt/multi-tenant-saas/config/production.py
# Production optimizations
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.redis.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/1',
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient',
        }
    }
}

# Session configuration
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "default"

# Email configuration
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.your-email-provider.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD')

Testing and Verification

1. Health Checks

# Application health check
curl -f https://your-domain.com/health/ || exit 1

# Database connectivity
sudo -u multi-tenant psql -h localhost -d multi_tenant_saas_prod -c "SELECT 1;" || exit 1

# Redis connectivity
redis-cli ping || exit 1

2. Load Testing

# Install load testing tools
pip install locust

# Create load test script
sudo vim /opt/multi-tenant-saas/load-test.py
from locust import HttpUser, task, between

class WebsiteUser(HttpUser):
    wait_time = between(1, 5)

    def on_start(self):
        self.client.get("/api/v1/health/")

    @task(3)
    def view_home(self):
        self.client.get("/")

    @task(1)
    def api_call(self):
        self.client.get("/api/v1/core/tenants/")

3. Security Testing

# Run security checks
pip install bandit safety
bandit -r /opt/multi-tenant-saas/backend/src/
safety check

# SSL security test
openssl s_client -connect your-domain.com:443 -servername your-domain.com | openssl x509 -noout -dates

Deployment Checklist

  • System requirements met
  • Software dependencies installed
  • Database configured and secured
  • Application code deployed
  • Environment variables set
  • SSL certificate obtained
  • Nginx configured
  • Gunicorn service running
  • Payment gateways configured
  • Malaysian compliance settings
  • Security hardening completed
  • Monitoring and logging set up
  • Backup procedures implemented
  • Performance optimizations applied
  • Health checks passing
  • Load testing completed
  • Security testing completed

Support and Maintenance

Regular Maintenance

  • Daily: Check logs and monitor performance
  • Weekly: Review security updates and patches
  • Monthly: Database maintenance and optimization
  • Quarterly: Security audit and compliance review
  • Annually: Full system review and upgrade planning

Emergency Procedures

  • Application failure: Check logs, restart services
  • Database issues: Restore from backup, contact support
  • Security incident: Follow incident response plan
  • Performance issues: Scale resources, optimize queries

Support Contacts