caddyserver/caddy · error

failed to load system cert pool: %v

Error message

failed to load system cert pool: %v

What it means

The `tls.ca_pool.source.system` pool calls x509.SystemCertPool() to load the OS trust store, and that call failed. On most platforms this only fails when the system certificate store cannot be read or parsed at all.

Source

Thrown at modules/caddytls/capools.go:802

type SystemCAPool struct {
	pool *x509.CertPool
}

// CaddyModule implements caddy.Module.
func (SystemCAPool) CaddyModule() caddy.ModuleInfo {
	return caddy.ModuleInfo{
		ID: "tls.ca_pool.source.system",
		New: func() caddy.Module {
			return new(SystemCAPool)
		},
	}
}

// Provision implements caddy.Provisioner.
func (scp *SystemCAPool) Provision(ctx caddy.Context) error {
	pool, err := x509.SystemCertPool()
	if err != nil {
		return fmt.Errorf("failed to load system cert pool: %v", err)
	}
	scp.pool = pool
	return nil
}

func (scp *SystemCAPool) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
	d.Next() // consume module name
	if d.CountRemainingArgs() > 0 {
		return d.ArgErr()
	}
	if d.NextBlock(0) {
		return d.Err("system trust pool does not support any configuration")
	}
	return nil
}

// CertPool implements CA.
func (scp SystemCAPool) CertPool() *x509.CertPool {

View on GitHub (pinned to 50e54ee279)

Solutions

  1. In containers, install the CA certificates package (e.g. `apt-get install -ca-certificates` on Debian, `apk add ca-certificates` on Alpine) and rebuild.
  2. On hosts, rebuild the trust store (Debian: `update-ca-certificates --fresh`; RHEL: `update-ca-trust`).
  3. If the system store genuinely cannot be fixed, use an explicit `file` or `inline` trust pool instead of `system`.

Example fix

# before: Dockerfile
FROM scratch
COPY caddy /caddy

# after: Dockerfile
FROM alpine:3.20
RUN apk add --no-cache ca-certificates
COPY caddy /usr/bin/caddy
Defensive patterns

Strategy: validation

Validate before calling

// container/CI check: system store readable and non-empty (unix)
import (
	"crypto/x509"
	"os"
)

func systemStoreOK() error {
	if _, err := x509.SystemCertPool(); err != nil {
		return fmt.Errorf("system cert pool unavailable: %w", err)
	}
	if _, err := os.Stat("/etc/ssl/certs"); os.IsNotExist(err) {
		return errors.New("no /etc/ssl/certs; install ca-certificates")
	}
	return nil
}

Prevention

When it happens

Trigger: The OS trust store is missing, empty, unreadable, or corrupt — e.g. a minimal container with no ca-certificates package, a broken /etc/ssl/certs, or unusual permissions on the trust store files.

Common situations: Docker/Distroless/scratch images without ca-certificates installed; chroots with incomplete /etc/ssl; broken symlinks in the cert directory after a partial update.

Related errors


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