# Coves Local Development Environment Configuration # This file contains all environment variables for the local atProto development stack # DO NOT commit secrets to version control in production! # ============================================================================= # PostgreSQL Configuration (Development Database) # ============================================================================= # Development database for Coves AppView (runs on port 5435) POSTGRES_HOST=localhost POSTGRES_PORT=5435 POSTGRES_DB=coves_dev POSTGRES_USER=dev_user POSTGRES_PASSWORD=dev_password # ============================================================================= # PDS (Personal Data Server) Configuration # ============================================================================= # PDS runs on port 3001 (to avoid conflict with production PDS on :3000) PDS_HOSTNAME=localhost PDS_PORT=3001 # PDS Service Endpoint for DIDs # This is the URL that goes in DID documents' atproto_pds service endpoint # Must match what the PDS thinks its public URL is (internal port 3000) # Development: http://localhost:3000 (PDS's internal view) # Production: https://pds.coves.social PDS_SERVICE_ENDPOINT=http://localhost:3000 # DID PLC Directory for PDS # For local E2E testing: Use local PLC (requires --profile plc) # Note: Use container hostname for PDS to reach PLC within Docker network PDS_DID_PLC_URL=http://plc-directory:3000 # JWT Secret (for signing tokens - change in production!) PDS_JWT_SECRET=local-dev-jwt-secret-change-in-production # Admin password for PDS management PDS_ADMIN_PASSWORD=admin # Handle domains (users will get handles like alice.local.coves.dev) # Communities will use .community.coves.social (singular per atProto conventions) PDS_SERVICE_HANDLE_DOMAINS=.local.coves.dev,.community.coves.social # PLC Rotation Key (k256 private key in hex format - for local dev only) # This is a randomly generated key for testing - DO NOT use in production PDS_PLC_ROTATION_KEY=af514fb84c4356241deed29feb392d1ee359f99c05a7b8f7bff2e5f2614f64b2 # ============================================================================= # AppView Configuration (Your Go Application) # ============================================================================= # AppView runs on port 8081 (to avoid conflicts) APPVIEW_PORT=8081 # PDS Firehose URL (WebSocket connection - direct to PDS, no relay) FIREHOSE_URL=ws://localhost:3001/xrpc/com.atproto.sync.subscribeRepos # PDS URL (for XRPC calls) PDS_URL=http://localhost:3001 # ============================================================================= # Test Database Configuration # ============================================================================= # Test database runs on port 5434 (separate from dev on 5433) POSTGRES_TEST_DB=coves_test POSTGRES_TEST_USER=test_user POSTGRES_TEST_PASSWORD=test_password POSTGRES_TEST_PORT=5434 # ============================================================================= # Jetstream Configuration (Read-Forward User Indexing) # ============================================================================= # Jetstream WebSocket URL for real-time atProto events # # Production: Use Bluesky's public Jetstream (indexes entire network) # JETSTREAM_URL=wss://jetstream2.us-east.bsky.network/subscribe?wantedCollections=app.bsky.actor.profile # # Local E2E Testing: Use local Jetstream (indexes only local PDS) # 1. Start local Jetstream: docker-compose --profile jetstream up pds jetstream # 2. Use this URL: JETSTREAM_URL=ws://localhost:6008/subscribe # Optional: Filter events to specific PDS # JETSTREAM_PDS_FILTER=http://localhost:3001 # ============================================================================= # Identity Resolution Configuration # ============================================================================= # IMPORTANT: In dev mode (IS_DEV_ENV=true), identity resolution automatically # uses PLC_DIRECTORY_URL to ensure E2E tests stay local. In production, you # can optionally set IDENTITY_PLC_URL to use a different URL for read operations. # # For local dev: Leave IDENTITY_PLC_URL unset (uses PLC_DIRECTORY_URL) # For production: Optionally set IDENTITY_PLC_URL=https://plc.directory # Cache TTL for resolved identities (Go duration format: 24h, 1h30m, etc.) IDENTITY_CACHE_TTL=24h # ============================================================================= # OAuth Configuration # ============================================================================= # OAuth client private key (ES256 keypair - generate with: go run cmd/genjwks/main.go) # DO NOT commit this to version control in production! # # Supports two formats: # 1. Plain JSON (easier for local development): # OAUTH_PRIVATE_JWK={"alg":"ES256","crv":"P-256",...} # # 2. Base64 encoded (recommended for production to avoid shell escaping): # OAUTH_PRIVATE_JWK=base64:eyJhbGciOiJFUzI1NiIsImNydiI6IlAtMjU2Ii... # Generate with: echo '{"alg":...}' | base64 -w 0 # OAUTH_PRIVATE_JWK={"alg":"ES256","crv":"P-256","d":"9tCMceYSgyZfO5KYOCm3rWEhXLqq2l4LjP7-PJtJKyk","kid":"oauth-client-key","kty":"EC","use":"sig","x":"EOYWEgZ2d-smTO6jh0f-9B7YSFYdlrvlryjuXTCrOjE","y":"_FR2jBcWNxoJl5cd1eq9sYtAs33No9AVtd42UyyWYi4"} # Cookie secret for session encryption (generate with: openssl rand -hex 32) # Also supports base64: prefix for consistency OAUTH_COOKIE_SECRET=f1132c01b1a625a865c6c455a75ee793572cedb059cebe0c4c1ae4c446598f7d # Seal secret for OAuth session tokens (AES-256-GCM encryption) # Generate with: openssl rand -base64 32 # This must be 32 bytes when base64-decoded for AES-256 # OAUTH_SEAL_SECRET=ryW6xNVxYhP6hCDA90NGCmK58Q2ONnkYXbHL0oZN2no= # AppView public URL (used for OAuth callback and client metadata) # Dev: http://127.0.0.1:8081 (use 127.0.0.1 instead of localhost per RFC 8252) # Prod: https://coves.social APPVIEW_PUBLIC_URL=http://127.0.0.1:8081 # ============================================================================= # Coves Instance PDS Authentication # ============================================================================= # The Coves instance needs a PDS account to write community records # Create this account once: curl -X POST http://localhost:3001/xrpc/com.atproto.server.createAccount PDS_INSTANCE_HANDLE=testuser123.local.coves.dev PDS_INSTANCE_PASSWORD=test-password-123 # Kagi News Aggregator DID (for trusted thumbnail URLs) KAGI_AGGREGATOR_DID=did:plc:yyf34padpfjknejyutxtionr # ============================================================================= # Development Settings # ============================================================================= # Environment ENV=development NODE_ENV=development # Always true for local development (use PLC_DIRECTORY_URL to control registration) IS_DEV_ENV=true # Security: Skip did:web domain verification for local development # IMPORTANT: Set to false in production to prevent domain spoofing attacks # When true, communities can claim any hostedByDID without verification # When false, hostedByDID must match the community handle domain SKIP_DID_WEB_VERIFICATION=true # Authentication: Skip JWT signature verification for local development (Phase 1) # IMPORTANT: Set to false in production for full signature verification # When true, only parses JWT without verifying signature (trusts any valid JWT format) # When false, verifies JWT signature against issuer's JWKS AUTH_SKIP_VERIFY=true # HS256 Issuers: PDSes allowed to use HS256 (shared secret) authentication # Must share PDS_JWT_SECRET with Coves instance. External PDSes use ES256 via DID resolution. # For local dev, allow the local PDS or turn AUTH_SKIP_VERIFY = true HS256_ISSUERS=http://localhost:3001 # Logging LOG_LEVEL=debug LOG_ENABLED=true # ============================================================================= # PLC Directory Configuration # ============================================================================= # URL for PLC (Public Ledger of Credentials) directory # # For local E2E testing with registration: http://localhost:3002 (requires --profile plc) # - Registers DIDs with local PLC directory # - Safe for testing, won't pollute production plc.directory # - PDS must also be configured to use local PLC (see PDS_DID_PLC_URL) # # Production: https://plc.directory (currently Bluesky's, will transfer to third party) # - DO NOT use production PLC for testing! # PLC_DIRECTORY_URL=http://localhost:3002 # ============================================================================= # Dev Mode Quick Reference # ============================================================================= # REQUIRED for local OAuth to work with local PDS: # IS_DEV_ENV=true # Master switch for dev mode # PDS_URL=http://localhost:3001 # Local PDS for handle resolution # PLC_DIRECTORY_URL=http://localhost:3002 # Local PLC directory # APPVIEW_PUBLIC_URL=http://127.0.0.1:8081 # Use IP not localhost (RFC 8252) # # BUILD TAGS: # make run - Runs with -tags dev (includes localhost OAuth resolvers) # make build - Production binary (no dev code) # make build-dev - Dev binary (includes dev code) # # Dev-only code (only compiled with -tags dev): # - internal/atproto/oauth/dev_resolver.go (handle resolution via local PDS) # - internal/atproto/oauth/dev_auth_resolver.go (localhost OAuth bypass) # # ============================================================================= # Notes # ============================================================================= # All local development configuration in one file! # - Dev PostgreSQL: port 5435 # - Test PostgreSQL: port 5434 (via --profile test) # - PDS: port 3001 (avoids conflict with production on :3000) # - AppView: port 8081 # - PDS is self-contained (SQLite + CAR files) # - PostgreSQL is only for Coves AppView indexing # - AppView subscribes directly to PDS firehose (no relay needed) # - PDS firehose: ws://localhost:3001/xrpc/com.atproto.sync.subscribeRepos