Updated AE_API_GUNICORN_WORKERS default from 2 → 4 based on stress testing (nearly 2x throughput improvement confirmed). Added detailed comments to Gunicorn, DB pool, and connection tuning settings explaining what each parameter does, how they interact, and capacity planning math. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
202 lines
8.7 KiB
Plaintext
202 lines
8.7 KiB
Plaintext
# ------------------------------------------------------------------------------
|
||
# AETHER FRAMEWORK - DOCKER ENVIRONMENT CONFIGURATION TEMPLATE
|
||
# ------------------------------------------------------------------------------
|
||
# Copy this file to .env and fill in real values.
|
||
# .env is gitignored — never commit the live file.
|
||
# ------------------------------------------------------------------------------
|
||
|
||
# ------------------------------------------------------------------------------
|
||
# SYSTEM SETTINGS
|
||
# ------------------------------------------------------------------------------
|
||
# System timezone for all containers
|
||
TZ=US/Eastern
|
||
|
||
# Logging level for the API and background workers (debug, info, warning, error)
|
||
AE_LOG_LVL=debug
|
||
|
||
# Docker Compose Profiles
|
||
# 'database' includes: mariadb, phpmyadmin, ae_ops
|
||
# Comment out or leave empty for "app-only" nodes that connect to a remote DB
|
||
# COMPOSE_PROFILES=database
|
||
|
||
# ------------------------------------------------------------------------------
|
||
# STACK ISOLATION
|
||
# ------------------------------------------------------------------------------
|
||
# Unique Docker network name per stack (prevents collisions when running test/prod on same host)
|
||
AE_NETWORK_NAME=ae_dev_net
|
||
|
||
# Internal Docker container names (must be unique per stack)
|
||
# Note: ae_api and ae_app are scaled services — Docker does not allow container_name on those.
|
||
CONTAINER_WEB=ae_web_dev
|
||
CONTAINER_REDIS=ae_redis_dev
|
||
CONTAINER_DOZZLE=ae_dozzle_dev
|
||
CONTAINER_MARIADB=ae_mariadb_dev
|
||
CONTAINER_PMA=ae_pma_dev
|
||
CONTAINER_AE_OPS=ae_ops_dev
|
||
|
||
# ------------------------------------------------------------------------------
|
||
# NETWORK & PROXY SETTINGS
|
||
# ------------------------------------------------------------------------------
|
||
# Local Nginx listener ports on the host system
|
||
OSIT_WEB_HTTP_PORT=8888
|
||
|
||
# Maximum allowed file upload size (Global for Nginx)
|
||
OSIT_WEB_MAX_BODY_SIZE=5120M
|
||
|
||
# Gateway ports for external reverse proxy (Home Server → this node → Docker Nginx)
|
||
AE_APP_GATEWAY_PORT=3001
|
||
AE_API_GATEWAY_PORT=5060
|
||
|
||
# Dozzle log viewer port
|
||
AE_DOZZLE_PORT=8881
|
||
|
||
# Nginx Server Names (used in vhost config templates)
|
||
DOCKER_AE_API_SERVER_NAME=dev-api.oneskyit.com
|
||
DOCKER_AE_APP_SERVER_NAME=dev-example.oneskyit.com
|
||
DOCKER_PHPMYADMIN_SERVER_NAME=dev-phpmyadmin.oneskyit.com
|
||
DOCKER_OSIT_SERVER_NAME=dev.oneskyit.com
|
||
|
||
|
||
# ------------------------------------------------------------------------------
|
||
# DATABASE SETTINGS (MariaDB)
|
||
# ------------------------------------------------------------------------------
|
||
# To use an EXTERNAL database:
|
||
# 1. Set COMPOSE_PROFILES= (empty) above to disable local DB containers.
|
||
# 2. Set AE_DB_SERVER to the external IP or hostname.
|
||
# 3. Ensure the external DB allows connections from this host's IP.
|
||
|
||
# DB Hostname (use 'mariadb' for the local container, or a remote IP/FQDN)
|
||
AE_DB_SERVER=vpn-db.oneskyit.com
|
||
# AE_DB_SERVER=mariadb
|
||
AE_DB_PORT=3306
|
||
|
||
# Port to expose on the host system if running a local MariaDB container
|
||
AE_DB_EXTERNAL_PORT=32768
|
||
|
||
# Database credentials
|
||
AE_DB_NAME=aether_dev
|
||
AE_DB_USERNAME=aether_dev
|
||
AE_DB_PASSWORD=XXXX
|
||
|
||
# Connection Tuning
|
||
# Seconds to wait when establishing a new connection before giving up.
|
||
# Lower values fail fast on DB outage rather than hanging requests.
|
||
AE_DB_CONNECTION_TIMEOUT=7
|
||
|
||
# Seconds before a pooled connection is recycled (closed and reopened).
|
||
# Prevents "MySQL server has gone away" errors from MariaDB's wait_timeout.
|
||
# Must be less than MariaDB's wait_timeout (default 28800s / 8 hours).
|
||
# 900s (15 min) is a safe conservative value for active workloads.
|
||
AE_DB_POOL_RECYCLE=900
|
||
|
||
# Connections held open per API replica at idle (the "warm" pool).
|
||
# Each replica maintains this many persistent connections to MariaDB.
|
||
AE_DB_POOL_SIZE=10
|
||
|
||
# Additional connections a replica can open beyond AE_DB_POOL_SIZE under burst load.
|
||
# These are created on demand and closed when the burst subsides.
|
||
# Max connections per replica = AE_DB_POOL_SIZE + AE_DB_POOL_MAX_OVERFLOW.
|
||
# Total max DB connections across all replicas = AE_API_REPLICAS × (AE_DB_POOL_SIZE + AE_DB_POOL_MAX_OVERFLOW).
|
||
# Example: 3 replicas × (10 + 20) = 90 max connections. MARIADB_MAX_CONNECTIONS must exceed this.
|
||
AE_DB_POOL_MAX_OVERFLOW=20
|
||
|
||
# ------------------------------------------------------------------------------
|
||
# REDIS SETTINGS
|
||
# ------------------------------------------------------------------------------
|
||
# Redis is used for caching, ID resolution, and messaging
|
||
AE_REDIS_SERVER=redis
|
||
AE_REDIS_PORT=6379
|
||
|
||
# ------------------------------------------------------------------------------
|
||
# API SETTINGS (FastAPI)
|
||
# ------------------------------------------------------------------------------
|
||
|
||
# Number of API container instances (Docker Compose replica scaling).
|
||
# Each replica is an independent container with its own Gunicorn process and
|
||
# connection pool. Total DB connections = AE_API_REPLICAS × (AE_DB_POOL_SIZE + AE_DB_POOL_MAX_OVERFLOW).
|
||
# Increase for horizontal scaling across CPU cores. On a single-node Linode,
|
||
# 2-4 replicas is typical; more replicas won't help if the DB is the bottleneck.
|
||
AE_API_REPLICAS=3
|
||
|
||
# --- Gunicorn / Uvicorn Tuning ---
|
||
|
||
# Internal port Gunicorn listens on inside the container. Nginx proxies to this.
|
||
# Each replica uses this same port within its own network namespace.
|
||
AE_API_GUNICORN_PORT=5065
|
||
|
||
# Worker timeout in seconds. A request that takes longer than this causes Gunicorn
|
||
# to kill and restart the worker. Default in gunicorn_conf.py is 120s.
|
||
# Raise for endpoints that run long ffmpeg operations (clip_video, convert_file, etc.).
|
||
# Dev typically uses 900s to accommodate 5-15 min video jobs.
|
||
AE_API_GUNICORN_TIMEOUT=900
|
||
|
||
# Uvicorn worker processes per replica. Each worker handles requests independently
|
||
# using async I/O, but SQLAlchemy DB calls are synchronous and block the worker.
|
||
# More workers = more parallel DB queries. Recommended: 2-4 per replica.
|
||
# Total parallel DB query capacity ≈ AE_API_REPLICAS × AE_API_GUNICORN_WORKERS.
|
||
# Stress testing at 4 workers/replica yielded ~2x throughput vs 2 workers (14 req/s vs 7.5 req/s).
|
||
# Rule of thumb: (2 × CPU cores) + 1 per replica, but DB throughput caps before CPU becomes the limit.
|
||
AE_API_GUNICORN_WORKERS=4
|
||
|
||
# Threads per Gunicorn worker. Uvicorn workers use async I/O, so threading provides
|
||
# minimal benefit here. Leave at 1 unless explicitly benchmarked otherwise.
|
||
AE_API_GUNICORN_THREADS=1
|
||
|
||
# Security & CORS
|
||
# JWT_KEY should be a 22+ character secret string. Rotate if compromised.
|
||
AE_API_JWT_KEY=XXXX
|
||
|
||
# Regex for allowed CORS origins. Requests from non-matching origins are blocked.
|
||
# Extend the pattern if adding new domains or local dev ports.
|
||
AE_API_ORIGINS_REGEX="(https://.*\.oneskyit\.com)|(http://.*\.oneskyit\.com)|(http://.*.localhost)|(http://.*.localhost:5173)"
|
||
|
||
# ------------------------------------------------------------------------------
|
||
# SMTP SETTINGS (Email)
|
||
# ------------------------------------------------------------------------------
|
||
# Core SMTP configuration for system notifications and user emails
|
||
AE_SMTP_SERVER=linode.oneskyit.com
|
||
AE_SMTP_PORT=465
|
||
AE_SMTP_USERNAME=send_mail
|
||
AE_SMTP_PASSWORD=XXXX
|
||
|
||
# ------------------------------------------------------------------------------
|
||
# APP SETTINGS (SvelteKit)
|
||
# ------------------------------------------------------------------------------
|
||
# Build mode baked into the Docker image at build time (dev, test, prod)
|
||
AE_APP_BUILD_MODE=dev
|
||
AE_APP_REPLICAS=2
|
||
|
||
# ------------------------------------------------------------------------------
|
||
# SOURCE PATHS (Absolute paths on Host Machine)
|
||
# ------------------------------------------------------------------------------
|
||
# IMPORTANT: These paths must exist on the machine running Docker.
|
||
# They are mounted into containers as volumes for real-time development.
|
||
AE_API_SRC=/home/scott/OSIT_dev/aether_api_fastapi
|
||
AE_APP_SRC=/home/scott/OSIT_dev/aether_app_sveltekit
|
||
|
||
# Physical File Storage (Images, Documents, etc.)
|
||
# NOTE: Shared between environments to ensure binary availability
|
||
HOSTED_FILES_SRC=/home/scott/OSIT/hosted_files
|
||
HOSTED_TMP_SRC=/home/scott/OSIT/hosted_tmp
|
||
|
||
# ------------------------------------------------------------------------------
|
||
# SERVICE TUNING & PERFORMANCE
|
||
# ------------------------------------------------------------------------------
|
||
# phpMyAdmin Host Port
|
||
AE_PMA_PORT=8081
|
||
|
||
# MariaDB Performance (Injected via Docker Compose command flags)
|
||
MARIADB_MAX_CONNECTIONS=500
|
||
MARIADB_INNODB_BUFFER_POOL_SIZE=512M
|
||
MARIADB_QUERY_CACHE_SIZE=32M
|
||
MARIADB_TMP_TABLE_SIZE=384M
|
||
MARIADB_TABLE_OPEN_CACHE=4000
|
||
|
||
# ------------------------------------------------------------------------------
|
||
# AETHER SHARED CONFIG (DB Driven)
|
||
# ------------------------------------------------------------------------------
|
||
# Specifies which record from the 'cfg' table to use for shared settings
|
||
# (SMTP, API routes, and external service keys)
|
||
# common options: 1=Default, 5=Home Dev, 7=Live Test
|
||
AE_CFG_ID=5
|