# HAProxy OpenManager - Environment Variables Configuration # Copy this file to .env and adjust values for your environment # ============================================================================ # DATABASE CONFIGURATION # ============================================================================ DATABASE_URL=postgresql://haproxy_user:haproxy_pass@postgres:5432/haproxy_openmanager # ============================================================================ # REDIS CONFIGURATION # ============================================================================ REDIS_URL=redis://redis:6379 # ============================================================================ # SECURITY CONFIGURATION # ============================================================================ # Change this to a strong random string in production SECRET_KEY=your-secret-key-change-this-in-production # ---------------------------------------------------------------------------- # Optional per-purpose encryption keys. # # Every secret the application stores is encrypted at rest with Fernet. Each class # derives its own key, so rotating one never affects another. If a variable below is # unset, that class's key is derived from SECRET_KEY via HKDF — which works, but means # rotating SECRET_KEY makes the existing values of that class UNDECRYPTABLE. Set an # explicit key (urlsafe-base64, 32 bytes) in production if you want independent # rotation. Generate one with: # python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())" # ---------------------------------------------------------------------------- # VRRP secrets for HA/VIP (Issue #27). # VIP_ENCRYPTION_KEY= # TOTP secrets for multi-factor authentication (Issue #18). # MFA_ENCRYPTION_KEY= # Per-account DNS provider credentials for ACME DNS-01 (Issue #35). # Rotating this without re-entering credentials makes DNS-01 renewals fail until the # affected accounts' credentials are re-saved in ACME Automation. # DNS_PROVIDER_ENCRYPTION_KEY= # Private keys of PENDING CSRs, held only until the signed certificate is imported # (Issue #53). Rotating this while CSRs are out for signature makes those CSRs # unusable — they must be deleted and re-created. # CSR_ENCRYPTION_KEY= # ============================================================================ # PUBLIC URL CONFIGURATION # ============================================================================ # The public URL where this application is accessible # This is used by agent installation scripts to connect back to the manager # # Examples: # Development: http://localhost:8000 # Production: https://haproxy-manager.example.com # OpenShift: https://internal-haproxy-openmanager.apps.openshift.example.com PUBLIC_URL=http://localhost:8000 # Management base URL (defaults to PUBLIC_URL if not set) # Override this if your management interface is on a different URL # # This is also the last-resort fallback for the ACME HTTP-01 challenge backend, # i.e. the address written into haproxy.cfg as `server _acme_mgmt :`. # That address is resolved BY HAPROXY, ON THE HAPROXY NODE. If HAProxy runs # anywhere other than this machine, localhost points at the wrong box and HTTP-01 # validation fails while DNS-01 keeps working. Set a routable address, with the # port, e.g. MANAGEMENT_BASE_URL=http://10.90.1.4:8080 MANAGEMENT_BASE_URL=http://localhost:8000 # ============================================================================ # LOGGING CONFIGURATION # ============================================================================ # Options: DEBUG, INFO, WARNING, ERROR, CRITICAL LOG_LEVEL=INFO # ============================================================================ # DEBUG MODE # ============================================================================ # Set to False in production DEBUG=True # ============================================================================ # AGENT CONFIGURATION # ============================================================================ # Heartbeat timeout in seconds AGENT_HEARTBEAT_TIMEOUT_SECONDS=15 # Config sync interval in seconds AGENT_CONFIG_SYNC_INTERVAL_SECONDS=30 # ============================================================================ # BACKEND PERFORMANCE # ============================================================================ # Number of uvicorn worker processes for the backend API (default: 1). # On multi-core hosts, setting this to the core count (e.g. 2) lets the API # use all cores. Safe to increase: background tasks are multi-replica safe # (the k8s deployment already runs 2+ replicas via HPA). UVICORN_WORKERS=1 # ============================================================================ # CORS CONFIGURATION # ============================================================================ # Comma-separated list of allowed origins for CORS # Leave empty to use defaults (localhost:3000, localhost:8080, localhost:8000) # Example: http://haproxy-manager.example.com,http://localhost:8080 CORS_ORIGINS= # ============================================================================ # REQUEST / RESPONSE LOG (v1.11.0) # ============================================================================ # Records every inbound API call and every outbound HTTP call the backend makes # (ACME, DNS providers, agents) into the `request_logs` table, browsable under # "Request Log" in the UI. # # Only the four settings below are environment-level, because they decide # whether the middleware is registered at all and how much memory the writer # queue may hold. Everything an operator tunes day to day — retention windows, # body capture, sampling, excluded paths — lives in the database and is edited # in Settings -> Request Log. # Hard kill-switch. When false the logging middleware is NEVER added to the ASGI # stack and neither the writer nor the retention task starts: zero overhead, not # even a settings lookup. Requires a restart to change. # (The `enabled` toggle in Settings is the no-restart equivalent.) REQUEST_LOG_ENABLED=true # Per-worker in-process queue depth. When it fills, rows are DROPPED and counted # rather than blocking the request — the drop count is shown on the Request Log # page (per worker). REQUEST_LOG_QUEUE_MAX=2000 # Hard memory ceiling for that same queue, per worker. The row count above does # NOT bound memory on its own: `requestlog.max_body_bytes` is editable from # Settings up to 256 KB and a row can carry it twice, so at that ceiling a # 2000-row queue would hold ~1 GiB. Whichever limit is reached first stops the # queue. Raise this if you raise REQUEST_LOG_QUEUE_MAX. REQUEST_LOG_QUEUE_MAX_BYTES=67108864 # Rows per batched INSERT. One connection is taken from the pool per batch, not # per request. REQUEST_LOG_BATCH_SIZE=100 # Maximum wait before a partial batch is flushed, in milliseconds. REQUEST_LOG_FLUSH_MS=500 # ============================================================================ # FRONTEND CONFIGURATION (React) # ============================================================================ # API URL for frontend (leave empty to auto-detect from window.location) # In production, it's recommended to leave this empty for same-origin # In development, set to: http://localhost:8000 REACT_APP_API_URL= # ============================================================================ # DEPLOYMENT NOTES # ============================================================================ # # For Docker Compose: # 1. Copy this file to .env # 2. Adjust values as needed # 3. Run: docker-compose up -d # # For Kubernetes/OpenShift: # 1. Update ConfigMaps in k8s/manifests/07-configmaps.yaml # 2. Update Secrets in k8s/manifests/03-secrets.yaml # 3. Apply manifests: kubectl apply -f k8s/manifests/ # # For Development: # 1. Copy this file to backend/.env # 2. Adjust values for local development # 3. Run: uvicorn main:app --reload #