{"record":{"id":"fc3df43e533ffeec","repo":"caddyserver/caddy","slug":"expanding-eab-key-id-s-v","errorCode":null,"errorMessage":"expanding EAB key ID '%s': %v","messagePattern":"expanding EAB key ID '(.+?)': (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddytls/acmeissuer.go","lineNumber":166,"sourceCode":"\t\t}\n\t\tiss.CA = ca\n\t}\n\n\t// expand TestCA endpoint, if non-empty\n\tif iss.TestCA != \"\" {\n\t\ttestca, err := repl.ReplaceOrErr(iss.TestCA, true, true)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"expanding TestCA endpoint '%s': %v\", iss.TestCA, err)\n\t\t}\n\t\tiss.TestCA = testca\n\t}\n\n\t// expand EAB credentials, if non-empty\n\tif iss.ExternalAccount != nil {\n\t\tif iss.ExternalAccount.KeyID != \"\" {\n\t\t\tkeyID, err := repl.ReplaceOrErr(iss.ExternalAccount.KeyID, true, true)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"expanding EAB key ID '%s': %v\", iss.ExternalAccount.KeyID, err)\n\t\t\t}\n\t\t\tiss.ExternalAccount.KeyID = keyID\n\t\t}\n\t\tif iss.ExternalAccount.MACKey != \"\" {\n\t\t\tmacKey, err := repl.ReplaceOrErr(iss.ExternalAccount.MACKey, true, true)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"expanding EAB MAC key (redacted): %v\", err)\n\t\t\t}\n\t\t\tiss.ExternalAccount.MACKey = macKey\n\t\t}\n\t}\n\n\t// expand account key, if non-empty\n\tif iss.AccountKey != \"\" {\n\t\taccountKey, err := repl.ReplaceOrErr(iss.AccountKey, true, true)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"expanding account key PEM '%s': %v\", iss.AccountKey, err)\n\t\t}","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddytls/acmeissuer.go#L148-L184","documentation":"Returned by ACMEIssuer.Provision (modules/caddytls/acmeissuer.go:166) when an External Account Binding key ID (eab key_id / JSON \"key_id\") contains a placeholder that fails to expand. EAB is required by some ACME CAs (ZeroSSL, Google Trust Services, private CAs); a broken placeholder in the key ID prevents issuer setup entirely.","triggerScenarios":"Configuring tls { issuer acme { eab { key_id {env.EAB_KEY_ID} mac_key ... } } } where EAB_KEY_ID is not present in Caddy's environment, or the placeholder expression is malformed.","commonSituations":"Credentials stored in .env files that the systemd unit or container does not load; rotating EAB credentials in a secret manager but not updating the env var; copying configs to a new host without the secrets; brace typos.","solutions":["Set EAB_KEY_ID in the actual service environment (systemd Environment=, EnvironmentFile=, or container env) and restart/reload Caddy","Verify with: sudo systemctl show caddy -p Environment or printenv inside the container","Fix the placeholder to exactly {env.EAB_KEY_ID}; no spaces, balanced braces","If EAB is not required by your CA, remove the eab block entirely"],"exampleFix":"# before\n example.com {\n   tls {\n     issuer acme {\n       eab {\n         key_id {env.EAB_KEYID}   # actual var is EAB_KEY_ID\n         mac_key {env.EAB_MAC_KEY}\n       }\n     }\n   }\n }\n\n# after\n example.com {\n   tls {\n     issuer acme {\n       eab {\n         key_id {env.EAB_KEY_ID}\n         mac_key {env.EAB_MAC_KEY}\n       }\n     }\n   }\n }\n# systemd: EnvironmentFile=/etc/caddy/acme.env (defines both vars)","handlingStrategy":"validation","validationCode":"// verify all EAB env vars exist before deploy\nfor _, k := range []string{\"EAB_KEY_ID\", \"EAB_MAC_KEY\"} {\n    if os.Getenv(k) == \"\" {\n        return fmt.Errorf(\"%s must be set for EAB-enabled ACME issuance\", k)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := issuer.Provision(ctx); err != nil {\n    if strings.Contains(err.Error(), \"expanding EAB key ID\") {\n        // EAB_KEY_ID missing: add to EnvironmentFile, then reload\n    }\n    return err\n}","preventionTips":["Store EAB credentials in a permission-600 EnvironmentFile referenced by the unit","Secret-check in CI: fail the pipeline when {env.*} references lack values in the deployment environment","Rotate EAB creds by updating the file and reloading Caddy, never by editing inline literals"],"tags":["tls","acme","eab","placeholders","secrets","environment"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}