# ── Server A (port 3000) ───────────────────────────────────────────────────── # Copy this file to tests/docker/sipher-a.env, then run: # bun run docker:generate-keys # That will write unique federation keypairs into each tests/docker/sipher-*.env file. NODE_ENV=development PORT=3000 # Signals to auth.ts that this is the federation test cluster — disables the # real EmailService construction without affecting Next.js dev/prod heuristics # (Next.js statically rewrites process.env.NODE_ENV, which would otherwise # defeat any NODE_ENV-based check at runtime). SIPHER_TEST_MODE=true # Public base URL as seen by OTHER federation peers inside the Docker network. # Integration test scripts also run inside Docker on the same network, so this # is always the right value; no host.docker.internal tricks needed. BETTER_AUTH_URL=http://sipher-a:3000 # Must be unique per instance and kept secret in production. BETTER_AUTH_SECRET=CHANGE_ME_SECRET_A # Each instance gets its own Postgres database. DATABASE_URL=postgresql://sipher:sipher_test@postgres:5432/sipher_a # Each instance gets its own Redis logical DB so BullMQ queues don't cross-contaminate. REDIS_URL=redis://redis:6379/0 # Allow federation fetches to other sipher-* service names (Docker internal DNS). # The url-guard checks these by hostname before doing IP resolution, so this # safely bypasses the private-IP block for intra-cluster traffic only. # # `sipher-unreachable.test` is intentionally non-existent — it passes the # url-guard but fails DNS lookup, producing the DNS_BLOCKED federation error # code which the threat model classifies as proxy-eligible. The failover # integration test (tests/integration/proxy-chain.ts) uses this to force the # real `federationFetch` proxy-fallback path without disrupting the live cluster. DEV_ALLOWED_HOSTNAMES=sipher-a,sipher-b,sipher-c,sipher-unreachable.test # Needed because Docker container IPs are in the 172.x private range. FEDERATION_ALLOW_PRIVATE_URLS=true DEBUG=app:*,test:* # ── Email (not required for federation tests — leave empty to disable) ──────── EMAIL_HOST= EMAIL_PORT= EMAIL_SECURE= EMAIL_USER= EMAIL_PASSWORD= # ── MinIO (not exercised by the federation tests, but minio.client.ts throws # at import time if any of these are unset, so dummy values keep auth loadable) MINIO_BUCKET=sipher-test MINIO_ENDPOINT=minio.local MINIO_PORT=9000 MINIO_USE_SSL=false MINIO_ACCESS_KEY=test-access-key MINIO_SECRET_KEY=test-secret-key # ── Federation keys — filled in by: bun run docker:generate-keys ───────────── FEDERATION_PUBLIC_KEY= FEDERATION_PRIVATE_KEY= FEDERATION_ENCRYPTION_PUBLIC_KEY= FEDERATION_ENCRYPTION_PRIVATE_KEY=