Replaces the implicit Let's Encrypt flow with a general corporate-CA HTTPS path: - Caddy switches to cert-file mode (`tls /certs/fullchain.pem /certs/privkey.pem`) with HSTS + TLS 1.2/1.3 floor - New `docker-compose.tls.yml` overlay closes host `:8000` when Caddy fronts (no TLS bypass) - New `scripts/tls-fetch.sh` — generic URL fetcher for `sm://`, `gs://`, `https://`, `file://` with redirect refusal + PEM validation - New `scripts/grpn/agnes-tls-rotate.sh` — daily rotation, self-signed fallback against same key (zero key churn), on-VM RSA-2048 + CSR auto-gen, atomic swap, SIGUSR1 reload - `scripts/grpn/agnes-auto-upgrade.sh` becomes cert-aware (auto-enables tls overlay when certs present) - Compose profile `production` renamed to `tls` (aligns with DEPLOYMENT.md and infra startup) Pairs with FoundryAI/agnes-the-ai-analyst-infra#27 (merged) which wires per-VM `local.vm_tls`, writes `TLS_*` env vars into `.env`, auto-creates Secret Manager containers for `sm://` privkey URLs, and installs `agnes-tls-rotate.{service,timer}` for daily polling. Includes hardening + docs follow-ups from code review: - `TLS_CSR_SUBJECT` env-var parametrisation applied to both CSR and self-signed cert paths - curl `--max-redirs 0 --proto '=https'` + post-fetch PEM validation in `tls-fetch.sh` - `ulimit -c 0` + array-form `COMPOSE_FILES` (POSIX-safe, bash 3.2 compatible) - TLS section added to `config/.env.template` - Historical-note headers in `docs/superpowers/{plans,specs}/2026-04-09-*.md` flagging the profile rename
90 lines
4.2 KiB
Text
90 lines
4.2 KiB
Text
# Agnes AI Data Analyst - Environment Variables
|
|
# =============================================
|
|
# Copy to .env: cp config/.env.template .env
|
|
# .env is gitignored - NEVER commit it.
|
|
|
|
# ── REQUIRED ────────────────────────────────────────
|
|
JWT_SECRET_KEY= # python -c "import secrets; print(secrets.token_hex(32))"
|
|
SESSION_SECRET= # python -c "import secrets; print(secrets.token_hex(32))"
|
|
|
|
# ── GOOGLE OAUTH (required for Google login) ────────
|
|
# GOOGLE_CLIENT_ID=
|
|
# GOOGLE_CLIENT_SECRET=
|
|
|
|
# ── KEBOOLA (required for Keboola data source) ──────
|
|
# KEBOOLA_STORAGE_TOKEN=
|
|
# KEBOOLA_STACK_URL=https://connection.keboola.com
|
|
|
|
# ── BIGQUERY (required for BigQuery data source) ─────
|
|
# BIGQUERY_PROJECT=
|
|
# BIGQUERY_LOCATION=us
|
|
|
|
# ── BOOTSTRAP (first deploy only) ───────────────────
|
|
# SEED_ADMIN_EMAIL=admin@example.com
|
|
# SEED_ADMIN_PASSWORD= # Dev helper only — sets password_hash on seed.
|
|
# # Never overwrites an existing password.
|
|
|
|
# ── EMAIL / SMTP (required for magic link auth) ─────
|
|
# SMTP_HOST=smtp.gmail.com
|
|
# SMTP_PORT=587
|
|
# SMTP_USER=
|
|
# SMTP_PASSWORD=
|
|
|
|
# ── OPTIONAL SERVICES ───────────────────────────────
|
|
# TELEGRAM_BOT_TOKEN=
|
|
# JIRA_WEBHOOK_SECRET=
|
|
# JIRA_API_TOKEN=
|
|
# ANTHROPIC_API_KEY=
|
|
# LLM_API_KEY=
|
|
|
|
# ── DESKTOP APP ─────────────────────────────────────
|
|
# DESKTOP_JWT_SECRET= # Separate secret for desktop app tokens
|
|
|
|
# ── DEPLOYMENT ──────────────────────────────────────
|
|
# DATA_DIR=/data # Default: /data in Docker, ./data locally
|
|
# LOG_LEVEL=info # debug, info, warning, error
|
|
# CORS_ORIGINS=http://localhost:3000,http://localhost:8000
|
|
|
|
# ── HTTPS / REVERSE PROXY ───────────────────────────
|
|
# Set these when the app runs behind a TLS terminator (Caddy, Cloudflare
|
|
# Tunnel, nginx, GCP LB, etc.). The app itself speaks plain HTTP on :8000;
|
|
# the terminator is responsible for TLS.
|
|
#
|
|
# DOMAIN: public hostname. When set, session cookies get the `Secure` flag
|
|
# (browser only sends them over HTTPS). Also used by the Caddy
|
|
# profile to auto-provision Let's Encrypt certs.
|
|
# DOMAIN=data.yourcompany.com
|
|
#
|
|
# SERVER_URL: absolute base URL used to build OAuth callback URLs and other
|
|
# external links. Set this to avoid relying on the incoming
|
|
# request's Host header (which a misconfigured proxy can get
|
|
# wrong). Must match the redirect URI registered in OAuth apps.
|
|
# SERVER_URL=https://data.yourcompany.com
|
|
#
|
|
# Uvicorn is started with `--proxy-headers --forwarded-allow-ips='*'` so it
|
|
# trusts X-Forwarded-Proto / X-Forwarded-For from the reverse proxy.
|
|
|
|
# ── TLS TERMINATION (Caddy in cert-file mode) ───────
|
|
# When TLS_FULLCHAIN_URL is set, scripts/grpn/agnes-tls-rotate.sh fetches
|
|
# the cert daily from this URL and reloads Caddy on diff (zero downtime).
|
|
# Empty -> no TLS, app serves plain HTTP on :8000. See docs/DEPLOYMENT.md
|
|
# -> TLS for the full bring-up flow.
|
|
#
|
|
# Supported URL schemes (all four scripts/tls-fetch.sh resolves):
|
|
# sm://<secret-name> Google Secret Manager (latest version)
|
|
# gs://<bucket>/<obj> GCS object
|
|
# https://<url> Plain HTTPS download (no redirects allowed)
|
|
# file://<path> Local file (dev/testing only)
|
|
#
|
|
# TLS_FULLCHAIN_URL=
|
|
#
|
|
# TLS_PRIVKEY_URL: optional. Empty -> on-VM RSA-2048 key + CSR auto-
|
|
# generated on first rotate tick (key never leaves the host; CSR at
|
|
# /data/state/certs/cert.csr to submit to your CA). Set to a URL when
|
|
# you want VM-replace resilience (e.g. sm://<secret>).
|
|
# TLS_PRIVKEY_URL=
|
|
#
|
|
# TLS_CSR_SUBJECT: stamped on auto-generated CSRs and on the self-signed
|
|
# bring-up cert that Caddy serves until your CA publishes the real chain.
|
|
# Defaults to /CN=$DOMAIN when unset.
|
|
# TLS_CSR_SUBJECT=/C=US/ST=California/L=San Francisco/O=Your Org/CN=data.yourcompany.com
|