caddyserver/caddy · critical

generating root: %v

Error message

generating root: %v

What it means

When no root exists yet, Caddy generates one via CA.genRoot (generateRoot creates an ECDSA P-256 root, 24h*3650 by default). Any failure in key generation, self-signing, or the replacer is wrapped as 'generating root'. This path runs only on first use of a CA id, so failure usually indicates an entropy, crypto, or pre-processing problem rather than bad input data.

Source

Thrown at modules/caddypki/ca.go:294

func (ca CA) loadOrGenRoot() (rootCert *x509.Certificate, rootKey crypto.Signer, err error) {
	if ca.Root != nil {
		rootChain, rootSigner, err := ca.Root.Load()
		if err != nil {
			return nil, nil, err
		}
		return rootChain[0], rootSigner, nil
	}
	rootCertPEM, err := ca.storage.Load(ca.ctx, ca.storageKeyRootCert())
	if err != nil {
		if !errors.Is(err, fs.ErrNotExist) {
			return nil, nil, fmt.Errorf("loading root cert: %v", err)
		}

		// TODO: should we require that all or none of the assets are required before overwriting anything?
		rootCert, rootKey, err = ca.genRoot()
		if err != nil {
			return nil, nil, fmt.Errorf("generating root: %v", err)
		}
	}

	if rootCert == nil {
		rootCert, err = pemDecodeCertificate(rootCertPEM)
		if err != nil {
			return nil, nil, fmt.Errorf("parsing root certificate PEM: %v", err)
		}
	}
	if rootKey == nil {
		rootKeyPEM, err := ca.storage.Load(ca.ctx, ca.storageKeyRootKey())
		if err != nil {
			return nil, nil, fmt.Errorf("loading root key: %v", err)
		}
		rootKey, err = certmagic.PEMDecodePrivateKey(rootKeyPEM)
		if err != nil {
			return nil, nil, fmt.Errorf("decoding root key: %v", err)
		}

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Retry provisioning after ensuring entropy is available (check /proc/sys/kernel/random/entropy_avail, getrandom health); on VMs/containers this often resolves itself after the host is up.
  2. Simplify root_common_name to plain ASCII and retry.
  3. Update Caddy to a current version to pick up crypto-layer fixes.
  4. If it persists, capture the wrapped inner error from logs — it names the exact failing crypto call.
Defensive patterns

Strategy: retry

Validate before calling

// Pre-provisioning check on hosts you control
b := make([]byte, 32)
if _, err := rand.Read(b); err != nil { log.Fatal("RNG unavailable; fix entropy first") }

Try / catch

// first-boot generation can fail transiently on entropy; retry provisioning once
if err := provisionCA(); err != nil && strings.Contains(err.Error(), "generating root") {
    time.Sleep(time.Second)
    err = provisionCA()
}
if err != nil { return err }

Prevention

When it happens

Trigger: First startup for a CA id (storage returns fs.ErrNotExist for the root cert) and generateRoot fails: RNG exhaustion on the host, an invalid RootCommonName after replacement producing an unencodable subject, or an OS crypto subsystem failure while generating the ECDSA key or self-signing.

Common situations: Containers with depleted/absent entropy during rapid provisioning; exotic architectures where crypto/rand or ecdsa fails; a template in root_common_name that expands to invalid ASN.1 characters.

Related errors


AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15). Data as JSON: /api/errors/b708f1431863fb4a. Report an issue: GitHub.