{"record":{"id":"b6278d3540ed3ac2","repo":"caddyserver/caddy","slug":"loading-trusted-root-ca-s-pem-file-s-v","errorCode":null,"errorMessage":"loading trusted root CA's PEM file: %s: %v","messagePattern":"loading trusted root CA's PEM file: (.+?): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddytls/acmeissuer.go","lineNumber":237,"sourceCode":"\t\t\tDNSManager: certmagic.DNSManager{\n\t\t\t\tDNSProvider:        prov,\n\t\t\t\tTTL:                time.Duration(iss.Challenges.DNS.TTL),\n\t\t\t\tPropagationDelay:   time.Duration(iss.Challenges.DNS.PropagationDelay),\n\t\t\t\tPropagationTimeout: time.Duration(iss.Challenges.DNS.PropagationTimeout),\n\t\t\t\tResolvers:          iss.Challenges.DNS.Resolvers,\n\t\t\t\tOverrideDomain:     iss.Challenges.DNS.OverrideDomain,\n\t\t\t\tLogger:             iss.logger.Named(\"dns_manager\"),\n\t\t\t},\n\t\t}\n\t}\n\n\t// add any custom CAs to trust store\n\tif len(iss.TrustedRootsPEMFiles) > 0 {\n\t\tiss.rootPool = x509.NewCertPool()\n\t\tfor _, pemFile := range iss.TrustedRootsPEMFiles {\n\t\t\tpemData, err := os.ReadFile(pemFile)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"loading trusted root CA's PEM file: %s: %v\", pemFile, err)\n\t\t\t}\n\t\t\tif !iss.rootPool.AppendCertsFromPEM(pemData) {\n\t\t\t\treturn fmt.Errorf(\"unable to add %s to trust pool: %v\", pemFile, err)\n\t\t\t}\n\t\t}\n\t}\n\n\tvar err error\n\tiss.template, err = iss.makeIssuerTemplate(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc (iss *ACMEIssuer) makeIssuerTemplate(ctx caddy.Context) (certmagic.ACMEIssuer, error) {\n\ttemplate := certmagic.ACMEIssuer{","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddytls/acmeissuer.go#L219-L255","documentation":"Returned by ACMEIssuer.Provision (modules/caddytls/acmeissuer.go:237) when one of the trusted root CA PEM files (tls_trust_pool / TrustedRootsPEMFiles) cannot be read with os.ReadFile. The wrapped error is the OS error: file not found, permission denied, or (on Windows) sharing violations. Issuer provisioning aborts, so the config fails to load.","triggerScenarios":"Configuring an ACME issuer with a custom trust pool pointing at a path that does not exist in the container/host, a file the service user cannot read, or a path with a typo; also paths valid on the author's machine but absent in the deployment image.","commonSituations":"Custom trust pools for private ACME CAs (step-ca, smallstep) where the root was never mounted into the container; file owned by root with mode 600 while Caddy runs as another user; paths written for bare-metal used in a container where the file lives at a different mount point.","solutions":["Verify the path and spelling, then check readability as the service user: sudo -u caddy head -1 /path/to/root.pem","Fix permissions/ownership: chown caddy:caddy file && chmod 644 file","In containers, mount the root CA: - ./ca/root-ca.crt:/etc/caddy/roots/root-ca.crt:ro and reference that path","Use an absolute path; avoid ~ or shell variables that Caddy does not expand"],"exampleFix":"# before\n{\n  acme_ca https://acme.internal/dir\n  tls_trust_pool file\n}\n\n# after\n{\n  acme_ca https://acme.internal/dir\n}\n(defined in a site's issuer with the file present)\n example.com {\n   tls {\n     issuer acme https://acme.internal/dir {\n       trusted_roots /etc/caddy/roots/root-ca.pem\n     }\n   }\n }\n# docker: - ./ca/root-ca.crt:/etc/caddy/roots/root-ca.pem:ro","handlingStrategy":"validation","validationCode":"# preflight every trusted-roots path referenced by the config\nfor f in $(grep -oE 'trusted_roots [^ ]+' Caddyfile | cut -d' ' -f2); do\n  test -r \"$f\" || { echo \"missing/unreadable: $f\"; exit 1; }\ndone","typeGuard":null,"tryCatchPattern":"if err := issuer.Provision(ctx); err != nil {\n    if strings.Contains(err.Error(), \"loading trusted root CA's PEM file\") {\n        // the message includes the failing path: fix it, mount it, or fix permissions\n    }\n    return err\n}","preventionTips":["Mount CA bundles into containers at fixed absolute paths and reference those","Check file readability as the service user (sudo -u caddy test -r) in deploy scripts","Keep the set of trusted-root files under configuration management so drift is visible"],"tags":["tls","acme","trust-store","filesystem","containers","permissions"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}