caddyserver/caddy · error
getting server identity credentials
Error message
getting server identity credentials: %v
What it means
When the http config loader is configured with tls.use_server_identity, makeClient asks the Caddy context for the server's own identity certificate (the local PKI-installed leaf, via IdentityCredentials) to use as the client certificate. Failure to obtain it (local CA not provisioned, identity cert missing or unreadable) is wrapped with this message.
Solutions
- Verify Caddy's storage/data directory is writable and persistent (same volume across restarts).
- Run 'caddy trust' / start Caddy once so the local PKI and identity cert get provisioned.
- Check file permissions on the storage directory for the Caddy user.
- If mTLS with a custom CA is intended instead, use client_certificate_file/client_certificate_key_file rather than use_server_identity.
Example fix
# before
http https://cfg.internal/config.json {
tls {
use_server_identity
}
}
# after (mTLS with explicit client cert when identity creds are unavailable)
http https://cfg.internal/config.json {
tls {
client_certificate_file /etc/caddy/client.crt
client_certificate_key_file /etc/caddy/client.key
root_ca /etc/caddy/ca.pem
}
} Defensive patterns
Strategy: validation
Validate before calling
# confirm the local PKI identity exists and is readable
ls -l "${XDG_DATA_HOME:-$HOME/.local/share}/caddy/pki/authorities/local" 2>/dev/null || echo 'no local PKI: run caddy trust / start once' Prevention
- Persist Caddy's storage directory across restarts/containers.
- Run 'caddy trust' once on fresh hosts before enabling use_server_identity.
- Prefer explicit client cert files when the local PKI is unavailable.
When it happens
Trigger: 'use_server_identity' set on the http loader while ctx.IdentityCredentials fails — local PKI not yet provisioned on a fresh host, storage directory missing/unreadable, or the identity certificate absent (e.g. non-persistent container volume).
Common situations: First run with a custom or read-only XDG_DATA_HOME; containers missing the persisted storage volume so identity certs never exist; permission changes on the data directory after initial provisioning.
Related errors
- failed reading ca cert
- problem calling http loader url
- provisioning default internal automation policy
- acme challenge is not supported
- acme_dns specified without DNS provider config, but no…
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/c7ab7949813f2ee5.
Report an issue: GitHub.
Appendix: source
Thrown at caddyconfig/httploader.go:182
}
}
return resp, err
}
func (hl HTTPLoader) makeClient(ctx caddy.Context) (*http.Client, error) {
client := &http.Client{
Timeout: time.Duration(hl.Timeout),
}
if hl.TLS != nil {
var tlsConfig *tls.Config
// client authentication
if hl.TLS.UseServerIdentity {
certs, err := ctx.IdentityCredentials(ctx.Logger())
if err != nil {
return nil, fmt.Errorf("getting server identity credentials: %v", err)
}
// See https://github.com/securego/gosec/issues/1054#issuecomment-2072235199
//nolint:gosec
tlsConfig = &tls.Config{Certificates: certs}
} else if hl.TLS.ClientCertificateFile != "" && hl.TLS.ClientCertificateKeyFile != "" {
cert, err := tls.LoadX509KeyPair(hl.TLS.ClientCertificateFile, hl.TLS.ClientCertificateKeyFile)
if err != nil {
return nil, err
}
//nolint:gosec
tlsConfig = &tls.Config{Certificates: []tls.Certificate{cert}}
}
// trusted server certs
if len(hl.TLS.RootCAPEMFiles) > 0 {
rootPool := x509.NewCertPool()
for _, pemFile := range hl.TLS.RootCAPEMFiles {
pemData, err := os.ReadFile(pemFile)View on GitHub (pinned to 50e54ee279)