Billionmail/BillionMail · critical
Failed to generate user private key: {}
Error message
Failed to generate user private key: {} What it means
GetMyUser loads the persisted ACME account ECDSA key, and if none exists generates a new P-256 key with ecdsa.GenerateKey. If crypto/rand fails, the error is wrapped via public.LangCtx into this localized message and returned, aborting the SSL flow (ApplySSLWithExistingServer) before any ACME client is created.
Source
Thrown at core/internal/service/acme/acme.go:77
if public.FileExists(accountKeyPath) {
keyBytes, readErr := public.ReadFile(accountKeyPath)
if readErr == nil {
block, _ := pem.Decode([]byte(keyBytes))
if block != nil {
parsedKey, parseErr := x509.ParseECPrivateKey(block.Bytes)
if parseErr == nil {
privateKey = parsedKey
}
}
}
}
if privateKey == nil {
// Generate new private key if none exists
privateKey, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return nil, errors.New(public.LangCtx(ctx, "Failed to generate user private key: {}", err.Error()))
}
// Persist the key for future use
keyBytes, marshalErr := x509.MarshalECPrivateKey(privateKey)
if marshalErr == nil {
pemBlock := &pem.Block{
Type: "EC PRIVATE KEY",
Bytes: keyBytes,
}
pemBytes := pem.EncodeToMemory(pemBlock)
dir := filepath.Dir(accountKeyPath)
if !public.FileExists(dir) {
os.MkdirAll(dir, 0750)
}
public.WriteFile(accountKeyPath, string(pemBytes))
}
}View on GitHub (pinned to fc36c76c05)
Solutions
- Check the container's seccomp/apparmor profile allows getrandom(2); loosen the profile or use a default Docker profile.
- Verify /dev/urandom exists and is readable inside the container/host.
- Inspect core/data/acme/account.key — if it exists but is corrupt, delete it so a fresh key is generated and persisted.
- Upgrade the kernel/glibc on minimal hosts where getrandom is broken.
Example fix
// before
privateKey, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return nil, errors.New(public.LangCtx(ctx, "Failed to generate user private key: {}", err.Error()))
}
// after
privateKey, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return nil, fmt.Errorf("generate ACME account key (check crypto/rand availability/seccomp): %w", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
// preflight before ApplySSL
f, err := os.OpenFile("/dev/urandom", os.O_RDONLY, 0)
if err != nil { return fmt.Errorf("entropy source unavailable: %w", err) }
f.Close() Type guard
func hasUsableAccountKey(pemBytes []byte) bool {
block, _ := pem.Decode(pemBytes)
if block == nil { return false }
_, err := x509.ParseECPrivateKey(block.Bytes)
return err == nil
} Try / catch
u, err := acme.GetMyUser(ctx, email)
if err != nil {
if strings.Contains(err.Error(), "Failed to generate user private key") {
return fmt.Errorf("crypto/rand unavailable — check container seccomp/dev/urandom: %w", err)
}
return err
} Prevention
- Use default (unrestricted) seccomp profiles in containers
- Delete corrupt core/data/acme/account.key files instead of silently ignoring parse errors
- Persist generated keys with error handling (currently marshalErr/write errors are swallowed)
When it happens
Trigger: ecdsa.GenerateKey returning an error — practically only when the OS cryptographic entropy source (/dev/urandom, getrandom) fails: sandboxed/restricted containers, seccomp filters blocking getrandom, or a heavily degraded kernel.
Common situations: Container with restricted seccomp profile blocking getrandom(2); unusual minimal distros lacking proper /dev/urandom; this message also appears when the account.key file could not be read/parsed (silently ignored) and generation then runs — check for a corrupted PEM file first.
Related errors
- DNS automated resolution failed: SecretId or SecretKey is em
- DNS provider initialization failed: {}
- DNS verification setup failed: {}
- DNS automated resolution failed: APIKey or SecretKey is empt
- DNS automated resolution failed: APIKey or Email is empty in
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/b12265554d979e75.
Report an issue: GitHub.