# Every setting the backend reads, with the default it falls back to. Blank # means "off" or "not configured" throughout — nothing here has a secret in it, # and nothing here is required except the database, the secret key and a model. # ── Database and sessions ────────────────────────────────────────────── DATABASE_URL=postgresql://quiz:quiz@postgres:5432/quiz SECRET_KEY=change-me-to-a-random-secret-key-in-production ALGORITHM=HS256 ACCESS_TOKEN_EXPIRE_MINUTES=1440 # The first admin, created only when the database has none. Leave the email # blank too and the first person to register becomes the admin instead. # Set the email and leave the password blank, and one is generated and printed # to the log at first start: docker compose logs backend | grep -A3 "FIRST ADMIN" DEFAULT_ADMIN_EMAIL= DEFAULT_ADMIN_PASSWORD= # Redis: Celery's broker, the rate limiters, job progress and site settings. REDIS_URL=redis://redis:6379/0 # ── Models ───────────────────────────────────────────────────────────── # Everything goes through one LiteLLM proxy. Per-job models (extraction, the # tutor, TTS, and so on) are chosen by an administrator in Settings → AI # models; this is the fallback when a job has no model of its own. LITELLM_MODEL=gpt-4o-mini LITELLM_API_KEY=your-api-key-here LITELLM_API_BASE= # The embedding model, and the one model setting that is NOT editable in the # interface. Every stored vector was produced by it, and vectors from different # models are not comparable — change this and search returns noise until every # question, article and card has been re-embedded. That is a deployment, so it # lives here. `EMBEDDING_DIMENSIONS` must match what the model returns. LITELLM_EMBEDDING_MODEL= EMBEDDING_DIMENSIONS=1024 # The cross-encoder that reorders search results. Unset, unreachable or # malformed and the fused ranking is returned untouched — never fewer results. LITELLM_RERANK_MODEL=cohere-rerank-v4.0-pro # Direct provider keys, used only where the proxy does not carry the service. OPENAI_API_KEY= ELEVENLABS_API_KEY= GOOGLE_TTS_API_KEY= AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= AWS_REGION=us-east-1 AWS_BEDROCK_REGION=us-east-1 # Self-hosted speech, for TTS and dictation without leaving the machine. LOCAL_SPEECH_GATEWAY_URL=http://local-speech-gateway:8110 # ── Where the site lives ─────────────────────────────────────────────── # Used in the links inside emails, so a wrong value sends people nowhere. APP_URL=https://pedshub.com LOG_LEVEL=INFO # ── Storage ──────────────────────────────────────────────────────────── # `local` keeps uploads on the volume at UPLOAD_DIR; `s3` puts them in a # bucket and reads them back through it. Thumbnails live beside the original # either way. STORAGE_BACKEND=local UPLOAD_DIR=/app/uploads MAX_UPLOAD_SIZE=524288000 S3_ENDPOINT_URL=http://minio:9000 S3_ACCESS_KEY= S3_SECRET_KEY= S3_BUCKET=pedshub-media S3_REGION=us-east-1 # Page chunks for extraction context. CHROMA_PERSIST_DIR=/app/chroma_data # ── Email ────────────────────────────────────────────────────────────── # With MAIL_USERNAME or MAIL_FROM blank, mail is logged instead of sent — which # also means sign-in codes and verification links go nowhere. MAIL_USERNAME=your-email@example.com MAIL_PASSWORD=your-app-password MAIL_FROM=your-email@example.com MAIL_PORT=587 MAIL_SERVER=smtp.gmail.com MAIL_STARTTLS=true MAIL_SSL_TLS=false # Where the contact form's messages land. ADMIN_EMAIL= # ── Bot protection ───────────────────────────────────────────────────── # Cap, self-hosted beside the app. Leave the secret blank to disable the # challenge; sign-up then accepts submissions without one. CAP_SECRET_KEY= CAP_SITE_KEY= CAP_API_URL=http://cap:3000 # ── Single sign-on ───────────────────────────────────────────────────── # Any OIDC provider. Blank means the site uses its own accounts only. OIDC_PROVIDER_URL= OIDC_CLIENT_ID= OIDC_CLIENT_SECRET= OIDC_SCOPES=openid email profile OIDC_PROVIDER_NAME=SSO # ── Live sessions ────────────────────────────────────────────────────── BBB_SERVER_URL= BBB_SECRET= # ── Clinical corpus (read-only) ──────────────────────────────────────── # A separate Milvus collection the assistant may query but never write to. CLINICAL_MILVUS_URI= CLINICAL_MILVUS_TOKEN= CLINICAL_MILVUS_COLLECTION=mcp_bge_m3_1024