From 587f9f4c09ae051d1051c32dde21538527d84e36 Mon Sep 17 00:00:00 2001 From: Muhamad Aji Wibisono Date: Tue, 10 Jun 2025 22:06:45 +0700 Subject: [PATCH] feat: added richer uvicorn configuration in .env --- surfsense_backend/.env.example | 41 +++++++++++++++ surfsense_backend/main.py | 95 +++++++++++++++++++++++++++++++--- 2 files changed, 128 insertions(+), 8 deletions(-) diff --git a/surfsense_backend/.env.example b/surfsense_backend/.env.example index 9a66a43..b094dae 100644 --- a/surfsense_backend/.env.example +++ b/surfsense_backend/.env.example @@ -45,3 +45,44 @@ LANGSMITH_API_KEY=lsv2_pt_..... LANGSMITH_PROJECT=surfsense +# OPTIONAL: LiteLLM API Base +FAST_LLM_API_BASE="" +STRATEGIC_LLM_API_BASE="" +LONG_CONTEXT_LLM_API_BASE="" +TTS_SERVICE_API_BASE="" +STT_SERVICE_API_BASE="" + +# --- Uvicorn Server Configuration --- +UVICORN_HOST="0.0.0.0" # Host to bind (default: 0.0.0.0) +UVICORN_PORT=8000 # Port to bind (default: 8000) +UVICORN_LOG_LEVEL="info" # Log level (critical, error, warning, info, debug, trace) + +# --- Advanced Uvicorn Options (uncomment to use) --- +# UVICORN_PROXY_HEADERS=false # Enable proxy headers (true/false) +# UVICORN_FORWARDED_ALLOW_IPS="127.0.0.1" # Comma-separated list of IPs to trust with proxy headers +# UVICORN_WORKERS=1 # Number of worker processes +# UVICORN_ACCESS_LOG=true # Access log (true/false) +# UVICORN_LOOP="auto" # Event loop implementation (auto, asyncio, uvloop) +# UVICORN_HTTP="auto" # HTTP protocol implementation (auto, h11, httptools) +# UVICORN_WS="auto" # WebSocket protocol implementation (auto, none, websockets, wsproto) +# UVICORN_LIFESPAN="auto" # Lifespan implementation (auto, on, off) +# UVICORN_ENV_FILE=".env" # Environment configuration file +# UVICORN_LOG_CONFIG="" # Logging configuration file (YAML/JSON/dict) +# UVICORN_SERVER_HEADER=true # Enable server header (true/false) +# UVICORN_DATE_HEADER=true # Enable date header (true/false) +# UVICORN_LIMIT_CONCURRENCY= # Maximum number of concurrent connections or tasks +# UVICORN_LIMIT_MAX_REQUESTS= # Maximum number of requests a worker will process before restarting +# UVICORN_TIMEOUT_KEEP_ALIVE=5 # Timeout for keep-alive connections (seconds) +# UVICORN_TIMEOUT_NOTIFY=30 # Timeout for graceful shutdown (seconds) +# UVICORN_SSL_KEYFILE="" # SSL key file (path) +# UVICORN_SSL_CERTFILE="" # SSL certificate file (path) +# UVICORN_SSL_KEYFILE_PASSWORD="" # SSL key file password +# UVICORN_SSL_VERSION="" # SSL version to use +# UVICORN_SSL_CERT_REQS="" # Whether client certificate is required (none, optional, required) +# UVICORN_SSL_CA_CERTS="" # CA certificates file +# UVICORN_SSL_CIPHERS="" # Ciphers to use +# UVICORN_HEADERS="" # List of custom default HTTP response headers (comma-separated, e.g. X-Frame-Options:DENY,X-Content-Type-Options:nosniff) +# UVICORN_USE_COLORS=true # Enable colorized logging output (true/false) +# UVICORN_UDS="" # Bind to a UNIX domain socket (overrides host/port) +# UVICORN_FD="" # Bind to socket from this file descriptor +# UVICORN_ROOT_PATH="" # Root path for ASGI applications submounted below a given URL path diff --git a/surfsense_backend/main.py b/surfsense_backend/main.py index 8d3f356..7c27a8b 100644 --- a/surfsense_backend/main.py +++ b/surfsense_backend/main.py @@ -1,6 +1,8 @@ import uvicorn import argparse import logging +import os +from dotenv import load_dotenv logging.basicConfig( level=logging.INFO, @@ -8,18 +10,95 @@ logging.basicConfig( datefmt='%Y-%m-%d %H:%M:%S' ) +load_dotenv() + if __name__ == "__main__": parser = argparse.ArgumentParser(description='Run the SurfSense application') parser.add_argument('--reload', action='store_true', help='Enable hot reloading') - parser.add_argument('--proxy', nargs='?', const='0.0.0.0/0', default=None, help='Enable proxy headers with allowed IPs (e.g., --proxy 0.0.0.0/0)') args = parser.parse_args() - uvicorn.run( - "app.app:app", - host="0.0.0.0", - log_level="info", + config_kwargs = dict( + app="app.app:app", + host=os.getenv("UVICORN_HOST", "0.0.0.0"), + port=int(os.getenv("UVICORN_PORT", 8000)), + log_level=os.getenv("UVICORN_LOG_LEVEL", "info"), reload=args.reload, - reload_dirs=["app"], - proxy_headers=bool(args.proxy), - forwarded_allow_ips=args.proxy if args.proxy else "", + reload_dirs=["app"] if args.reload else None, ) + + # Only add advanced args if set in env + if os.getenv("UVICORN_PROXY_HEADERS"): + config_kwargs["proxy_headers"] = ( + os.getenv("UVICORN_PROXY_HEADERS").lower() == "true" + ) + if os.getenv("UVICORN_FORWARDED_ALLOW_IPS"): + config_kwargs["forwarded_allow_ips"] = os.getenv("UVICORN_FORWARDED_ALLOW_IPS") + if os.getenv("UVICORN_WORKERS"): + config_kwargs["workers"] = int(os.getenv("UVICORN_WORKERS")) + if os.getenv("UVICORN_ACCESS_LOG"): + config_kwargs["access_log"] = os.getenv("UVICORN_ACCESS_LOG").lower() == "true" + if os.getenv("UVICORN_LOOP"): + config_kwargs["loop"] = os.getenv("UVICORN_LOOP") + if os.getenv("UVICORN_HTTP"): + config_kwargs["http"] = os.getenv("UVICORN_HTTP") + if os.getenv("UVICORN_WS"): + config_kwargs["ws"] = os.getenv("UVICORN_WS") + if os.getenv("UVICORN_LIFESPAN"): + config_kwargs["lifespan"] = os.getenv("UVICORN_LIFESPAN") + if os.getenv("UVICORN_ENV_FILE"): + config_kwargs["env_file"] = os.getenv("UVICORN_ENV_FILE") + if os.getenv("UVICORN_LOG_CONFIG"): + config_kwargs["log_config"] = os.getenv("UVICORN_LOG_CONFIG") + if os.getenv("UVICORN_SERVER_HEADER"): + config_kwargs["server_header"] = ( + os.getenv("UVICORN_SERVER_HEADER").lower() == "true" + ) + if os.getenv("UVICORN_DATE_HEADER"): + config_kwargs["date_header"] = ( + os.getenv("UVICORN_DATE_HEADER").lower() == "true" + ) + if os.getenv("UVICORN_LIMIT_CONCURRENCY"): + config_kwargs["limit_concurrency"] = int(os.getenv("UVICORN_LIMIT_CONCURRENCY")) + if os.getenv("UVICORN_LIMIT_MAX_REQUESTS"): + config_kwargs["limit_max_requests"] = int( + os.getenv("UVICORN_LIMIT_MAX_REQUESTS") + ) + if os.getenv("UVICORN_TIMEOUT_KEEP_ALIVE"): + config_kwargs["timeout_keep_alive"] = int( + os.getenv("UVICORN_TIMEOUT_KEEP_ALIVE") + ) + if os.getenv("UVICORN_TIMEOUT_NOTIFY"): + config_kwargs["timeout_notify"] = int(os.getenv("UVICORN_TIMEOUT_NOTIFY")) + if os.getenv("UVICORN_SSL_KEYFILE"): + config_kwargs["ssl_keyfile"] = os.getenv("UVICORN_SSL_KEYFILE") + if os.getenv("UVICORN_SSL_CERTFILE"): + config_kwargs["ssl_certfile"] = os.getenv("UVICORN_SSL_CERTFILE") + if os.getenv("UVICORN_SSL_KEYFILE_PASSWORD"): + config_kwargs["ssl_keyfile_password"] = os.getenv( + "UVICORN_SSL_KEYFILE_PASSWORD" + ) + if os.getenv("UVICORN_SSL_VERSION"): + config_kwargs["ssl_version"] = int(os.getenv("UVICORN_SSL_VERSION")) + if os.getenv("UVICORN_SSL_CERT_REQS"): + config_kwargs["ssl_cert_reqs"] = int(os.getenv("UVICORN_SSL_CERT_REQS")) + if os.getenv("UVICORN_SSL_CA_CERTS"): + config_kwargs["ssl_ca_certs"] = os.getenv("UVICORN_SSL_CA_CERTS") + if os.getenv("UVICORN_SSL_CIPHERS"): + config_kwargs["ssl_ciphers"] = os.getenv("UVICORN_SSL_CIPHERS") + if os.getenv("UVICORN_HEADERS"): + config_kwargs["headers"] = [ + tuple(h.split(":", 1)) + for h in os.getenv("UVICORN_HEADERS").split(",") + if ":" in h + ] + if os.getenv("UVICORN_USE_COLORS"): + config_kwargs["use_colors"] = os.getenv("UVICORN_USE_COLORS").lower() == "true" + if os.getenv("UVICORN_UDS"): + config_kwargs["uds"] = os.getenv("UVICORN_UDS") + if os.getenv("UVICORN_FD"): + config_kwargs["fd"] = int(os.getenv("UVICORN_FD")) + if os.getenv("UVICORN_ROOT_PATH"): + config_kwargs["root_path"] = os.getenv("UVICORN_ROOT_PATH") + + config = uvicorn.Config(**config_kwargs) + uvicorn.run(config)