Angie includes a native ACME client — no Certbot, no cron jobs, no hooks. It handles certificate issuance, renewal, and reloading automatically, all from inside nginx.conf.
How it works
Angie implements the ACME protocol (RFC 8555) directly in the server process. When Angie starts (or reloads), it checks whether the certificate for each acme-enabled server is absent, expiring, or already valid. If a certificate is needed, it completes the HTTP-01 challenge on port 80, saves the certificate and private key to disk, and loads them into memory — all without external tooling.
Renewal is triggered automatically when the certificate has fewer than 30 days remaining (configurable). Angie performs a graceful reload after renewal so in-flight requests are not dropped.
Basic setup
Declare the ACME client once in the http block, then attach it to each server with the acme directive:
http {
acme_client letsencrypt https://acme-v02.api.letsencrypt.org/directory;
server {
listen 80;
listen 443 ssl;
server_name example.com;
acme letsencrypt;
ssl_certificate $acme_cert_letsencrypt;
ssl_certificate_key $acme_cert_key_letsencrypt;
}
}
Angie handles the HTTP-01 challenge automatically on port 80. No separate location /.well-known/acme-challenge/ block is needed.
Multiple domains on one certificate
All names in server_name are added to the certificate’s Subject Alternative Name (SAN) list automatically. A single certificate covers all of them:
server {
listen 443 ssl;
server_name example.com www.example.com static.example.com;
acme letsencrypt;
ssl_certificate $acme_cert_letsencrypt;
ssl_certificate_key $acme_cert_key_letsencrypt;
}
Multiple CAs
Declare multiple acme_client entries and attach more than one to a server. The server will present certificates from whichever CA the client supports best:
acme_client letsencrypt https://acme-v02.api.letsencrypt.org/directory;
acme_client zerossl https://acme.zerossl.com/v2/DV90;
server {
acme letsencrypt;
acme zerossl;
ssl_certificate $acme_cert_letsencrypt;
ssl_certificate_key $acme_cert_key_letsencrypt;
}
Staging / testing
Use the Let’s Encrypt staging endpoint during testing to avoid hitting rate limits. Staging certificates are not trusted by browsers but are otherwise identical to production certificates:
acme_client letsencrypt_staging
https://acme-staging-v02.api.letsencrypt.org/directory;
Custom email and storage path
The email parameter registers your contact address with the CA (used for expiry warnings). The path parameter controls where certificates and private keys are stored on disk:
acme_client letsencrypt https://acme-v02.api.letsencrypt.org/directory
email moc.elpmaxe@nimda
path /etc/angie/ssl/acme;
Full example with HTTP redirect
http {
acme_client letsencrypt https://acme-v02.api.letsencrypt.org/directory
email moc.elpmaxe@nimda;
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
http2 on;
server_name example.com www.example.com;
acme letsencrypt;
ssl_certificate $acme_cert_letsencrypt;
ssl_certificate_key $acme_cert_key_letsencrypt;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
location / {
root /var/www/example.com;
}
}
}
Renewal
Angie renews automatically before expiry (default: 30 days before). On renewal it performs a graceful reload — zero downtime, no cron needed. To monitor certificate expiry:
curl -s http://127.0.0.1/status | python3 -m json.tool | grep -A10 '"acme"'
Checking certificate status
With the status API enabled, Angie exposes certificate expiry timestamps in the /status JSON output. Useful for alerting:
location /status {
api;
allow 127.0.0.1;
deny all;
}
# Check expiry from the command line:
curl -s http://127.0.0.1/status | python3 -m json.tool | grep -A5 acme
HTTP-01 challenge behind a proxy
If Angie sits behind a load balancer or CDN, HTTP-01 challenges must reach Angie on port 80. Forward challenge traffic through the upstream proxy:
# Upstream proxy: forward challenge traffic to Angie
location /.well-known/acme-challenge/ {
proxy_pass http://angie_backend;
}
Frequently asked questions
Does Angie ACME work if port 80 is blocked?
Not with HTTP-01 challenges. Let’s Encrypt requires port 80 to be reachable from the internet for HTTP-01. If port 80 is blocked by a firewall, use DNS-01 challenges instead — but Angie’s built-in ACME module only supports HTTP-01. For DNS-01 you would need Certbot with a DNS plugin.
Can I use Angie ACME with wildcard certificates?
No. Wildcard certificates require DNS-01 challenges. The Angie ACME module only supports HTTP-01, which validates domain control via a file served on port 80. Wildcards are not possible with HTTP-01.
Where does Angie store the certificates?
In the path specified by the path parameter of acme_client. The default is /etc/angie/acme/. The private key and certificate are stored as PEM files and referenced by the $acme_cert_* and $acme_cert_key_* variables.
What happens if the ACME CA is unreachable at renewal time?
Angie will retry. As long as the existing certificate has not yet expired, it continues serving the current certificate. Let’s Encrypt certificates are valid for 90 days; with a 30-day renewal window there is a 60-day buffer for retries. If the certificate does expire, Angie logs an error and stops serving TLS on that server.
Can I use Angie ACME with an internal CA (e.g. Step CA)?
Yes — any ACME-compatible CA works. Set the acme_client URL to your internal CA’s ACME directory URL. Step CA, Smallstep, HashiCorp Vault PKI, and EJBCA all support RFC 8555.
Does ACME renewal cause any downtime?
No. Angie performs a graceful reload after issuing a new certificate. Active connections complete normally; new connections start using the new certificate. The reload typically takes under 100 ms.
How do I migrate from Certbot to Angie ACME?
- Add the
acme_clientandacmedirectives to your config - Change
ssl_certificateandssl_certificate_keyto the$acme_cert_*variables - Run
angie -tto check the config - Reload Angie:
systemctl reload angie - Angie will fetch a new certificate immediately on reload
- Once confirmed working, remove Certbot:
apt-get remove certbotand delete the cron/systemd timer