#!/bin/bash # =========================================== # Airflow Configuration — Single Source of Truth # =========================================== # Override any value by setting the corresponding environment # variable (e.g. as an HF Secret). # ---- Directory Paths ---- export AIRFLOW_HOME="${AIRFLOW_HOME:-/opt/airflow}" export DAGS_DIR="${AIRFLOW_HOME}/dags" export LOGS_DIR="${AIRFLOW_HOME}/logs" # ---- Database ---- # Default: local SQLite so the container always boots. # For production, set AIRFLOW__DATABASE__SQL_ALCHEMY_CONN as an HF Secret # pointing to your PostgreSQL instance. export AIRFLOW__DATABASE__SQL_ALCHEMY_CONN="${AIRFLOW__DATABASE__SQL_ALCHEMY_CONN:-sqlite:///${AIRFLOW_HOME}/airflow.db}" # Pool tuning — keeps connections low for Supabase / free-tier DBs export AIRFLOW__DATABASE__SQL_ALCHEMY_POOL_SIZE="${AIRFLOW__DATABASE__SQL_ALCHEMY_POOL_SIZE:-2}" export AIRFLOW__DATABASE__SQL_ALCHEMY_MAX_OVERFLOW="${AIRFLOW__DATABASE__SQL_ALCHEMY_MAX_OVERFLOW:-2}" export AIRFLOW__DATABASE__SQL_ALCHEMY_POOL_RECYCLE="${AIRFLOW__DATABASE__SQL_ALCHEMY_POOL_RECYCLE:-1800}" export AIRFLOW__DATABASE__SQL_ALCHEMY_POOL_PRE_PING="True" # ---- DAG Repository ---- export DAG_REPO_URL="${DAG_REPO_URL:-https://github.com/subhamgiri460/myworkflows.git}" export DAG_REPO_BRANCH="${DAG_REPO_BRANCH:-main}" # For private repos: set DAG_REPO_TOKEN to a GitHub PAT (fine-grained or classic) # The token is injected into the URL at runtime — never stored in config. export DAG_REPO_TOKEN="${DAG_REPO_TOKEN:-}" # ---- Admin Credentials ---- # Set these as HF Secrets for production. export AIRFLOW_ADMIN_USER="${AIRFLOW_ADMIN_USER:-admin}" export AIRFLOW_ADMIN_PASSWORD="${AIRFLOW_ADMIN_PASSWORD:-admin}" # ---- Internal Ports ---- export AIRFLOW_WEB_PORT="${AIRFLOW_WEB_PORT:-8080}" export REFRESH_SERVICE_PORT="${REFRESH_SERVICE_PORT:-5000}" export NGINX_PORT="${NGINX_PORT:-7860}" # ---- Core ---- export AIRFLOW__CORE__LOAD_EXAMPLES="${AIRFLOW__CORE__LOAD_EXAMPLES:-False}" export AIRFLOW__CORE__EXECUTOR="${AIRFLOW__CORE__EXECUTOR:-LocalExecutor}" export AIRFLOW__CORE__PARALLELISM="${AIRFLOW__CORE__PARALLELISM:-2}" export AIRFLOW__CORE__MAX_ACTIVE_TASKS_PER_DAG="${AIRFLOW__CORE__MAX_ACTIVE_TASKS_PER_DAG:-2}" export AIRFLOW__CORE__DAGS_ARE_PAUSED_AT_CREATION="${AIRFLOW__CORE__DAGS_ARE_PAUSED_AT_CREATION:-True}" # Auto-generate Fernet key if not set (required for connection encryption) if [ -z "${AIRFLOW__CORE__FERNET_KEY:-}" ]; then export AIRFLOW__CORE__FERNET_KEY=$(python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())" 2>/dev/null || echo "") fi # ---- Webserver ---- export AIRFLOW__WEBSERVER__WEB_SERVER_PORT="${AIRFLOW_WEB_PORT}" export AIRFLOW__WEBSERVER__WEB_SERVER_MASTER_TIMEOUT="${AIRFLOW__WEBSERVER__WEB_SERVER_MASTER_TIMEOUT:-300}" export AIRFLOW__WEBSERVER__WORKER_CLASS="${AIRFLOW__WEBSERVER__WORKER_CLASS:-gevent}" export AIRFLOW__WEBSERVER__SECRET_KEY="${AIRFLOW__WEBSERVER__SECRET_KEY:-$(python3 -c 'import secrets; print(secrets.token_hex(32))' 2>/dev/null)}" export AIRFLOW__WEBSERVER__WORKERS="${AIRFLOW__WEBSERVER__WORKERS:-1}" export AIRFLOW__WEBSERVER__EXPOSE_CONFIG="${AIRFLOW__WEBSERVER__EXPOSE_CONFIG:-False}" # ---- Scheduler ---- export AIRFLOW__SCHEDULER__DAG_DIR_LIST_INTERVAL="${AIRFLOW__SCHEDULER__DAG_DIR_LIST_INTERVAL:-30}" # ---- API ---- export AIRFLOW__API__AUTH_BACKENDS="${AIRFLOW__API__AUTH_BACKENDS:-airflow.api.auth.backend.session}" # ---- Logging ---- export AIRFLOW__LOGGING__LOGGING_LEVEL="${AIRFLOW__LOGGING__LOGGING_LEVEL:-INFO}" # ---- Validation ---- validate_config() { local warn=0 if [[ "${AIRFLOW__DATABASE__SQL_ALCHEMY_CONN}" == sqlite* ]]; then echo "[WARN] Using SQLite — not suitable for production. Set AIRFLOW__DATABASE__SQL_ALCHEMY_CONN as an HF Secret." # SQLite requires SequentialExecutor export AIRFLOW__CORE__EXECUTOR="SequentialExecutor" warn=1 fi if [ "${AIRFLOW_ADMIN_PASSWORD}" = "admin" ]; then echo "[WARN] Using default admin password. Set AIRFLOW_ADMIN_PASSWORD as an HF Secret." warn=1 fi if [ "${warn}" -eq 0 ]; then echo "[OK] Configuration validated." fi }