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>
Documents AE_DB_POOL_SIZE and AE_DB_POOL_MAX_OVERFLOW in .env.default
with per-replica connection math comment for capacity planning.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace AE_APP_BUILD_MODE=staging references and old docker compose
build-ui instructions with current build-docker-* and deploy-remote-*
Makefile targets.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- deploy.sh: SSH-triggered deploy for prod and test environments on
srv-nyx (linode.oneskyit.com). Pulls repos, builds ae_app container
with correct BUILD_MODE, restarts ae_api.
- Makefile: rename build-ui → build-docker-dev/test/prod to match new
naming convention; add deploy-remote-test and deploy-remote-prod targets
- .env.default: AE_APP_BUILD_MODE staging → dev (from prior session)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The Docker env project had no committed .env template — new contributors
had to reverse-engineer the required variables from the compose files.
Added .env.default with all required variables, secrets replaced with XXXX,
and comments explaining each section. Notable: AE_API_GUNICORN_TIMEOUT is
documented as 900 (needed for long ffmpeg video jobs like clip_video).
Updated .gitignore to whitelist .env.default via !.env.default.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Nginx was closing the client connection after exactly 60 seconds on requests
like clip_video (ffmpeg, 5-40 min) because send_timeout and proxy_send_timeout
both default to 60s. proxy_read_timeout was already 2100s but the other two
timeouts were still at defaults.
With proxy_buffering off, Nginx holds the write path to the client open as soon
as the upstream connection is established. If the upstream sends no data for 60s
(e.g. ffmpeg processing), Nginx treats the idle write path as stalled and closes
the client connection, logging 499 (Client Closed Request).
Fixed: raise proxy_send_timeout and send_timeout to 2100s to match
proxy_read_timeout in the main location block.
Also raised the Gunicorn default timeout from 30s to 120s in gunicorn_conf.py
as a belt-and-suspenders measure (AE_API_GUNICORN_TIMEOUT env var takes precedence).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Newer gunicorn (post-23.0.0) added _get_control_socket_path() which
calls os.path.isabs() on the value — crashing when it is None.
Point the socket to /dev/shm (already used for worker_tmp_dir) so it
is writable inside the container and satisfies the new gunicorn code.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Gunicorn 25.1.0+ enables a 'control_socket' by default, which creates
a root-owned 'gunicorn.ctl' file in the chdir directory. When this
directory is a volume mount (as in our dev/test setups), it causes
permission errors during Docker build context gathering.
This change explicitly sets 'control_socket = None' to prevent the
creation of this file.
API config is no longer injected via volume mount. app/config.py in the
aether_api_fastapi repo reads all settings directly from env vars (.env).
Updated README to reflect the new config location.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Traffic diagram corrected: both app and api route through ae_web_dev
- Removed outdated 'two options' scaling section for ae_app
- Added port reference table to CHEATSHEET
- Scaling section simplified: change replicas, done, home nginx never changes
- localhost link corrected from 3001 to 8888 (LAN HTTP via ae_web_dev)
Both API and App now scale transparently via Docker DNS round-robin.
Home server nginx points at a single port for each service:
- workstation:5060 -> ae_web_dev:80 -> ae_api replicas
- workstation:3001 -> ae_web_dev:80 -> ae_app replicas
ae_app no longer needs host port bindings. AE_APP_REPLICAS scales freely.
HTTPS (443) commented out -- SSL terminates at home server, not internally.
Replace single AE_APP_NODE_PORT with AE_APP_NODE_PORT_RANGE (e.g. 3001-3006).
Docker assigns one port from the range to each replica, enabling external
nginx upstreams to reference individual ports per instance.
ae_api needs no host ports -- it scales via Docker DNS through ae_web_dev.
With scale > 1, multiple replicas cannot bind to the same host port.
ae_app does not need a host port -- nginx routes to it internally via
the Docker service name 'ae_app:3000' with round-robin load balancing.
Removed ports: '${AE_APP_NODE_PORT}:3000' to fix the port conflict.
Updated README.md to reflect V3 architecture, documented the physical database management suite, and finalized synchronization between env.default and active .env configuration.
Updated env.default with self-documenting comments and all active environment variables. Hardened conf/aether_api_config.py to ensure SMTP and FILES_PATH dictionaries are preserved during refactors. Integrated v3 websocket routes into Nginx template.