Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Deployment & Server Configuration

Overview

The AREA backend runs on Gunicorn, a production-grade WSGI HTTP server for Python. This document covers server configuration, deployment options, and production considerations.


Gunicorn Configuration

The server uses Gunicorn with a custom configuration file (server/gunicorn.conf.py).

Configuration Options

# Bind to all interfaces on port 8080
bind = "0.0.0.0:8080"

# Worker configuration
workers = 1  # Single worker to avoid scheduler duplication
worker_class = "sync"
worker_connections = 1000

# Timeouts
timeout = 120  # Request timeout in seconds
keepalive = 5  # Keep-alive connections

# Logging
accesslog = "-"  # Log to stdout
errorlog = "-"   # Log to stderr
loglevel = "info"

# Process naming
proc_name = "area_server"

# Auto-reload in development
reload = True  # When FLASK_ENV=development

Key Settings

SettingValueDescription
bind0.0.0.0:8080Listen on all interfaces, port 8080
workers1Single worker (see note below)
timeout1202-minute request timeout for long operations
loglevelinfoConfigurable via LOG_LEVEL env var

Note on Workers: The server uses a single worker because the APScheduler runs inside the Flask app. Multiple workers would create duplicate schedulers, causing workflows to execute multiple times. For scaling, the scheduler should be moved to a separate container.


Environment Variables

Server Configuration

VariableDefaultDescription
GUNICORN_WORKERS1Number of worker processes
LOG_LEVELinfoLogging level (debug, info, warning, error)
FLASK_ENVproductionEnvironment mode (enables auto-reload in development)

Example

# Production
GUNICORN_WORKERS=1
LOG_LEVEL=warning
FLASK_ENV=production

# Development
GUNICORN_WORKERS=1
LOG_LEVEL=debug
FLASK_ENV=development

Docker Deployment

Server Dockerfile

FROM python:3.12-slim

WORKDIR /app

# Install system dependencies
RUN apt-get update && apt-get install -y \
    gcc \
    postgresql-client \
    && rm -rf /var/lib/apt/lists/*

# Install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8080

# Start Gunicorn with config file
CMD ["gunicorn", "--config", "gunicorn.conf.py", "app:app"]

Docker Compose

The complete stack is defined in docker-compose.yml:

services:
  database:
    image: postgres:15
    environment:
      POSTGRES_DB: area_db
      POSTGRES_USER: area_user
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data

  server:
    build: ./server
    ports:
      - "8080:8080"
    depends_on:
      - database
    environment:
      DATABASE_URL: postgresql://area_user:${POSTGRES_PASSWORD}@database:5432/area_db
      JWT_SECRET_KEY: ${JWT_SECRET_KEY}
      # ... other env vars

  client_web:
    build:
      context: ./client
      dockerfile: Dockerfile.web
    ports:
      - "8081:8081"

  client_mobile:
    build:
      context: ./client
      dockerfile: Dockerfile.mobile
    volumes:
      - mobile_build:/build

volumes:
  postgres_data:
  mobile_build:

Starting the Server

# Start all services
docker-compose up --build

# Start in background
docker-compose up -d --build

# View logs
docker-compose logs -f server

Manual Start

cd server

# Install dependencies
pip install -r requirements.txt

# Set environment variables
export DATABASE_URL=postgresql://user:pass@localhost:5432/area_db
export JWT_SECRET_KEY=your-secret-key

# Start with Gunicorn
gunicorn --config gunicorn.conf.py app:app

# Or with Flask development server
flask run --host=0.0.0.0 --port=8080

Health Checks

Health Endpoint

The server exposes a health check endpoint:

curl http://localhost:8080/health

Response:

{
  "status": "healthy",
  "database": "connected",
  "scheduler": "enabled",
  "services": {
    "scheduler_interval": "1 minutes",
    "active_count": 8
  }
}

Docker Health Check

Add to docker-compose.yml:

server:
  healthcheck:
    test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
    interval: 30s
    timeout: 10s
    retries: 3

Logging

Log Format

Access logs follow the format:

%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"

Example:

172.20.0.1 - - [18/Jan/2026:10:30:00 +0000] "GET /api/auth/me HTTP/1.1" 200 234 "-" "Mozilla/5.0"

Log Levels

LevelDescription
debugDetailed debugging information
infoGeneral operational messages
warningWarning messages
errorError messages only
criticalCritical errors only

Set via environment variable:

LOG_LEVEL=debug