Environment Variables

docsfy runtime configuration is defined in code and loaded via pydantic-settings from .env (plus environment variables).

class Settings(BaseSettings):
    model_config = SettingsConfigDict(
        env_file=".env",
        env_file_encoding="utf-8",
        extra="ignore",
    )

    admin_key: str = ""  # Required — validated at startup
    ai_provider: str = "claude"
    ai_model: str = "claude-opus-4-6[1m]"  # [1m] = 1 million token context window
    ai_cli_timeout: int = Field(default=60, gt=0)
    log_level: str = "INFO"
    data_dir: str = "/data"
    secure_cookies: bool = True  # Set to False for local HTTP dev
@lru_cache
def get_settings() -> Settings:
    return Settings()

Tip: get_settings() is cached. After changing environment variables, restart the process to apply them.

Core Runtime Variables

Variable Required Default Description
ADMIN_KEY Yes (none) Admin authentication secret. Required at startup, minimum length 16. Also used as HMAC secret for stored user API key hashes.
AI_PROVIDER No claude Default AI provider used by dashboard + /api/generate when request does not specify one. Allowed providers: claude, gemini, cursor.
AI_MODEL No claude-opus-4-6[1m] Default model name used when request omits ai_model.
AI_CLI_TIMEOUT No 60 Default timeout for AI CLI calls (seconds). Must be > 0.
LOG_LEVEL No INFO Logging level setting exposed in app config (log_level).
DATA_DIR No /data Base directory for SQLite DB and generated artifacts.
SECURE_COOKIES No true Controls Secure flag on session cookie.

Note: LOG_LEVEL is present in settings and .env.example; repository code does not directly call setLevel(), so final filtering behavior depends on python-simple-logger configuration.

Validation and Fallback Behavior

ADMIN_KEY is enforced at app startup:

settings = get_settings()
if not settings.admin_key:
    logger.error("ADMIN_KEY environment variable is required")
    raise SystemExit(1)

if len(settings.admin_key) < 16:
    logger.error("ADMIN_KEY must be at least 16 characters long")
    raise SystemExit(1)

Provider/model/timeout defaulting in /api/generate:

settings = get_settings()
ai_provider = gen_request.ai_provider or settings.ai_provider
ai_model = gen_request.ai_model or settings.ai_model
...
ai_cli_timeout=gen_request.ai_cli_timeout or settings.ai_cli_timeout

Provider and model are validated before generation:

if ai_provider not in ("claude", "gemini", "cursor"):
    raise HTTPException(
        status_code=400,
        detail=f"Invalid AI provider: '{ai_provider}'. Must be claude, gemini, or cursor.",
    )
if not ai_model:
    raise HTTPException(status_code=400, detail="AI model must be specified.")

Timeout validation is strict in both settings and request schema:

ai_cli_timeout: int = Field(default=60, gt=0)
ai_cli_timeout: int | None = Field(default=None, gt=0)

AI Provider Credential Variables

From the repository .env.example:

# Claude - Option 1: API Key
# ANTHROPIC_API_KEY=

# Claude - Option 2: Vertex AI
# CLAUDE_CODE_USE_VERTEX=1
# CLOUD_ML_REGION=
# ANTHROPIC_VERTEX_PROJECT_ID=

# Gemini
# GEMINI_API_KEY=

# Cursor
# CURSOR_API_KEY=

Note: docsfy passes provider/model/timeout to call_ai_cli(...); provider credential variables are expected to be present in the process environment for the installed CLIs.

DATA_DIR controls persistent paths:

DB_PATH = Path(os.getenv("DATA_DIR", "/data")) / "docsfy.db"
DATA_DIR = Path(os.getenv("DATA_DIR", "/data"))
PROJECTS_DIR = DATA_DIR / "projects"

ADMIN_KEY is also used for API key hashing:

secret = hmac_secret or os.getenv("ADMIN_KEY", "")
if not secret:
    msg = "ADMIN_KEY environment variable is required for key hashing"
    raise RuntimeError(msg)
return hmac.new(secret.encode(), key.encode(), hashlib.sha256).hexdigest()

Warning: Rotating ADMIN_KEY invalidates existing stored user API key hashes. Users must regenerate API keys after rotation.

Session cookie flags are set from config:

response.set_cookie(
    "docsfy_session",
    session_token,
    httponly=True,
    samesite="strict",
    secure=settings.secure_cookies,
    max_age=SESSION_TTL_SECONDS,
)

.env.example includes:

# Set to false for local HTTP development
# SECURE_COOKIES=false

Tip: For local non-HTTPS development, set SECURE_COOKIES=false so browsers send the session cookie over HTTP.

Process Runtime Variables (docsfy CLI)

When starting via the Python entrypoint (docsfy script), these are read:

reload = os.getenv("DEBUG", "").lower() == "true"
host = os.getenv("HOST", "127.0.0.1")
port = int(os.getenv("PORT", "8000"))
uvicorn.run("docsfy.main:app", host=host, port=port, reload=reload)
  • DEBUG: enables uvicorn reload when set to "true".
  • HOST: bind address (default 127.0.0.1).
  • PORT: bind port (default 8000).

Note: In Docker, HOST/PORT/DEBUG are bypassed because the container entrypoint launches uvicorn with fixed arguments.

ENTRYPOINT ["uv", "run", "--no-sync", "uvicorn", "docsfy.main:app", "--host", "0.0.0.0", "--port", "8000"]

Docker Compose Environment Snippet

services:
  docsfy:
    build: .
    ports:
      - "8000:8000"
    env_file: .env
    volumes:
      - ./data:/data

Repository .env Template

# REQUIRED - Admin key for user management (minimum 16 characters)
ADMIN_KEY=your-secure-admin-key-here-min-16-chars

# AI Configuration
AI_PROVIDER=claude
# [1m] = 1 million token context window, this is a valid model identifier
AI_MODEL=claude-opus-4-6[1m]
AI_CLI_TIMEOUT=60

# Claude - Option 1: API Key
# ANTHROPIC_API_KEY=

# Claude - Option 2: Vertex AI
# CLAUDE_CODE_USE_VERTEX=1
# CLOUD_ML_REGION=
# ANTHROPIC_VERTEX_PROJECT_ID=

# Gemini
# GEMINI_API_KEY=

# Cursor
# CURSOR_API_KEY=

# Logging
LOG_LEVEL=INFO

# Set to false for local HTTP development
# SECURE_COOKIES=false

Runtime Constants (Not Environment-Configurable)

These runtime settings exist in code but are not currently exposed as environment variables:

SESSION_TTL_SECONDS = 28800  # 8 hours
SESSION_TTL_HOURS = SESSION_TTL_SECONDS // 3600
MAX_CONCURRENT_PAGES = 5
await asyncio.wait_for(task, timeout=5.0)