KHOLO LogoDocs v1.0
Developer Guide

Production Deployment & POPIA Guide

Docker Compose production, Nginx reverse proxy, SSL, and SA POPIA compliance.

This guide covers deploying KHOLO into production environments using Docker Compose, configuring reverse proxies with SSL, and implementing South African POPIA (Protection of Personal Information Act) compliance.


1. Production Architecture Overview

In production, the entire stack runs within isolated Docker containers behind an Nginx or Caddy reverse proxy:

Production Container Topologydocker-compose.prod.yml
Reverse Proxy
Nginx / Caddy
Port 80/443 with Let's Encrypt SSL. Routes API and Web traffic.
Frontend Web
Next.js 15 (Port 3000)
Order Control Centre, Pick Slips, Catalog, and Customer Portal.
API Gateway
Fastify (Port 3001)
Webhook receiver, AI extraction, and Background Task Queue worker.
Data Tier
Postgres + Redis 7
Vector Database database and Background Task Queue queue broker with persistent volumes.

2. Server Requirements & Prerequisites

  • Hardware Recommendation:
    • Minimum: 2 vCPU, 4GB RAM, 40GB SSD.
    • Recommended: 4 vCPU, 8GB RAM, 80GB NVMe SSD (handles 5,000+ orders/day with real-time audio transcription).
  • Operating System: Ubuntu 22.04 LTS or 24.04 LTS.
  • Dependencies: Docker Engine $\ge 24.0$ and Docker Compose V2.

3. Deployment Steps

Step 1: Clone Repository & Configure Production Environment

git clone https://github.com/MojaHorse/KHOLO.git /opt/kholo
cd /opt/kholo

# Copy and edit production environment variables
cp apps/api/.env.example apps/api/.env
cp apps/web/.env.example apps/web/.env

Ensure production values are set in apps/api/.env:

NODE_ENV=production
DATABASE_URL="postgresql://kholo_user:SECURE_PASSWORD@db:5432/kholo_prod?schema=public"
REDIS_HOST=redis
REDIS_PORT=6379
PORT=3001

# Meta WhatsApp Credentials
META_WHATSAPP_PHONE_NUMBER_ID="1092837465"
META_WHATSAPP_ACCESS_TOKEN="EAAxxxxxxx"
META_APP_SECRET="your_meta_app_secret"
WHATSAPP_VERIFY_TOKEN="your_strong_verify_token"

# Primary AI Provider
PRIMARY_AI_PROVIDER="gemini"
GEMINI_API_KEY="your_production_gemini_key"
OPENAI_API_KEY="your_production_openai_key"

# CORS Allowed Origins
ALLOWED_ORIGINS="https://app.yourdomain.co.za,https://admin.yourdomain.co.za"

Step 2: Build and Start Containers

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

Step 3: Run Database Migrations in the Container

docker compose -f docker-compose.prod.yml exec api npx prisma migrate deploy

4. Nginx Reverse Proxy & SSL Configuration

Create an Nginx configuration file at /etc/nginx/sites-available/kholo.conf:

# API & Webhooks
server {
    server_name api.yourdomain.co.za;

    location / {
        proxy_pass http://127.0.0.1:3001;
        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;
        client_max_body_size 25M; # Allows WhatsApp voice notes and catalog CSVs
    }
}

# Web Control Centre
server {
    server_name app.yourdomain.co.za;

    location / {
        proxy_pass http://127.0.0.1:3000;
        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;
    }
}

Enable SSL using Certbot:

sudo certbot --nginx -d api.yourdomain.co.za -d app.yourdomain.co.za

5. Security & Access Control Architecture

1. Role-Based Access Control (RBAC):

  • ADMIN: Platform super-administrators with fleet management, tenant creation, and billing management.
  • MANAGER: Distributor administrators with catalog editing, credit hold release, pricing changes, and API key management.
  • CLERK: Order desk operators with order review, SKU resolution, and pick slip printing permissions.

2. Dual Authentication Model:

  • Clerk Terminal Access: Clerks log in using a 4-digit PIN (pinHash verified with bcrypt) for fast, friction-free switching on shared warehouse dispatch tablets.
  • Manager & Admin Access: Authenticated via Supabase JWT with mandatory session expiry.

3. HTTP Hardening:

  • Helmet: Strict Content Security Policy (CSP), HSTS, and X-Content-Type-Options headers.
  • Rate Limiting: Configured at 100 requests per minute per IP address with burst protection.
  • HMAC Signatures: Every incoming Meta webhook is verified against META_APP_SECRET.

6. South African POPIA & Data Protection Compliance

Under the South African Protection of Personal Information Act (POPIA):

  1. Lawful Processing: Customer phone numbers are collected solely for wholesale order fulfillment and delivery notifications.
  2. Log Sanitization: Plaintext customer phone numbers and payment details are masked in standard application logs.
  3. Immutable Audit Trails: The AuditLog table permanently records:
    • Who reviewed and approved an order (userId or clerkId).
    • What SKU corrections or alias changes were made (beforeState and afterState JSON).
    • Exact timestamps for ERP creation and delivery slips.
  4. Data Retention: Audio recordings of voice notes can be set to auto-purge after 30 days while retaining transcribed text for tax auditing.

On this page