Skip to content

Deployment Guide

Production deployment guide for Certana platform.

Pre-Deployment Checklist

  • Code reviewed and tested
  • Environment variables configured
  • Database migrations ready
  • SSL certificates obtained
  • Rate limiting configured
  • Monitoring setup
  • Backup strategy in place
  • Security audit completed

Deployment Options

1. Docker + Docker Compose

Build Docker Images

# Backend
cd backend
docker build -t certana-backend:latest .
docker tag certana-backend:latest your-registry/certana-backend:1.0.0

# Frontend
cd ../frontend
docker build -t certana-frontend:latest .

# Extension (built separately)
cd ../browser
npm run build

Push to Registry

docker login your-registry
docker push your-registry/certana-backend:1.0.0
docker push your-registry/certana-frontend:1.0.0

Deploy with Docker Compose

# docker-compose.prod.yml
version: '3.9'

services:
  backend:
    image: your-registry/certana-backend:1.0.0
    environment:
      ENVIRONMENT: production
      DATABASE_URL: postgresql+asyncpg://certana:${DB_PASSWORD}@db:5432/certana
      REDIS_URL: redis://redis:6379/0
    ports:
      - "8000:8000"
    depends_on:
      - db
      - redis
    restart: always
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  frontend:
    image: your-registry/certana-frontend:1.0.0
    ports:
      - "3000:3000"
    restart: always

  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: certana
      POSTGRES_USER: certana
    volumes:
      - pg_data:/var/lib/postgresql/data
    restart: always

  redis:
    image: redis:7-alpine
    restart: always

volumes:
  pg_data:

Deploy

docker-compose -f docker-compose.prod.yml up -d

2. Kubernetes Deployment

Prerequisites

  • Kubernetes cluster (AWS EKS, GCP GKE, etc.)
  • kubectl configured
  • Helm (optional but recommended)

Create Namespace

kubectl create namespace certana-prod
kubectl config set-context --current --namespace=certana-prod

Create ConfigMap & Secrets

# ConfigMap for non-sensitive config
kubectl create configmap certana-config \
  --from-literal=ENVIRONMENT=production \
  --from-literal=LOG_LEVEL=info

# Secret for sensitive data
kubectl create secret generic certana-secrets \
  --from-literal=DATABASE_URL=postgresql+asyncpg://... \
  --from-literal=REDIS_URL=redis://... \
  --from-literal=SECRET_KEY=...

Backend Deployment

# k8s/backend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: certana-backend
  namespace: certana-prod
spec:
  replicas: 3
  selector:
    matchLabels:
      app: certana-backend
  template:
    metadata:
      labels:
        app: certana-backend
    spec:
      containers:
      - name: backend
        image: your-registry/certana-backend:1.0.0
        ports:
        - containerPort: 8000
        env:
        - name: ENVIRONMENT
          valueFrom:
            configMapKeyRef:
              name: certana-config
              key: ENVIRONMENT
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: certana-secrets
              key: DATABASE_URL
        resources:
          requests:
            memory: "512Mi"
            cpu: "500m"
          limits:
            memory: "1Gi"
            cpu: "1000m"
        livenessProbe:
          httpGet:
            path: /health
            port: 8000
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /health
            port: 8000
          initialDelaySeconds: 10
          periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: certana-backend
  namespace: certana-prod
spec:
  type: LoadBalancer
  ports:
  - port: 8000
    targetPort: 8000
  selector:
    app: certana-backend

Deploy to Kubernetes

# Create namespace
kubectl create namespace certana-prod

# Deploy backend
kubectl apply -f k8s/backend-deployment.yaml

# Check status
kubectl get pods -n certana-prod
kubectl logs -f deployment/certana-backend -n certana-prod

3. Serverless Deployment (AWS Lambda)

Package Backend for Lambda

# Install serverless framework
npm install -g serverless

# Create serverless config
cat > serverless.yml << EOF
service: certana-backend

provider:
  name: aws
  runtime: python3.11
  region: us-east-1
  environment:
    ENVIRONMENT: production
    DATABASE_URL: ${ssm:/certana/db_url}

functions:
  api:
    handler: src/main.handler
    events:
      - http:
          path: /{proxy+}
          method: ANY
          cors: true

plugins:
  - serverless-python-requirements
  - serverless-wsgi
EOF

# Deploy
serverless deploy

SSL/TLS Certificate

Using Let's Encrypt with Certbot

# Install certbot
sudo apt-get install certbot python3-certbot-nginx

# Get certificate
sudo certbot certonly --standalone -d yourdomain.com

# Renew automatically
sudo certbot renew --dry-run

Use in Docker

FROM nginx:alpine

COPY --from=certbot /etc/letsencrypt /etc/letsencrypt
COPY nginx.conf /etc/nginx/nginx.conf

EXPOSE 443
CMD ["nginx", "-g", "daemon off;"]

Environment Configuration

Production .env

# Application
VERSION=1.0.0
ENVIRONMENT=production
SECRET_KEY=<generate-strong-secret>
MASTER_KEY=<load-from-kms>

# Database
DATABASE_URL=postgresql+asyncpg://certana:${DB_PASSWORD}@db.example.com:5432/certana
DATABASE_POOL_SIZE=30
DATABASE_MAX_OVERFLOW=20

# Redis
REDIS_URL=redis://redis.example.com:6379/0

# CORS
CORS_ORIGINS=https://yourdomain.com,https://app.yourdomain.com

# OAuth
GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...

# Storage
AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...
S3_BUCKET_NAME=certana-prod
CDN_BASE_URL=https://cdn.yourdomain.com

# Solana
SOLANA_RPC_URL=https://api.mainnet-beta.solana.com
SOLANA_PROGRAM_ID=...

# Rate Limiting
RATE_LIMIT_ENABLED=true
RATE_LIMIT_PER_MINUTE=60

Database Setup

Production PostgreSQL

# Connect to production database
psql -h db.example.com -U certana -d certana

# Run migrations
alembic upgrade head

# Verify
\dt  # List tables
\di  # List indexes

Backup Strategy

# Daily backup script (cron)
#!/bin/bash
BACKUP_DIR="/backups/database"
DATE=$(date +%Y%m%d_%H%M%S)

pg_dump -h db.example.com -U certana certana | \
  gzip > $BACKUP_DIR/certana_$DATE.sql.gz

# Upload to S3
aws s3 cp $BACKUP_DIR/certana_$DATE.sql.gz \
  s3://certana-backups/

# Cleanup old backups (keep 30 days)
find $BACKUP_DIR -mtime +30 -delete

Monitoring & Logging

Backend Monitoring

# Use CloudWatch (AWS) or similar
import logging
import watchtower

logger = logging.getLogger(__name__)
logger.addHandler(watchtower.CloudWatchLogHandler())

Key Metrics

  • Request latency (p50, p95, p99)
  • Error rate
  • Throughput (requests/sec)
  • Database connection pool usage
  • Memory usage
  • CPU usage

Set up Alarms

# AWS CloudWatch Alarm
import boto3

cloudwatch = boto3.client('cloudwatch')
cloudwatch.put_metric_alarm(
    AlarmName='CertanaBackendErrors',
    MetricName='ErrorRate',
    Namespace='Certana',
    Statistic='Average',
    Period=300,
    EvaluationPeriods=1,
    Threshold=5.0,  # 5% error rate
    ComparisonOperator='GreaterThanThreshold',
)

CI/CD Pipeline

GitHub Actions Example

name: Deploy to Production

on:
  push:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.11'

      - name: Install dependencies
        run: |
          pip install -r backend/requirements.txt

      - name: Run tests
        run: |
          pytest backend/tests/

      - name: Build Docker image
        run: |
          docker build -t certana-backend:latest backend/

      - name: Push to registry
        run: |
          echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
          docker push certana-backend:latest

      - name: Deploy to Kubernetes
        run: |
          kubectl set image deployment/certana-backend \
            backend=certana-backend:latest \
            --namespace=certana-prod

Health Checks

Backend Health Endpoint

@app.get("/health")
async def health_check():
    return {
        "status": "healthy",
        "version": settings.VERSION,
        "timestamp": datetime.utcnow().isoformat(),
        "checks": {
            "database": await check_database(),
            "redis": check_redis(),
            "ml_models": check_ml_models(),
        }
    }

Rollback Strategy

# Kubernetes rollback
kubectl rollout history deployment/certana-backend
kubectl rollout undo deployment/certana-backend --to-revision=2

# Docker rollback
docker service update --image old-image:tag certana_backend

Post-Deployment Verification

# Test API
curl -X GET https://api.yourdomain.com/v1/health

# Test database
psql -h db.example.com -U certana -d certana -c "SELECT COUNT(*) FROM users;"

# Test storage
aws s3 ls s3://certana-prod/

# Test Solana connection
curl https://api.mainnet-beta.solana.com -X POST \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"getHealth"}'

# Test frontend
open https://yourdomain.com

Scaling

Horizontal Scaling

# Kubernetes HPA
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: certana-backend-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: certana-backend
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80

Disaster Recovery

RTO/RPO Targets

  • RTO (Recovery Time Objective): 15 minutes
  • RPO (Recovery Point Objective): 1 hour

Backup & Restore

# Test restore from backup
pg_restore -h new-db.example.com -U certana -d certana_restore \
  /backups/database/certana_20240115_100000.sql.gz

# Verify restored data
psql -h new-db.example.com -U certana -d certana_restore \
  -c "SELECT COUNT(*) FROM assets;"

Next Steps