caddyserver/caddy · critical

provisioning CA '%s': %v

Error message

provisioning CA '%s': %v

What it means

Returned by PKI.Provision (modules/caddypki/pki.go:63) when provisioning a CA explicitly declared in the pki app configuration fails. It wraps whatever CA.Provision produced: unreadable or malformed root/intermediate files, keystore errors, key/cert mismatches, or bad names/durations in the CA config. This is a startup-time failure: Caddy refuses to start with the given config.

Source

Thrown at modules/caddypki/pki.go:63

}

// CaddyModule returns the Caddy module information.
func (PKI) CaddyModule() caddy.ModuleInfo {
	return caddy.ModuleInfo{
		ID:  "pki",
		New: func() caddy.Module { return new(PKI) },
	}
}

// Provision sets up the configuration for the PKI app.
func (p *PKI) Provision(ctx caddy.Context) error {
	p.ctx = ctx
	p.log = ctx.Logger()

	for caID, ca := range p.CAs {
		err := ca.Provision(ctx, caID, p.log)
		if err != nil {
			return fmt.Errorf("provisioning CA '%s': %v", caID, err)
		}
	}

	// if this app is initialized at all, ensure there's at
	// least a default CA that can be used: the standard CA
	// which is used implicitly for signing local-use certs
	if len(p.CAs) == 0 {
		err := p.ProvisionDefaultCA(ctx)
		if err != nil {
			return fmt.Errorf("provisioning CA '%s': %v", DefaultCAID, err)
		}
	}

	return nil
}

// ProvisionDefaultCA sets up the default CA.
func (p *PKI) ProvisionDefaultCA(ctx caddy.Context) error {

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Read the wrapped error - it names the concrete failure (file read, PEM decode, key mismatch, etc.) and fix that first
  2. Verify every path you configured actually exists and is readable by the Caddy process: sudo -u caddy cat <path>
  3. Validate the PEM pair: openssl x509 -in cert.pem -noout && openssl pkey -in key.pem -noout && match the public keys
  4. Simplify: temporarily remove the root/intermediate blocks so Caddy generates its own CA, confirming the rest of the config is sound, then re-add the custom files

Example fix

// before
{
  "apps": {
    "pki": {
      "certificate_authorities": {
        "local": {
          "root": { "certificate": "/wrong/path/root.crt", "private_key": "/wrong/path/root.key" }
        }
      }
    }
  }
}

// after: correct, process-readable paths
{
  "apps": {
    "pki": {
      "certificate_authorities": {
        "local": {
          "root": { "certificate": "/etc/caddy/pki/root.crt", "private_key": "/etc/caddy/pki/root.key" }
        }
      }
    }
  }
}
Defensive patterns

Strategy: validation

Validate before calling

// in CI: adapt and validate before deploy so provisioning errors never reach production
caddy adapt --config Caddyfile --adapter caddyfile > caddy.json
caddy validate --config caddy.json --adapter json
# additionally check referenced files exist:
#   for f in /etc/caddy/pki/root.crt /etc/caddy/pki/root.key; do test -r $f || exit 1; done

Try / catch

// if embedding Caddy programmatically
err = caddy.Run(cfg)
if err != nil {
    if strings.Contains(err.Error(), "provisioning CA") {
        // config/environment problem: inspect wrapped cause, fix CA files/paths
    }
    return err
}

Prevention

When it happens

Trigger: Declaring pki { ca <id> { ... } } with root/intermediate blocks whose cert_file/key_file paths are wrong, whose PEM content is invalid, or whose key does not match the certificate; a duplicate or reserved CA ID; a custom storage-backed keystore that cannot be opened.

Common situations: Path typos or container-relative paths that differ inside the container; files mounted read-only at the wrong location; PEM files with Windows line endings or trailing garbage; using a symlink that resolves outside the allowed directory; YAML/JSON indentation mistakes that put CA options under the wrong block.

Related errors


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