netbirdio/netbird · error
generate root key: %w
Error message
generate root key: %w
What it means
reposign.GenerateRootKey failed (root.go:50). The function generates an Ed25519 keypair via ed25519.GenerateKey(rand.Reader), embeds metadata (ID from SHA-256 of the public key, timestamps), and PEM-encodes two JSON blobs. The only realistic failure is the crypto/rand read: the system entropy source (/dev/urandom) is unavailable or exhausted. The json.Marshal steps handle plain structs and cannot realistically fail.
Source
Thrown at client/cmd/signer/rootkey.go:58
createRootKeyCmd.Flags().StringVar(&privKeyFile, "priv-key-file", "", "Path to output private key file")
createRootKeyCmd.Flags().StringVar(&pubKeyFile, "pub-key-file", "", "Path to output public key file")
createRootKeyCmd.Flags().DurationVar(&rootExpiration, "expiration", 0, "Expiration time for the root key (e.g., 720h,)")
if err := createRootKeyCmd.MarkFlagRequired("priv-key-file"); err != nil {
panic(err)
}
if err := createRootKeyCmd.MarkFlagRequired("pub-key-file"); err != nil {
panic(err)
}
if err := createRootKeyCmd.MarkFlagRequired("expiration"); err != nil {
panic(err)
}
}
func handleGenerateRootKey(cmd *cobra.Command, privKeyFile, pubKeyFile string, expiration time.Duration) error {
rk, privPEM, pubPEM, err := reposign.GenerateRootKey(expiration)
if err != nil {
return fmt.Errorf("generate root key: %w", err)
}
// Write private key
if err := os.WriteFile(privKeyFile, privPEM, 0o600); err != nil {
return fmt.Errorf("write private key file (%s): %w", privKeyFile, err)
}
// Write public key
if err := os.WriteFile(pubKeyFile, pubPEM, 0o600); err != nil {
return fmt.Errorf("write public key file (%s): %w", pubKeyFile, err)
}
cmd.Printf("%s\n\n", rk.String())
cmd.Printf("✅ Root key pair generated successfully.\n")
return nil
}
View on GitHub (pinned to 93e97f4bf1)
Solutions
- Check the entropy device: ls -l /dev/urandom and cat a few bytes to confirm it is readable
- Restart the process or host — transient early-boot starvation resolves once the kernel CRNG is ready
- For containers, ensure /dev/urandom is mounted (it is bind-mounted by default in standard runtimes); fix the runtime config if it was removed
- If the error is a marshal message instead of a rand error, treat it as a code bug and inspect local modifications to reposign
Defensive patterns
Strategy: retry
Validate before calling
func entropyAvailable() error {
f, err := os.Open("/dev/urandom")
if err != nil {
return fmt.Errorf("entropy source unavailable: %w", err)
}
defer f.Close()
buf := make([]byte, 8)
if _, err := io.ReadFull(f, buf); err != nil {
return fmt.Errorf("entropy read failed: %w", err)
}
return nil
} Try / catch
var rk *reposign.RootKey
var privPEM, pubPEM []byte
err := retry(3, 100*time.Millisecond, func() error {
rk, privPEM, pubPEM, err = reposign.GenerateRootKey(expiration)
return err
})
if err != nil {
// entropy or environment problem: surface it, do not fabricate a key
return fmt.Errorf("generate root key: %w", err)
} Prevention
- Ensure /dev/urandom exists and is readable in containers and chroots
- Retry a bounded number of times — early-boot entropy starvation is transient
- Never fall back to a weak or fixed key source when rand.Reader fails
When it happens
Trigger: create-root-key running in a restricted container or chroot where /dev/urandom is not mounted; severe entropy starvation during early boot of a VM; otherwise practically unreachable.
Common situations: Minimal Docker images with an empty /dev; sandboxed CI runners restricting device access; embedded hosts early in boot before the CRNG initializes.
Related errors
- failed to parse artifact private key: %w
- failed to create artifact key: %w
- sign artifact: %w
- failed to parse artifact public key: %w
- artifact verification failed: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/46e225a21567cad0.
Report an issue: GitHub.