block/buzz · critical

BUZZ_RELAY_PRIVATE_KEY must be set when BUZZ_REQUIRE_AUTH_TO

Error message

BUZZ_RELAY_PRIVATE_KEY must be set when BUZZ_REQUIRE_AUTH_TOKEN=true. A stable relay identity is required for production.

What it means

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.

Source

Thrown at crates/buzz-relay/src/main.rs:511

        .unwrap_or(&config.database_url);
    let search_pool = sqlx::postgres::PgPoolOptions::new()
        .connect(search_db_url)
        .await
        .map_err(|e| anyhow::anyhow!("Search DB connection failed: {e}"))?;
    let search = SearchService::new(search_pool);
    info!(
        replica = config.read_database_url.is_some(),
        "Search service ready (Postgres FTS)"
    );

    let workflow_config = buzz_workflow::WorkflowConfig::default();
    let workflow_engine = Arc::new(WorkflowEngine::new(db.clone(), workflow_config));

    config
        .media
        .validate()
        .map_err(|e| anyhow::anyhow!("invalid media config: {e}"))?;
    let media_storage = buzz_media::MediaStorage::new(&config.media)
        .map_err(|e| anyhow::anyhow!("failed to initialize media storage: {e}"))?;
    info!("Media storage connected");

    let (app_state, audit_shutdown) = AppState::new(
        config.clone(),
        db,
        redis_health_pool,
        audit,
        pubsub,
        auth,
        search,
        Arc::clone(&workflow_engine),
        relay_keypair,
        media_storage,
    );
    let state = Arc::new(app_state);

    // Inter-relay mesh (BUZZ_MESH seam). `boot_mesh` returns None when the

View on GitHub (pinned to dad5a33865)

Solutions

  1. 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)
  2. Restart the relay and confirm the startup log prints the same pubkey each time
  3. 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)

Example fix

# .env
# before
BUZZ_REQUIRE_AUTH_TOKEN=true
# (BUZZ_RELAY_PRIVATE_KEY unset)

# after
BUZZ_REQUIRE_AUTH_TOKEN=true
BUZZ_RELAY_PRIVATE_KEY=<64-hex stable secret from your key generator>
Defensive patterns

Strategy: validation

Validate before calling

#!/usr/bin/env bash
# preflight before starting the relay in production mode
if [ "${BUZZ_REQUIRE_AUTH_TOKEN:-false}" = true ]; then
  : "${BUZZ_RELAY_PRIVATE_KEY:?BUZZ_RELAY_PRIVATE_KEY must be set when BUZZ_REQUIRE_AUTH_TOKEN=true}"
  [[ ${#BUZZ_RELAY_PRIVATE_KEY} -eq 64 && $BUZZ_RELAY_PRIVATE_KEY =~ ^[0-9a-fA-F]+$ ]] \
    || { echo 'BUZZ_RELAY_PRIVATE_KEY must be 64 hex chars'; exit 1; }
fi

Prevention

When it happens

Trigger: 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().

Common situations: 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.

Related errors


AI-assisted analysis of block/buzz@dad5a33865 (2026-08-20). Data as JSON: /api/errors/6e38aaf998ee4ad0. Report an issue: GitHub.