Merge pull request 'compose: drive app config from .env (env_file, blanket passthrough)' (#243) from compose-env-file into main

This commit was merged in pull request #243.
This commit is contained in:
2026-06-10 08:46:16 -04:00
+27 -48
View File
@@ -51,8 +51,13 @@ services:
command: ["uv", "run", "--no-dev", "alembic", "upgrade", "head"] command: ["uv", "run", "--no-dev", "alembic", "upgrade", "head"]
labels: labels:
com.centurylinklabs.watchtower.enable: "true" com.centurylinklabs.watchtower.enable: "true"
# All app config comes from .env (twelve-factor) — no per-setting allow-list
# to maintain. The `environment:` block below only pins values that must NOT
# come from .env. See the backend service for the full rationale.
env_file:
- path: .env
required: false
environment: environment:
APP_ENV: ${APP_ENV:-development}
DATABASE_URL: ${DATABASE_URL:-postgresql+asyncpg://provenance:provenance@postgres:5432/provenance} DATABASE_URL: ${DATABASE_URL:-postgresql+asyncpg://provenance:provenance@postgres:5432/provenance}
depends_on: depends_on:
postgres: postgres:
@@ -63,50 +68,24 @@ services:
image: git.jpaul.io/justin/provenance-backend:${IMAGE_TAG:-test-main} image: git.jpaul.io/justin/provenance-backend:${IMAGE_TAG:-test-main}
labels: labels:
com.centurylinklabs.watchtower.enable: "true" com.centurylinklabs.watchtower.enable: "true"
# Twelve-factor: ALL application settings come straight from .env — owner,
# AI providers, mailer/SMTP, S3, sessions, everything in app/core/config.py.
# No per-setting allow-list to maintain, so a new setting in .env (and
# .env.example) reaches the app with no compose edit. The `environment:`
# block below is only for values that must NOT come from .env:
# - RUN_MIGRATIONS: backend-only flag, not an app setting.
# - DATABASE_URL: pinned to the compose-internal host as a safety net —
# the code default points at localhost, which is wrong inside the
# network. (.env normally sets it; this guards against it being absent.)
# `environment:` wins over `env_file`, so these always take effect.
# Trade-off (accepted): env_file also exposes infra secrets (POSTGRES_*,
# MINIO_*, CLOUDFLARE_TUNNEL_TOKEN) to the app process; the app ignores them.
env_file:
- path: .env
required: false
environment: environment:
APP_ENV: ${APP_ENV:-development}
# Self-migrate on start so a Watchtower in-place image swap applies any new
# migrations (idempotent). The one-shot `migrate` service covers the same
# for `compose up`; the depends_on below serializes them so they never run
# alembic concurrently.
RUN_MIGRATIONS: "1" RUN_MIGRATIONS: "1"
DATABASE_URL: ${DATABASE_URL:-postgresql+asyncpg://provenance:provenance@postgres:5432/provenance} DATABASE_URL: ${DATABASE_URL:-postgresql+asyncpg://provenance:provenance@postgres:5432/provenance}
# Instance owner/operator — the account(s) with instance-admin rights.
OWNER_EMAIL: ${OWNER_EMAIL:-}
S3_ENDPOINT_URL: ${S3_ENDPOINT_URL:-http://minio:9000}
S3_BUCKET: ${S3_BUCKET:-provenance}
S3_ACCESS_KEY: ${S3_ACCESS_KEY:-provenance}
S3_SECRET_KEY: ${S3_SECRET_KEY:-change-me-too}
S3_REGION: ${S3_REGION:-us-east-1}
# Email / mailer — verification + password-reset links. APP_BASE_URL is the
# base for those links; MAILER=smtp activates the SMTP_* settings.
APP_BASE_URL: ${APP_BASE_URL:-http://localhost}
REQUIRE_EMAIL_VERIFICATION: ${REQUIRE_EMAIL_VERIFICATION:-false}
MAILER: ${MAILER:-console}
SMTP_HOST: ${SMTP_HOST:-}
SMTP_PORT: ${SMTP_PORT:-587}
SMTP_USERNAME: ${SMTP_USERNAME:-}
SMTP_PASSWORD: ${SMTP_PASSWORD:-}
SMTP_FROM: ${SMTP_FROM:-Provenance <no-reply@provenance.local>}
# Model providers (AI assistant + embeddings). Each activates when its key
# is set; DEFAULT_*_PROVIDER picks the default. 'null' keeps AI off.
DEFAULT_LLM_PROVIDER: ${DEFAULT_LLM_PROVIDER:-null}
DEFAULT_EMBEDDING_PROVIDER: ${DEFAULT_EMBEDDING_PROVIDER:-null}
LLM_MAX_TOKENS: ${LLM_MAX_TOKENS:-4096}
EMBEDDING_DIMENSIONS: ${EMBEDDING_DIMENSIONS:-1536}
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-}
ANTHROPIC_MODEL: ${ANTHROPIC_MODEL:-claude-opus-4-8}
OPENAI_API_KEY: ${OPENAI_API_KEY:-}
OPENAI_BASE_URL: ${OPENAI_BASE_URL:-https://api.openai.com/v1}
OPENAI_MODEL: ${OPENAI_MODEL:-gpt-4o}
OPENAI_EMBEDDING_MODEL: ${OPENAI_EMBEDDING_MODEL:-text-embedding-3-small}
XAI_API_KEY: ${XAI_API_KEY:-}
XAI_BASE_URL: ${XAI_BASE_URL:-https://api.x.ai/v1}
XAI_MODEL: ${XAI_MODEL:-grok-2-latest}
OLLAMA_ENABLED: ${OLLAMA_ENABLED:-false}
OLLAMA_BASE_URL: ${OLLAMA_BASE_URL:-http://localhost:11434/v1}
OLLAMA_MODEL: ${OLLAMA_MODEL:-llama3.1}
OLLAMA_EMBEDDING_MODEL: ${OLLAMA_EMBEDDING_MODEL:-nomic-embed-text}
depends_on: depends_on:
postgres: postgres:
condition: service_healthy condition: service_healthy
@@ -133,14 +112,14 @@ services:
command: ["uv", "run", "--no-dev", "python", "-m", "app.worker"] command: ["uv", "run", "--no-dev", "python", "-m", "app.worker"]
labels: labels:
com.centurylinklabs.watchtower.enable: "true" com.centurylinklabs.watchtower.enable: "true"
# Same .env-driven config as the backend (see its comment). The worker reads
# the model-provider settings too, so the upcoming embedding/matching jobs
# are configured the moment they land — no compose change needed.
env_file:
- path: .env
required: false
environment: environment:
APP_ENV: ${APP_ENV:-development}
DATABASE_URL: ${DATABASE_URL:-postgresql+asyncpg://provenance:provenance@postgres:5432/provenance} DATABASE_URL: ${DATABASE_URL:-postgresql+asyncpg://provenance:provenance@postgres:5432/provenance}
S3_ENDPOINT_URL: ${S3_ENDPOINT_URL:-http://minio:9000}
S3_BUCKET: ${S3_BUCKET:-provenance}
S3_ACCESS_KEY: ${S3_ACCESS_KEY:-provenance}
S3_SECRET_KEY: ${S3_SECRET_KEY:-change-me-too}
S3_REGION: ${S3_REGION:-us-east-1}
depends_on: depends_on:
postgres: postgres:
condition: service_healthy condition: service_healthy