{"record":{"id":"49bad9a66c1211bf","repo":"block/buzz","slug":"buzz-relay-private-key-is-required-when-buzz-requi","errorCode":null,"errorMessage":"BUZZ_RELAY_PRIVATE_KEY is required when BUZZ_REQUIRE_RELAY_MEMBERSHIP=true. NIP-43 events signed with an ephemeral key become unverifiable after restart.","messagePattern":"BUZZ_RELAY_PRIVATE_KEY is required when BUZZ_REQUIRE_RELAY_MEMBERSHIP=true\\. NIP-43 events signed with an ephemeral key become unverifiable after restart\\.","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"critical","filePath":"crates/buzz-relay/src/main.rs","lineNumber":248,"sourceCode":"    // NIP-43: if membership enforcement is on, a valid owner pubkey is required.\n    // config.rs already strips invalid values with a warning; catch the resulting\n    // None here so we fail fast with a clear message rather than starting a relay\n    // that no one can administer.\n    if config.require_relay_membership && config.relay_owner_pubkey.is_none() {\n        error!(\n            \"BUZZ_REQUIRE_RELAY_MEMBERSHIP=true but RELAY_OWNER_PUBKEY is not set or invalid. \\\n             Set RELAY_OWNER_PUBKEY to a valid 64-char hex pubkey.\"\n        );\n        return Err(anyhow::anyhow!(\n            \"RELAY_OWNER_PUBKEY required when BUZZ_REQUIRE_RELAY_MEMBERSHIP=true\"\n        ));\n    }\n\n    // NIP-43: relay membership requires a stable signing key.\n    // Check this before any DB mutations so we fail fast — no point backfilling\n    // or bootstrapping if we'll reject the config anyway.\n    if config.require_relay_membership && config.relay_private_key.is_none() {\n        return Err(anyhow::anyhow!(\n            \"BUZZ_RELAY_PRIVATE_KEY is required when BUZZ_REQUIRE_RELAY_MEMBERSHIP=true. \\\n             NIP-43 events signed with an ephemeral key become unverifiable after restart.\"\n        ));\n    }\n\n    // NIP-43 / multi-tenant: seed the deployment's *own* community before any\n    // membership backfill or owner bootstrap, so those writes are scoped to a\n    // real `(community_id, pubkey)` and not a global pubkey. The host is derived\n    // from `relay_url` with the *same* normalization request resolution uses\n    // (`relay_url_authority` → `normalize_host`), so the bootstrapped owner lands\n    // in exactly the community that live requests for this host will resolve to.\n    //\n    // `ensure_configured_community` is idempotent, so this is safe to run every\n    // startup. An empty authority (unparseable `relay_url`)\n    // is a misconfiguration — fail fast when membership is enforced rather than\n    // seeding an empty-host community that no request can ever resolve to.\n    let deployment_community = {\n        let host = buzz_relay::tenant::relay_url_authority(&config.relay_url);","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/block/buzz/blob/f956e6fe06a76e50cbd8fba1a162482e752e7f1a/crates/buzz-relay/src/main.rs#L230-L266","documentation":"NIP-43 membership events are signed by the relay's own keypair, so enforcement requires the stable BUZZ_RELAY_PRIVATE_KEY. This fatal error fires when BUZZ_REQUIRE_RELAY_MEMBERSHIP=true but no private key is configured — events signed with an ephemeral key would become unverifiable after restart, so boot aborts before any DB mutations.","triggerScenarios":"BUZZ_REQUIRE_RELAY_MEMBERSHIP=true with BUZZ_RELAY_PRIVATE_KEY unset (checked before backfill/bootstrap so nothing is written first).","commonSituations":"Enabling enforcement on a deployment that previously relied on dev-mode key generation; the k8s secret not mounted into the pod; key present locally but missing in the CI/staging environment.","solutions":["Generate a stable secp256k1 private key and set BUZZ_RELAY_PRIVATE_KEY (64-char hex)","Confirm the secret actually reaches the process: `env | grep BUZZ_RELAY_PRIVATE_KEY`","Or set BUZZ_REQUIRE_RELAY_MEMBERSHIP=false until the key is provisioned"],"exampleFix":"# before\nBUZZ_REQUIRE_RELAY_MEMBERSHIP=true\n# BUZZ_RELAY_PRIVATE_KEY unset\n\n# after\nBUZZ_REQUIRE_RELAY_MEMBERSHIP=true\nBUZZ_RELAY_PRIVATE_KEY=81100d7eeb199f8565d5a9c0d5f01b5f5a3395e8b4e4b6b1e2a9c8d7e6f5a4b3","handlingStrategy":"validation","validationCode":"# Both must be present together before boot.\nif [ \"$BUZZ_REQUIRE_RELAY_MEMBERSHIP\" = \"true\" ] && [ -z \"${BUZZ_RELAY_PRIVATE_KEY:-}\" ]; then\n  echo 'BUZZ_RELAY_PRIVATE_KEY is required when BUZZ_REQUIRE_RELAY_MEMBERSHIP=true'\n  exit 1\nfi","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Provision the relay signing key in the secret store before enabling enforcement","Smoke-test the pod env (`env | grep BUZZ_RELAY_PRIVATE_KEY`) in staging","Generate the key once and back it up — NIP-43 events become unverifiable if it changes"],"tags":["config","nip-43","env-vars","startup","signing"],"backgroundTag":"missing-env-var","analyzedSha":"f956e6fe06a76e50cbd8fba1a162482e752e7f1a","analyzedAt":"2026-08-16T22:11:40.750Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}