ACME Best Practices¶
Security¶
Always Require External Account Binding¶
Enable Require EAB on all production ACME servers. EAB ensures that only pre-authorized clients can register accounts, preventing unauthorized certificate issuance.
Without EAB, any client that can reach your ACME endpoint can potentially register an account. While domain bindings still control what certificates can be issued, EAB provides an essential first line of defence.
Use Minimal Domain Bindings¶
Apply the principle of least privilege to domain bindings:
- Grant exact domain bindings whenever possible
- Enable subdomain permissions only when needed
- Enable wildcard permissions only when the system genuinely requires wildcard certificates
Avoid: A single account with wildcard permissions for all company domains.
Prefer: Dedicated accounts with specific bindings for each system.
Protect EAB Credentials¶
EAB credentials are effectively API keys. Handle them with the same care:
| Do | Don't |
|---|---|
| Transmit via encrypted channels | Send via unencrypted email |
| Store in a secrets manager | Store in source control |
| Delete after configuration | Leave in plaintext files |
| Regenerate if potentially exposed | Reuse credentials across systems |
Secure Key Storage on Clients¶
ACME clients generate and store private keys locally. Ensure:
- Private keys are stored with restrictive file permissions (e.g.,
600or400on Linux) - The service account running the ACME client has minimal privileges
- Key storage directories are excluded from backups that may be less secure than the host
Monitor for Unauthorized Activity¶
Review the audit log regularly for unexpected activity:
- Account registrations from unknown sources
- Orders for domains you wouldn't expect
- Failed authorization attempts (may indicate misconfiguration or probing)
Operational Best Practices¶
Use Short Validity Periods¶
Configure short default and maximum validity periods:
| Environment | Recommended Default | Recommended Maximum |
|---|---|---|
| Production | 90 days | 365 days |
| Development | 30 days | 90 days |
| High-security | 30 days | 90 days |
Short validity periods:
- Reduce the window of exposure if a key is compromised
- Force automation — manual certificate management is unsustainable
- Align with industry best practices (CA/Browser Forum recommends max 398 days for public TLS)
Automate Renewal¶
Configure ACME clients to renew certificates automatically, well before expiry:
| Client | Renewal Configuration |
|---|---|
| Certbot | Runs via systemd timer or cron; renews at 30 days before expiry by default |
| acme.sh | Cron job; renews at 60 days before expiry by default |
| Caddy | Automatic; renews at 1/3 of lifetime remaining |
| Traefik | Automatic; renews at 30 days before expiry |
Use Separate Servers for Environments¶
Create separate ACME server configurations for:
- Production — Stricter policies, longer maximum validity, production intermediate
- Staging/Development — Shorter validity, separate intermediate, more permissive for testing
This prevents test systems from accidentally obtaining production certificates and keeps audit logs clean.
Plan for PKI Rotation¶
When rotating intermediate certificates:
- Update the ACME server configuration to use the new intermediate
- Ensure clients trust both old and new intermediates during transition
- Allow time for all certificates to renew with the new chain
- Remove trust for the old intermediate only after all certificates have rotated
Client Configuration¶
Prefer Strong Cryptography¶
When configuring ACME clients, request strong cryptographic parameters:
| Parameter | Recommended | Avoid |
|---|---|---|
| Key algorithm | ECDSA P-384 | RSA 2048, ECDSA P-256 (for new deployments) |
| RSA key size | 4096 bits (if RSA required) | 2048 bits |
| Digest | SHA-384 or SHA-512 | SHA-1 |
Most ACME clients default to reasonable algorithms, but verify your configuration.
Handle Renewal Failures¶
Configure alerting for renewal failures. Most ACME clients provide hooks for error handling:
Certbot:
certbot renew --deploy-hook /path/to/success.sh --post-hook /path/to/alert-on-failure.sh
acme.sh:
acme.sh --issue -d example.com --reloadcmd "systemctl reload nginx" \
--notify-hook sendmail
Test Before Production¶
Before deploying ACME to production:
- Create a test ACME server configuration
- Test the full flow: account registration, certificate issuance, renewal
- Verify the certificate chain is trusted by your systems
- Test failure scenarios: expired credentials, unauthorized domains, network failures
Comparison: When to Use ACME vs Courier¶
| Scenario | Recommended Approach |
|---|---|
| Web server with native ACME support (Caddy, Traefik) | ACME |
| Kubernetes with cert-manager | ACME |
| Legacy application requiring scripts for certificate installation | Courier |
| Network-restricted systems (no internet access) | Courier via Bridge |
| Systems requiring platform-side key generation | Courier |
| Environments with existing ACME automation | ACME |
| Need for detailed lifecycle hooks (pre/post scripts) | Courier |
You can use both ACME and Couriers within the same organization for different systems.
Troubleshooting Common Issues¶
Certificate Not Trusted¶
Symptom: Certificate is issued but clients report "certificate not trusted".
Causes: - Client system does not trust the root CA - Intermediate certificate is not included in the chain - Certificate was issued by a different intermediate than expected
Resolution: - Install the root CA certificate in the client's trust store - Verify the ACME server is configured with the correct intermediate - Check the full chain returned by the ACME server
Account Registration Fails¶
Symptom: Client reports "unauthorized" or "account does not exist".
Causes: - EAB credentials are incorrect or already used - Server requires EAB but client did not provide it - Account was deactivated
Resolution: - Verify EAB credentials match exactly (case-sensitive) - Regenerate credentials if they may have been used or compromised - Check account status in the platform UI
Authorization Denied¶
Symptom: Order creation fails with "unauthorized identifier".
Causes: - Account does not have a domain binding for the requested domain - Subdomain requested but subdomain permission not granted - Wildcard requested but wildcard permission not granted
Resolution: - Review the account's domain bindings - Add missing bindings or enable required permissions
Order Stuck in Processing¶
Symptom: Order status remains "processing" indefinitely.
Causes: - Backend certificate signing job failed - Network connectivity issue between front and back control planes
Resolution: - Check the order's error field for details - Review platform health status - Contact support if the issue persists
Summary Checklist¶
- [ ] EAB required on all production ACME servers
- [ ] Domain bindings follow least privilege
- [ ] EAB credentials transmitted and stored securely
- [ ] Short validity periods configured
- [ ] Automatic renewal configured on all clients
- [ ] Renewal failure alerting in place
- [ ] Separate ACME servers for different environments
- [ ] Audit log reviewed periodically