caddyserver/caddy · error
cannot enable remote admin without a certificate cache; conf
Error message
cannot enable remote admin without a certificate cache; configure identity management to initialize a certificate cache
What it means
Enabling admin.remote requires server identity management because the remote endpoint's TLS certificate comes from the identity certmagic cache (identityCertCache). If that package-level cache is nil — i.e. admin.identity did not run and configure a certificate cache — remote admin cannot be set up and startup fails with this error.
Source
Thrown at admin.go:561
}
// create client certificate pool for TLS mutual auth, and extract public keys
// so that we can enforce access controls at the application layer
clientCertPool := x509.NewCertPool()
for i, accessControl := range cfg.Admin.Remote.AccessControl {
for j, certBase64 := range accessControl.PublicKeys {
cert, err := decodeBase64DERCert(certBase64)
if err != nil {
return fmt.Errorf("access control %d public key %d: parsing base64 certificate DER: %v", i, j, err)
}
accessControl.publicKeys = append(accessControl.publicKeys, cert.PublicKey)
clientCertPool.AddCert(cert)
}
}
// create TLS config that will enforce mutual authentication
if identityCertCache == nil {
return fmt.Errorf("cannot enable remote admin without a certificate cache; configure identity management to initialize a certificate cache")
}
cmCfg := cfg.Admin.Identity.certmagicConfig(remoteLogger, false)
tlsConfig := cmCfg.TLSConfig()
tlsConfig.NextProtos = nil // this server does not solve ACME challenges
tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
tlsConfig.ClientCAs = clientCertPool
// convert logger to stdlib so it can be used by HTTP server
serverLogger, err := zap.NewStdLogAt(remoteLogger, zap.DebugLevel)
if err != nil {
return err
}
serverMu.Lock()
// create secure HTTP server
remoteAdminServer = &http.Server{
Addr: addr.String(), // for logging purposes only
Handler: handler,View on GitHub (pinned to 50e54ee279)
Solutions
- Add an admin.identity section to the same config (at minimum identifiers, letting the default ACME or internal issuer manage a certificate)
- Consider the 'internal' issuer for identity to avoid external ACME dependencies: {"module": "internal"}
- Verify the whole admin config with caddy validate before restart
- If you don't need remote admin, remove the admin.remote block
Example fix
// before
"admin": {
"remote": { "listen": ":2021", "access_control": [...] }
}
// after
"admin": {
"identity": {
"identifiers": ["admin.example.com"],
"issuers": [{"module": "internal"}]
},
"remote": { "listen": ":2021", "access_control": [...] }
} Defensive patterns
Strategy: validation
Validate before calling
func remoteAdminConfigComplete(cfg *Config) error {
if cfg.Admin != nil && cfg.Admin.Remote != nil {
if cfg.Admin.Identity == nil || len(cfg.Admin.Identity.Identifiers) == 0 {
return errors.New("admin.remote requires admin.identity with identifiers")
}
}
return nil
} Prevention
- Treat admin.remote and admin.identity as one unit in config templates
- Validate configs in CI before deploy
- Use the internal issuer for identity in closed environments
When it happens
Trigger: JSON config with admin.remote configured but no admin.identity section (or identity provisioning skipped/failed silently in this path); ordering issues where remote setup runs before identity setup in the same config load.
Common situations: Experimenting with remote admin and adding only the remote block; copying partial examples from docs; identity issuers left empty in a config that still requests remote access.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- loading identity issuer modules: %s
- access control %d public key %d: parsing base64 certificate
- no identifiers configured
- no metrics registry found
- no server identity configured
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/0a044ded1e70210d.
Report an issue: GitHub.