caddyserver/caddy · error
expanding EAB MAC key (redacted): %v
Error message
expanding EAB MAC key (redacted): %v
What it means
Returned by ACMEIssuer.Provision (modules/caddytls/acmeissuer.go:173) when the EAB HMAC key (acme_eab / "mac_key") contains a placeholder that fails to expand. The message deliberately omits the value ('(redacted)') because it is a secret; only expansion errors, not content, are reported. Provisioning aborts before the issuer is usable.
Source
Thrown at modules/caddytls/acmeissuer.go:173
if err != nil {
return fmt.Errorf("expanding TestCA endpoint '%s': %v", iss.TestCA, err)
}
iss.TestCA = testca
}
// expand EAB credentials, if non-empty
if iss.ExternalAccount != nil {
if iss.ExternalAccount.KeyID != "" {
keyID, err := repl.ReplaceOrErr(iss.ExternalAccount.KeyID, true, true)
if err != nil {
return fmt.Errorf("expanding EAB key ID '%s': %v", iss.ExternalAccount.KeyID, err)
}
iss.ExternalAccount.KeyID = keyID
}
if iss.ExternalAccount.MACKey != "" {
macKey, err := repl.ReplaceOrErr(iss.ExternalAccount.MACKey, true, true)
if err != nil {
return fmt.Errorf("expanding EAB MAC key (redacted): %v", err)
}
iss.ExternalAccount.MACKey = macKey
}
}
// expand account key, if non-empty
if iss.AccountKey != "" {
accountKey, err := repl.ReplaceOrErr(iss.AccountKey, true, true)
if err != nil {
return fmt.Errorf("expanding account key PEM '%s': %v", iss.AccountKey, err)
}
iss.AccountKey = accountKey
}
// expand DNS override domain, if non-empty
if iss.Challenges != nil && iss.Challenges.DNS != nil && iss.Challenges.DNS.OverrideDomain != "" {
overrideDomain, err := repl.ReplaceOrErr(iss.Challenges.DNS.OverrideDomain, true, true)
if err != nil {View on GitHub (pinned to 50e54ee279)
Solutions
- Define EAB_MAC_KEY in the service environment (EnvironmentFile=/etc/caddy/acme.env with tight permissions) and reload Caddy
- Confirm the name matches exactly what the config references
- Ensure the placeholder is exactly {env.EAB_MAC_KEY} with no stray characters
- If EAB is unnecessary for your CA, delete the eab block
Example fix
# /etc/caddy/acme.env (chmod 600)
EAB_KEY_ID=kid-123
EAB_MAC_KEY=base64urlkey
# Caddyfile
example.com {
tls {
issuer acme {
eab {
key_id {env.EAB_KEY_ID}
mac_key {env.EAB_MAC_KEY}
}
}
}
}
# systemd unit
[Service]
EnvironmentFile=/etc/caddy/acme.env Defensive patterns
Strategy: validation
Validate before calling
if strings.Contains(cfgText, "{env.EAB_MAC_KEY}") && os.Getenv("EAB_MAC_KEY") == "" {
return errors.New("EAB_MAC_KEY referenced but not set; issuer provisioning will fail")
} Try / catch
if err := issuer.Provision(ctx); err != nil {
if strings.Contains(err.Error(), "expanding EAB MAC key") {
// value is redacted in logs; only the env var / syntax needs fixing
}
return err
} Prevention
- Never log or echo the MAC key; Caddy already redacts it - keep that invariant in your tooling
- Use secret managers that export to the process environment (systemd EnvironmentFile, Docker secrets wrappers)
- Test the secret's presence in the exact runtime context (unit vs shell) - shells and units differ
When it happens
Trigger: eab { mac_key {env.EAB_MAC_KEY} } configured while EAB_MAC_KEY is unset in the Caddy process, or the placeholder syntax is invalid (unbalanced braces, unknown prefix, leading/trailing whitespace).
Common situations: Secret injected via Docker secrets or Vault but exposed under a different variable name; CI has the var but the production unit does not; quoting issues in systemd Environment= lines; copy-paste from docs leaving a placeholder the deployment never defines.
Related errors
- expanding EAB key ID '%s': %v
- expanding email address '%s': %v
- expanding CA endpoint '%s': %v
- expanding TestCA endpoint '%s': %v
- expanding account key PEM '%s': %v
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/3300334d0bbf88af.
Report an issue: GitHub.