diff --git a/conf/.aether_fastapi_requirements [good].txt.bak.kate-swp b/conf/.aether_fastapi_requirements [good].txt.bak.kate-swp deleted file mode 100644 index 10bfc79..0000000 Binary files a/conf/.aether_fastapi_requirements [good].txt.bak.kate-swp and /dev/null differ diff --git a/conf/aether_api_config.py b/conf/aether_api_config.py index f7aa021..0f94dce 100644 --- a/conf/aether_api_config.py +++ b/conf/aether_api_config.py @@ -5,7 +5,7 @@ from typing import Any, Dict, List, Optional, Union class Settings(BaseSettings): AETHER_CFG: Dict[str, Any] = { - "id": os.getenv('AE_CFG_ID', '0') + "id": os.getenv('AE_CFG_ID', 0) } JWT_KEY: str = os.getenv('AE_API_JWT_KEY', 'EHmSXZFKfMEW65E8kxCKmQ') @@ -48,8 +48,31 @@ class Settings(BaseSettings): "port": os.getenv('AE_REDIS_PORT', '6379') } + # --- CRITICAL CONFIGURATIONS --- + # The following dictionaries are REQUIRED by the application logic. + # Do not remove them during refactors, as the app (e.g., lib_email.py) + # accesses these attributes directly on the settings object. + + # Send SMTP Email + # Used by app/lib_email.py for outbound communications. + SMTP: Dict[str, str] = { + "server": os.getenv('AE_SMTP_SERVER', 'linode.oneskyit.com'), + "port": os.getenv('AE_SMTP_PORT', '465'), + "username": os.getenv('AE_SMTP_USERNAME', 'send_mail'), + "password": os.getenv('AE_SMTP_PASSWORD', 'set-in-ae-sql-db-cnf-tbl') + } + + # Server Hosted File Paths + # Used extensively for file uploads, downloads, and exports. + FILES_PATH: Dict[str, str] = { + "hosted_files_root": os.getenv('AE_FILES_PATH_ROOT', '/srv/hosted_files'), + "hosted_tmp_root": os.getenv('AE_FILES_PATH_TMP', '/srv/hosted_tmp') + } + + # --- END CRITICAL CONFIGURATIONS --- + # CORS ORIGINS_REGEX: str = os.getenv('AE_API_ORIGINS_REGEX', '(https://.*\.oneskyit\.com)|(https://.*\.oneskyit\.com:4443)') ORIGINS: List[str] = ['https://oneskyit.com'] -settings = Settings() \ No newline at end of file +settings = Settings() diff --git a/conf/nginx/site-enabled_aether_fastapi_gunicorn.conf b/conf/nginx/site-enabled_aether_fastapi_gunicorn.conf index b9eaa42..74ec312 100644 --- a/conf/nginx/site-enabled_aether_fastapi_gunicorn.conf +++ b/conf/nginx/site-enabled_aether_fastapi_gunicorn.conf @@ -11,6 +11,7 @@ server { ${DOCKER_AE_API_SERVER_NAME} fastapi.localhost api.localhost + localhost ; # server_name @@ -75,6 +76,28 @@ server { access_log /logs/nginx/access_fastapi_gunicorn_ws.log; error_log /logs/nginx/error_fastapi_gunicorn_ws.log; } + + location /v3/ws { + proxy_set_header Host $http_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; + + proxy_http_version 1.1; + + proxy_redirect off; + proxy_buffering off; + + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + proxy_read_timeout 2100s; + + proxy_pass http://fastapi_backend; + + access_log /logs/nginx/access_fastapi_gunicorn_v3_ws.log; + error_log /logs/nginx/error_fastapi_gunicorn_v3_ws.log; + } } @@ -87,6 +110,7 @@ server { ${DOCKER_AE_API_SERVER_NAME} fastapi.localhost api.localhost + localhost ; # server_name @@ -160,6 +184,28 @@ server { access_log /logs/nginx/access_fastapi_gunicorn_ws.log; error_log /logs/nginx/error_fastapi_gunicorn_ws.log; } + + location /v3/ws { + proxy_set_header Host $http_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; + + proxy_http_version 1.1; + + proxy_redirect off; + proxy_buffering off; + + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + proxy_read_timeout 2100s; + + proxy_pass http://fastapi_backend; + + access_log /logs/nginx/access_fastapi_gunicorn_v3_ws.log; + error_log /logs/nginx/error_fastapi_gunicorn_v3_ws.log; + } } diff --git a/docker-compose.yml b/docker-compose.yml index bb52d39..2324ff4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -23,7 +23,7 @@ services: - ./conf/nginx/options-ssl-nginx.conf:/etc/nginx/options-ssl-nginx.conf - ./conf/nginx/site.conf:/etc/nginx/conf.d/0_site.conf - ./conf/nginx/site-enabled_aether_fastapi_gunicorn.conf:/etc/nginx/templates/site-enabled_aether_fastapi_gunicorn.conf.template - - ./conf/nginx/site-enabled_aether_flask_gunicorn.conf:/etc/nginx/templates/site-enabled_aether_flask_gunicorn.conf.template + # - ./conf/nginx/site-enabled_aether_flask_gunicorn.conf:/etc/nginx/templates/site-enabled_aether_flask_gunicorn.conf.template - ./conf/certs/oneskyit_wild_fullchain.pem:/etc/certs/fullchain_wild.pem - ./conf/certs/oneskyit_wild_privkey.pem:/etc/certs/privkey_wild.pem - ./conf/certs/oneskyit.com_fullchain.pem:/etc/certs/fullchain.pem @@ -32,7 +32,7 @@ services: - ./logs/web:/logs depends_on: - ae_api - - aether_app_gunicorn + # - aether_app_gunicorn logging: driver: "json-file" options: @@ -134,39 +134,39 @@ services: # *Legacy* Aether Flask Application served with Gunicorn # *NOTE:* This legacy frontend using Flask is being replaced by the new one using SvelteKit. - aether_app_gunicorn: - # ... (same as before) ... - restart: always - container_name: ${CONTAINER_AE_APP} - build: - context: ./ - dockerfile: aether_flask_gunicorn.Dockerfile - env_file: - - ./.env - ports: - - "${AE_APP_GUNICORN_PORT}:5005" - extra_hosts: - - "${DOCKER_AE_SERVER_EXTRA_HOST}" - - "${DOCKER_AE_API_SERVER_EXTRA_HOST}" - - "${DOCKER_AE_API_BAK_SERVER_EXTRA_HOST}" - volumes: - - ./conf/aether_flask_gunicorn_conf.py:/conf/gunicorn_flask_conf.py - - ./conf/aether_flask_requirements_current.txt:/requirements_current.txt - - ./conf/aether_app_config.py:/srv/aether_app/flask_config_v2.py - - ./logs/ae_app:/logs - - ${AE_APP_SRC}:/srv/aether_app - - ${HOSTED_FILES_SRC}:/srv/hosted_files - - ${HOSTED_TMP_SRC}:/srv/hosted_tmp - - ./tmp/ae_app:/tmp - depends_on: - - ae_api - stdin_open: true - tty: true - logging: - driver: "json-file" - options: - max-size: "10m" - max-file: "3" + # aether_app_gunicorn: + # # ... (same as before) ... + # restart: always + # container_name: ${CONTAINER_AE_APP} + # build: + # context: ./ + # dockerfile: aether_flask_gunicorn.Dockerfile + # env_file: + # - ./.env + # ports: + # - "${AE_APP_GUNICORN_PORT}:5005" + # extra_hosts: + # - "${DOCKER_AE_SERVER_EXTRA_HOST}" + # - "${DOCKER_AE_API_SERVER_EXTRA_HOST}" + # - "${DOCKER_AE_API_BAK_SERVER_EXTRA_HOST}" + # volumes: + # - ./conf/aether_flask_gunicorn_conf.py:/conf/gunicorn_flask_conf.py + # - ./conf/aether_flask_requirements_current.txt:/requirements_current.txt + # - ./conf/aether_app_config.py:/srv/aether_app/flask_config_v2.py + # - ./logs/ae_app:/logs + # - ${AE_APP_SRC}:/srv/aether_app + # - ${HOSTED_FILES_SRC}:/srv/hosted_files + # - ${HOSTED_TMP_SRC}:/srv/hosted_tmp + # - ./tmp/ae_app:/tmp + # depends_on: + # - ae_api + # stdin_open: true + # tty: true + # logging: + # driver: "json-file" + # options: + # max-size: "10m" + # max-file: "3" dozzle: container_name: ae_dozzle_dev @@ -207,4 +207,4 @@ services: networks: default: - name: ae_dev_net \ No newline at end of file + name: ae_dev_net diff --git a/env.default b/env.default index 6a6c711..c05a50e 100644 --- a/env.default +++ b/env.default @@ -2,16 +2,30 @@ # AETHER FRAMEWORK - DOCKER ENVIRONMENT CONFIGURATION (TEMPLATE) # ------------------------------------------------------------------------------ # Instructions: Copy this to .env and update the paths and credentials. +# This file serves as the master reference for all available environment variables. # ------------------------------------------------------------------------------ -# System Settings +# ------------------------------------------------------------------------------ +# SYSTEM SETTINGS +# ------------------------------------------------------------------------------ +# System timezone for all containers TZ=US/Eastern + +# Environment mode (development, testing, production) OSIT_ENV=development + +# Logging level for the API and background workers (debug, info, warning, error) AE_LOG_LVL=warning -# Profiles: 'database' includes mariadb, phpmyadmin, ae_ops. Comment out or leave empty for app-only nodes. + +# 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 -# Container Names +# ------------------------------------------------------------------------------ +# CONTAINER NAMES +# ------------------------------------------------------------------------------ +# Internal Docker container names (should be unique per environment) CONTAINER_WEB=ae_web_default CONTAINER_AE_API=ae_api_default CONTAINER_AE_APP=ae_app_default @@ -22,22 +36,27 @@ CONTAINER_PMA=ae_pma_default # ------------------------------------------------------------------------------ # NETWORK & PROXY SETTINGS # ------------------------------------------------------------------------------ -# Local Nginx Ports +# Local Nginx listener ports on the host system OSIT_WEB_HTTP_PORT=8080 OSIT_WEB_HTTPS_PORT=4443 + +# Maximum allowed file upload size (Global for Nginx) OSIT_WEB_MAX_BODY_SIZE=5120M # Gateway Port for External Reverse Proxy +# Used when a master proxy (e.g. Home Server) forwards traffic to this node AE_API_GATEWAY_PORT=5060 -# DNS Overrides +# DNS Overrides (Injected into containers' /etc/hosts) +# Format: DOMAIN:IP_ADDRESS +# Useful for container-to-container routing when using real domain names DOCKER_AE_SERVER_EXTRA_HOST=example.oneskyit.com:127.0.0.1 DOCKER_AE_APP_SERVER_EXTRA_HOST=example-app.oneskyit.com:127.0.0.1 DOCKER_AE_API_SERVER_EXTRA_HOST=example-api.oneskyit.com:127.0.0.1 DOCKER_AE_API_BAK_SERVER_EXTRA_HOST=example-bak-api.oneskyit.com:127.0.0.1 DOCKER_AE_DB_SERVER_EXTRA_HOST=db.oneskyit.com:127.0.0.1 -# Nginx Server Names +# Nginx Server Names (Used in vhost configuration templates) DOCKER_AE_API_SERVER_NAME=example-api.oneskyit.com DOCKER_AE_APP_SERVER_NAME=example-app.oneskyit.com DOCKER_PHPMYADMIN_SERVER_NAME=example-phpmyadmin.oneskyit.com @@ -46,19 +65,23 @@ DOCKER_OSIT_SERVER_NAME=example-docker.oneskyit.com # ------------------------------------------------------------------------------ # DATABASE SETTINGS (MariaDB) # ------------------------------------------------------------------------------ -# To use an external DB: -# 1. Set COMPOSE_PROFILES= (empty) in .env to disable local DB containers. -# 2. Set AE_DB_SERVER to the external IP/Hostname. -# 3. Ensure the external DB allows connections from this host. -# AE_DB_SERVER=HOSTNAME or IP_ADDRESS or "vpn-db.oneskyit.com" +# 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=mariadb AE_DB_PORT=3306 -# Port to expose on the host if running local MariaDB (default 3306) + +# Port to expose on the host system if running a local MariaDB container AE_DB_EXTERNAL_PORT=3306 + +# Database credentials AE_DB_NAME=aether_dev AE_DB_USERNAME=osit_aether -AE_DB_PASSWORD="your-password-here" -AE_DB_ROOT_PASSWORD="mariadb-root-password-here" +AE_DB_PASSWORD="your-secure-password-here" +AE_DB_ROOT_PASSWORD="your-mariadb-root-password-here" # Connection Tuning AE_DB_CONNECTION_TIMEOUT=15 @@ -67,6 +90,7 @@ AE_DB_POOL_RECYCLE=1800 # ------------------------------------------------------------------------------ # REDIS SETTINGS # ------------------------------------------------------------------------------ +# Redis is used for caching, ID resolution, and messaging AE_REDIS_SERVER=redis AE_REDIS_PORT=6379 @@ -74,14 +98,32 @@ AE_REDIS_PORT=6379 # API SETTINGS (FastAPI) # ------------------------------------------------------------------------------ AE_API_ENV=development + +# Number of API container instances to run (Docker Compose Scaling) AE_API_REPLICAS=2 + +# Gunicorn / Uvicorn Tuning AE_API_GUNICORN_PORT=5065 AE_API_GUNICORN_TIMEOUT=2100 AE_API_GUNICORN_WORKERS=2 AE_API_GUNICORN_THREADS=2 + +# Security & CORS +# JWT_KEY should be a 22+ character secret string AE_API_JWT_KEY="your-22-char-secret-key" + +# Regex for allowed CORS origins AE_API_ORIGINS_REGEX="(https://.*\.oneskyit\.com)|(https://.*\.oneskyit\.com:4443)" +# ------------------------------------------------------------------------------ +# SMTP SETTINGS (Email) +# ------------------------------------------------------------------------------ +# Core SMTP configuration for system notifications and user emails +AE_SMTP_SERVER=smtp.example.com +AE_SMTP_PORT=465 +AE_SMTP_USERNAME=send_mail +AE_SMTP_PASSWORD="your-smtp-password-here" + # ------------------------------------------------------------------------------ # APP SETTINGS (Legacy Flask) # ------------------------------------------------------------------------------ @@ -92,24 +134,37 @@ AE_APP_SESSION_LIFETIME=86400 AE_APP_CACHE_TIMEOUT=5 # ------------------------------------------------------------------------------ -# SOURCE PATHS (Absolute paths on Host) +# SOURCE PATHS (Absolute paths on Host Machine) # ------------------------------------------------------------------------------ -# IMPORTANT: Update these to match your local filesystem +# IMPORTANT: These paths must exist on the machine running Docker +# They are mounted into containers as volumes for real-time development + +# Project Source Code AE_API_SRC=/path/to/aether_api_fastapi AE_APP_SRC=/path/to/aether_app_flask -# NOTE: This is *correct* even in the *development* environment: /home/scott/OSIT/hosted_files +# Physical File Storage (Images, Documents, etc.) +# NOTE: Shared between environments to ensure binary availability HOSTED_FILES_SRC=/path/to/hosted_files HOSTED_TMP_SRC=/path/to/hosted_tmp # ------------------------------------------------------------------------------ -# SERVICE TUNING +# SERVICE TUNING & PERFORMANCE # ------------------------------------------------------------------------------ +# phpMyAdmin Host Port AE_PMA_PORT=8081 -# MariaDB Performance +# 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 \ No newline at end of file +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=1