# ============================================================================= # DISCLOSURE BUREAU — DEPLOYMENT CONFIG # ============================================================================= # Copy this file to `.env`, fill in the values, never commit `.env`. # When migrating to a different VPS, change ONLY the "VPS CONNECTION" block. # Everything else stays portable. # # To regenerate the secrets block: `./scripts/gen-secrets.sh` # ============================================================================= # ─── VPS CONNECTION ───────────────────────────────────────────────────────── # The only block you change when moving to another VPS. # scripts/ssh.sh, scripts/deploy.sh, scripts/logs.sh all read these. VPS_HOST= # e.g., 187.77.40.19 OR disclosure.example.com VPS_USER=root VPS_PORT=22 VPS_AUTH=password # 'password' or 'key' VPS_PASSWORD= # only if VPS_AUTH=password (kept ONLY in this gitignored .env) VPS_SSH_KEY=~/.ssh/id_ed25519 # only if VPS_AUTH=key VPS_DEPLOY_ROOT=/data/disclosure # where this stack lives on the VPS # ─── PROJECT IDENTITY ─────────────────────────────────────────────────────── PROJECT_NAME=disclosure # docker-compose project name; prefixes all containers STACK_PREFIX=disclosure- # matches the existing pattern on the VPS (unimed-, irmed-, ...) # ─── DOMAINS ──────────────────────────────────────────────────────────────── # Set DNS A records pointing all of these to VPS_HOST before deploying. DOMAIN_MAIN=disclosure.top # Next.js public app DOMAIN_API=api.disclosure.top # Kong (Supabase API gateway) DOMAIN_STUDIO=studio.disclosure.top # Supabase Studio (admin UI — protect with basic-auth) DOMAIN_SEARCH=search.disclosure.top # Meilisearch DOMAIN_IMG=img.disclosure.top # Imgproxy ACME_EMAIL= # for Let's Encrypt cert notifications # ─── HOST PORTS (must NOT collide with other projects on the VPS) ─────────── # Internal ports in containers stay default; these are the host-side mappings. # Each stack on the VPS uses its own range. Pick free ones via `ss -tlnp`. PORT_KONG_HTTP=18001 # Supabase API gateway HTTP PORT_KONG_HTTPS=18444 # Supabase API gateway HTTPS PORT_STUDIO=18002 # Studio UI PORT_NEXT=18003 # Next.js app PORT_MEILI=18004 # Meilisearch PORT_IMGPROXY=18005 # Imgproxy # Postgres NEVER exposed to host; reach it via internal network only. # ─── SECRETS (auto-generated, regenerate per VPS) ─────────────────────────── # Generate fresh values with: ./scripts/gen-secrets.sh POSTGRES_PASSWORD= JWT_SECRET= # 64+ chars, used to sign ANON_KEY and SERVICE_ROLE_KEY ANON_KEY= # JWT signed with role=anon (generated by gen-secrets.sh) SERVICE_ROLE_KEY= # JWT signed with role=service_role DASHBOARD_USERNAME=admin # Studio basic-auth DASHBOARD_PASSWORD= SECRET_KEY_BASE= # used by realtime + auth VAULT_ENC_KEY= # 32-char hex for Supabase Vault MEILI_MASTER_KEY= IMGPROXY_KEY= IMGPROXY_SALT= # ─── CHAT AGENT — providers ───────────────────────────────────────────────── # Primary: Claude Code SDK via OAuth (NEVER use ANTHROPIC_API_KEY in this project). # The container ships the `claude` CLI and authenticates with CLAUDE_CODE_OAUTH_TOKEN. # Get a long-lived OAuth token by running `claude setup-token` locally. CLAUDE_CODE_OAUTH_TOKEN= CLAUDE_CODE_MODEL=haiku # claude-haiku-4-5 alias; or 'sonnet' for harder cases # Fallback: OpenRouter — free or paid models when Claude Code is rate-limited. OPENROUTER_API_KEY= OPENROUTER_MODEL=deepseek/deepseek-v4-flash:free # primary (free, supports tool calls) OPENROUTER_FALLBACK_MODEL=nvidia/nemotron-3-super-120b-a12b:free # Provider selection: # 'openrouter' → tool calling + AG-UI streaming (Pattern C) # 'claude-code' → simple Q&A via OAuth subprocess, no tools # 'auto' → claude-code first, fallback OpenRouter on rate-limit CHAT_PROVIDER=openrouter # ─── EMAIL (for Supabase magic-link delivery) ─────────────────────────────── # Pick ONE: # A) Resend (recommended — free tier 3k/mo) SMTP_HOST=smtp.resend.com SMTP_PORT=465 SMTP_USER=resend SMTP_PASS= SMTP_FROM=noreply@disclosure.top SMTP_FROM_NAME="The Disclosure Bureau" # ─── DATA PATHS (on the VPS) ──────────────────────────────────────────────── # These mount the wiki/, processing/, raw/ trees into the Next.js container. # Sync via `./scripts/sync-data.sh` (rsync from your laptop). DATA_WIKI=/data/disclosure/wiki DATA_PROCESSING=/data/disclosure/processing DATA_RAW=/data/disclosure/raw # ─── RETRIEVAL (embed-service + pgvector) ─────────────────────────────────── # DATABASE_URL: Next.js connects to Postgres inside compose (service name `db`). # For local indexing from your laptop, set this to a tunneled VPS port or local PG. DATABASE_URL=postgres://postgres:${POSTGRES_PASSWORD}@db:5432/postgres EMBED_SERVICE_URL=http://embed:8000 # ─── BACKUPS (optional but recommended) ───────────────────────────────────── BACKUP_ENABLED=false BACKUP_DESTINATION= # e.g., b2:my-bucket/disclosure or s3:bucket/path BACKUP_PASSWORD= # restic repo encryption key B2_ACCOUNT_ID= B2_ACCOUNT_KEY= BACKUP_CRON="0 3 * * *" # daily 3am UTC # ─── RESOURCE LIMITS (tuned for 16GB/4cpu VPS) ────────────────────────────── # Conservative — adjust upward when you see fit. POSTGRES_SHARED_BUFFERS=256MB POSTGRES_WORK_MEM=8MB POSTGRES_MAINTENANCE_WORK_MEM=64MB POSTGRES_MAX_CONNECTIONS=80 MEILI_MAX_INDEXING_MEMORY=512MB NEXT_NODE_OPTIONS="--max-old-space-size=768"