{"record":{"id":"6e38aaf998ee4ad0","repo":"block/buzz","slug":"buzz-relay-private-key-must-be-set-when-buzz-requi","errorCode":null,"errorMessage":"BUZZ_RELAY_PRIVATE_KEY must be set when BUZZ_REQUIRE_AUTH_TOKEN=true. A stable relay identity is required for production.","messagePattern":"BUZZ_RELAY_PRIVATE_KEY must be set when BUZZ_REQUIRE_AUTH_TOKEN=true\\. A stable relay identity is required for production\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/buzz-relay/src/main.rs","lineNumber":511,"sourceCode":"        .unwrap_or(&config.database_url);\n    let search_pool = sqlx::postgres::PgPoolOptions::new()\n        .connect(search_db_url)\n        .await\n        .map_err(|e| anyhow::anyhow!(\"Search DB connection failed: {e}\"))?;\n    let search = SearchService::new(search_pool);\n    info!(\n        replica = config.read_database_url.is_some(),\n        \"Search service ready (Postgres FTS)\"\n    );\n\n    let workflow_config = buzz_workflow::WorkflowConfig::default();\n    let workflow_engine = Arc::new(WorkflowEngine::new(db.clone(), workflow_config));\n\n    config\n        .media\n        .validate()\n        .map_err(|e| anyhow::anyhow!(\"invalid media config: {e}\"))?;\n    let media_storage = buzz_media::MediaStorage::new(&config.media)\n        .map_err(|e| anyhow::anyhow!(\"failed to initialize media storage: {e}\"))?;\n    info!(\"Media storage connected\");\n\n    let (app_state, audit_shutdown) = AppState::new(\n        config.clone(),\n        db,\n        redis_health_pool,\n        audit,\n        pubsub,\n        auth,\n        search,\n        Arc::clone(&workflow_engine),\n        relay_keypair,\n        media_storage,\n    );\n    let state = Arc::new(app_state);\n\n    // Inter-relay mesh (BUZZ_MESH seam). `boot_mesh` returns None when the","sourceCodeStart":493,"sourceCodeEnd":529,"githubUrl":"https://github.com/block/buzz/blob/dad5a33865fc81a2e55b3b60746632f615ec1e3a/crates/buzz-relay/src/main.rs#L493-L529","documentation":"The relay refuses to start in production mode: BUZZ_REQUIRE_AUTH_TOKEN=true requires BUZZ_RELAY_PRIVATE_KEY so the relay has a stable Nostr identity. A persistent pubkey lets replace_addressable_event replace NIP-33 addressable events across restarts; a fresh key each restart would insert duplicates. When auth tokens are not required (dev mode) the relay falls back to a hardcoded, loudly-warned dev keypair.","triggerScenarios":"Starting buzz-relay with BUZZ_REQUIRE_AUTH_TOKEN=true (or unset-but-defaulting-to-strict behavior) while BUZZ_RELAY_PRIVATE_KEY is missing from the environment; the panic fires during relay key setup in main().","commonSituations":"Docker/Kubernetes deployment where the secret holding the key is not mounted or the env var name is typo'd; copying .env.example without filling the key; enabling the production auth flag without provisioning the relay identity secret.","solutions":["Set BUZZ_RELAY_PRIVATE_KEY to a stable 64-hex-char Nostr secret in the relay environment (generate once and store it as a secret so restarts keep the same relay pubkey)","Restart the relay and confirm the startup log prints the same pubkey each time","For throwaway local development only: set BUZZ_REQUIRE_AUTH_TOKEN=false to fall back to the documented hardcoded dev keypair (never do this in production)"],"exampleFix":"# .env\n# before\nBUZZ_REQUIRE_AUTH_TOKEN=true\n# (BUZZ_RELAY_PRIVATE_KEY unset)\n\n# after\nBUZZ_REQUIRE_AUTH_TOKEN=true\nBUZZ_RELAY_PRIVATE_KEY=<64-hex stable secret from your key generator>","handlingStrategy":"validation","validationCode":"#!/usr/bin/env bash\n# preflight before starting the relay in production mode\nif [ \"${BUZZ_REQUIRE_AUTH_TOKEN:-false}\" = true ]; then\n  : \"${BUZZ_RELAY_PRIVATE_KEY:?BUZZ_RELAY_PRIVATE_KEY must be set when BUZZ_REQUIRE_AUTH_TOKEN=true}\"\n  [[ ${#BUZZ_RELAY_PRIVATE_KEY} -eq 64 && $BUZZ_RELAY_PRIVATE_KEY =~ ^[0-9a-fA-F]+$ ]] \\\n    || { echo 'BUZZ_RELAY_PRIVATE_KEY must be 64 hex chars'; exit 1; }\nfi","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Store the relay key in a secret manager and inject it into the deployment environment; never rely on the dev fallback in shared environments","Pin the same key across restarts so NIP-33 addressable events replace instead of duplicating","Add a deployment healthcheck that fails fast on a missing required env var before the container reaches main()"],"tags":["env-var","relay","startup","panic","config","nostr"],"backgroundTag":"missing-required-env-var","analyzedSha":"dad5a33865fc81a2e55b3b60746632f615ec1e3a","analyzedAt":"2026-08-20T04:38:24.874Z","contentChangedAt":"2026-08-20T04:38:24.874Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}