caddyserver/caddy · error

getting server identity credentials: %v

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.

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)

Solutions

  1. Verify Caddy's storage/data directory is writable and persistent (same volume across restarts).
  2. Run 'caddy trust' / start Caddy once so the local PKI and identity cert get provisioned.
  3. Check file permissions on the storage directory for the Caddy user.
  4. 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

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


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