OpenNHP/opennhp · critical
failed to generate random cookie signing key
Error message
failed to generate random cookie signing key: %v
What it means
UdpServer.Start generates a random 32-byte cookie signing key when CookieSigningKeyBase64 is unset, and returns this error if crypto/rand fails to produce those bytes. This is an environment/OS-level entropy failure, not a config problem.
Solutions
- Restart the process — rand.Read failures are typically transient OS-level conditions
- Fix the container sandbox so getrandom(2)/getentropy is permitted (adjust seccomp/AppArmor profile)
- Ensure /dev/urandom is available in the container or jail
- Set CookieSigningKeyBase64 explicitly to skip the random-generation path entirely
Example fix
// before (docker run) docker run --security-opt seccomp:strict-random.json nhp-server // after (allow getrandom in the profile, or pre-supply the key) environment: - CookieSigningKeyBase64=<base64 32-byte key>
Defensive patterns
Strategy: try-catch
Try / catch
if err := srv.Start(); err != nil {
if strings.Contains(err.Error(), "random cookie signing key") {
log.Fatalf("entropy unavailable on host: %v — fix OS randomness source or set CookieSigningKeyBase64", err)
}
return err
} Prevention
- Pre-supply CookieSigningKeyBase64 so the rand.Read path is never exercised in production
- Verify containers permit getrandom(2) before shipping seccomp profiles
- Confirm /dev/urandom exists in minimal images
When it happens
Trigger: Calling Start with an empty CookieSigningKeyBase64 while rand.Read on the 32-byte buffer returns an error (e.g. exhausted or blocked system entropy source).
Common situations: Containers/seccomp profiles blocking getrandom(2); misconfigured chroots lacking /dev/urandom; heavily degraded kernels in embedded environments.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- private key parse error
- failed to create device
- server peer config invalid on initial load
- failed to create device
- failed to create device from new key
AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07).
Data as JSON: /api/errors/e0a705c76513fb8f.
Report an issue: GitHub.
Appendix: source
Thrown at endpoints/server/udpserver.go:298
// verify a cookie that a sibling minted. When the operator hasn't
// configured one we mint a random per-process key — fine for a single
// instance, broken for a cluster (the failure is silent: cookies
// minted by replica A don't verify on replica B and the agent's RKN
// stalls until timeout). Always log which mode we're in.
cookieKey, cookieKeyErr := decodeCookieSigningKey(s.config.CookieSigningKeyBase64)
if cookieKeyErr != nil {
// Malformed (not empty) is an ops mistake — fail fast rather
// than silently degrading to a per-process random key. Silent
// fallback would let a cluster look healthy while its replicas
// each mint cookies a sibling can't verify.
log.Critical("invalid CookieSigningKeyBase64 in config: %v", cookieKeyErr)
return fmt.Errorf("invalid CookieSigningKeyBase64: %w", cookieKeyErr)
}
if len(cookieKey) == 0 {
cookieKey = make([]byte, 32)
if _, readErr := rand.Read(cookieKey); readErr != nil {
log.Critical("failed to generate random cookie signing key: %v", readErr)
return fmt.Errorf("failed to generate random cookie signing key: %v", readErr)
}
log.Info("CookieSigningKeyBase64 not set; using a random per-process key (single-instance only — clusters must share an operator-supplied key)")
} else {
log.Info("CookieSigningKeyBase64 configured; cookies are stateless and shared across the cluster")
// Catch operators who copy the docker-compose demo config and
// forget to regenerate the shared key. The shipped value is
// public (committed to docker/nhp-server/etc/config.toml so
// `docker-compose up` works out of the box) — running it in
// any environment a real client can reach lets anyone who has
// browsed the repo mint cookies the server will accept.
// Critical (not Warning) so it surfaces in default journalctl
// filters and any oncall log-volume alarms.
if s.config.CookieSigningKeyBase64 == shippedDemoCookieSigningKeyBase64 {
log.Critical("CookieSigningKeyBase64 matches the docker-compose demo value committed at " +
"docker/nhp-server/etc/config.toml — this key is PUBLIC. Regenerate before any " +
"deployment reachable from outside the host (use `nhp-serverd keygen --curve` or " +
"`openssl rand -base64 32`).")
}View on GitHub (pinned to 6e04ca5ff0)