Introduction
When it comes to web servers, nginx has been the gold standard for years. However, the emergence of Angie—a modern fork of nginx developed by some of the original nginx team members—offers compelling reasons to consider migration. This article chronicles a real-world migration from nginx with certbot to Angie with its built-in ACME module, including the challenges faced and solutions implemented.
Why Migrate to Angie?
Angie brings several improvements over nginx:
- Built-in ACME support: No more external certificate management tools
- Enhanced features: Advanced load balancing, improved monitoring, and better HTTP/3 support
- Active development: Regular updates and new features from the team that helped create nginx
- Backward compatibility: Most nginx configurations work with minimal changes
The Migration Challenge
Our production environment was running:
- Web Server: nginx
- SSL Management: certbot for Let's Encrypt certificates
- Application: Next.js application proxied through nginx
- Domains: Multiple domains (tangaacademie.com, api.tangaacademie.com)
The goal was to migrate to Angie while replacing certbot with Angie's native ACME module for automated certificate management.
Step 1: Understanding Angie's ACME Module
Unlike certbot, which is an external tool that modifies your web server configuration and manages certificates separately, Angie's ACME module is built directly into the web server. This means:
- No external processes: Everything happens within Angie
- Configuration-based: Certificates are managed through Angie's config files
- Variable-based access: Certificates are exposed as embedded variables
- Automatic renewal: Handled internally without cron jobs
Key Concepts
The ACME module works through:
-
ACME clients: Defined in the
httpblock with unique names - Server references: Individual servers reference the ACME client
-
Certificate variables:
$acme_cert_<name>and$acme_cert_key_<name> - Automatic validation: Built-in handlers for HTTP, DNS, and ALPN challenges
Step 2: Installing Angie
First, we installed Angie following the official documentation:
# For RHEL/CentOS/AlmaLinux
sudo dnf install angie
# Start and enable Angie
sudo systemctl start angie
sudo systemctl enable angie
Step 3: Initial Configuration Migration
Our original nginx configuration looked like this:
# Original nginx config with certbot
server {
listen 80;
server_name tangaacademie.com www.tangaacademie.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name tangaacademie.com www.tangaacademie.com;
ssl_certificate /etc/letsencrypt/live/tangaacademie.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/tangaacademie.com/privkey.pem;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
We migrated this to Angie with ACME:
# /etc/angie/angie.conf or /etc/angie/sites-enabled/tangaacademie.conf
http {
# Critical: DNS resolver for ACME
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Define ACME client
acme_client tangaacademie https://acme-v02.api.letsencrypt.org/directory;
server {
listen 80;
server_name tangaacademie.com www.tangaacademie.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name tangaacademie.com www.tangaacademie.com;
# Reference ACME client
acme tangaacademie;
# Use ACME-managed certificates via variables
ssl_certificate $acme_cert_tangaacademie;
ssl_certificate_key $acme_cert_key_tangaacademie;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
Step 4: The DNS Resolver Challenge
After initial configuration, we encountered our first major issue. The Angie error logs showed:
[error] acme-v02.api.letsencrypt.org could not be resolved (5: Operation refused)
[error] request to ACME server failed: -1, ACME client: tangaacademie
The Problem
We initially configured the resolver as:
resolver 127.0.0.53;
This is a common systemd-resolved stub resolver on modern Linux systems. However, testing revealed the issue:
$ dig @127.0.0.53 acme-v02.api.letsencrypt.org
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
status: REFUSED
The local resolver was refusing recursive queries, which the ACME module requires to contact Let's Encrypt servers.
The Solution
We switched to public DNS resolvers:
# Google DNS
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Alternative: Cloudflare DNS
# resolver 1.1.1.1 1.0.0.1 valid=300s;
# resolver_timeout 5s;
After this change, the ACME module successfully connected to Let's Encrypt.
Step 5: Verification and Testing
After applying the configuration, we verified the setup:
# Test configuration
angie -t
# Reload Angie
systemctl reload angie
# Watch for ACME activity
tail -f /var/log/angie/error.log
The logs showed successful certificate acquisition:
[notice] creating implicit client block for "@acme"
[notice] ACME: requesting certificate for tangaacademie.com
We verified the certificates were issued:
$ openssl x509 -in /var/lib/angie/acme/tangaacademie/certificate.pem -noout -issuer -subject -dates
issuer=C=US, O=Let's Encrypt, CN=E7
subject=CN=tangaacademie.com
notBefore=Feb 1 11:04:38 2026 GMT
notAfter=May 2 11:04:37 2026 GMT
Perfect! Let's Encrypt had issued valid certificates.
Step 6: Managing Multiple Domains
For our API subdomain, we created a separate ACME client:
http {
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Main domain ACME client
acme_client tangaacademie https://acme-v02.api.letsencrypt.org/directory;
# API subdomain ACME client
acme_client apitangaacademie https://acme-v02.api.letsencrypt.org/directory;
# Main domain
server {
listen 443 ssl;
server_name tangaacademie.com www.tangaacademie.com;
acme tangaacademie;
ssl_certificate $acme_cert_tangaacademie;
ssl_certificate_key $acme_cert_key_tangaacademie;
# ... location blocks
}
# API subdomain
server {
listen 443 ssl;
server_name api.tangaacademie.com;
acme apitangaacademie;
ssl_certificate $acme_cert_apitangaacademie;
ssl_certificate_key $acme_cert_key_apitangaacademie;
# ... location blocks
}
}
Step 7: Cleaning Up Certbot
After confirming Angie's ACME module was working correctly, we removed certbot:
# Stop certbot renewal timer
sudo systemctl stop certbot.timer
sudo systemctl disable certbot.timer
# Remove certbot
sudo dnf remove certbot # or apt remove certbot
# Clean up old certificates (optional, after backup)
sudo rm -rf /etc/letsencrypt
Key Differences: Certbot vs. Angie ACME
| Aspect | Certbot | Angie ACME |
|---|---|---|
| Integration | External tool | Built into web server |
| Configuration | Modifies server config | Pure config-based |
| Certificate Access | File paths | Embedded variables |
| Renewal | Cron job required | Automatic internal |
| Process | Separate process | Same process as web server |
| Complexity | Moderate | Lower (once configured) |
| Startup | Web server independent | Certificates ready at startup |
Common Pitfalls and Solutions
1. DNS Resolver Issues
Problem: acme-v02.api.letsencrypt.org could not be resolved
Solution: Use public DNS resolvers instead of local stub resolvers:
resolver 8.8.8.8 8.8.4.4 valid=300s;
2. Old Certificate Paths
Problem: cannot load certificate "/etc/angie/"
Solution: Ensure all ssl_certificate directives use ACME variables:
ssl_certificate $acme_cert_<client_name>;
ssl_certificate_key $acme_cert_key_<client_name>;
3. Port 80 Not Open
Problem: HTTP validation fails
Solution: Ensure port 80 is accessible for ACME HTTP challenges. Angie automatically handles /.well-known/acme-challenge/ requests.
4. Missing Resolver Directive
Problem: ACME client can't contact Let's Encrypt
Solution: Always include a resolver directive in the http block.
Advanced Configuration: DNS Validation
For wildcard certificates or when port 80 isn't available, DNS validation is an option:
acme_client example https://acme-v02.api.letsencrypt.org/directory
challenge=dns;
server {
listen 443 ssl;
server_name example.com *.example.com;
acme example;
ssl_certificate $acme_cert_example;
ssl_certificate_key $acme_cert_key_example;
}
This requires configuring your DNS to delegate _acme-challenge. subdomains to your Angie server.
Monitoring and Maintenance
Check Certificate Status
# View certificate details
openssl x509 -in /var/lib/angie/acme/<client_name>/certificate.pem -noout -text
# Check expiration
openssl x509 -in /var/lib/angie/acme/<client_name>/certificate.pem -noout -dates
Monitor ACME Activity
# Watch error log for ACME events
tail -f /var/log/angie/error.log | grep -i acme
# Check certificate directory
ls -la /var/lib/angie/acme/
Debug Mode
For troubleshooting, enable debug logging:
error_log /var/log/angie/error.log debug;
Performance Considerations
Angie's built-in ACME module offers several performance advantages:
- Reduced overhead: No external processes or file monitoring
- Faster startup: Certificates are loaded at startup, no waiting for certbot
- Less disk I/O: Direct memory access to certificates via variables
- Simpler architecture: Fewer moving parts means fewer failure points
Security Best Practices
- Use strong SSL configuration:
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
- Enable OCSP stapling:
ssl_stapling on;
ssl_stapling_verify on;
- Implement HSTS:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
Conclusion
Migrating from nginx with certbot to Angie with built-in ACME proved to be a worthwhile endeavor. The key lessons learned:
- DNS resolver configuration is critical - Don't rely on local stub resolvers
- ACME variables simplify configuration - No more managing file paths
- Built-in integration is elegant - Fewer external dependencies
- Test thoroughly - Verify each domain and subdomain independently
The migration resulted in:
- ✅ Simplified infrastructure (no more certbot)
- ✅ More reliable certificate renewal
- ✅ Cleaner configuration
- ✅ Improved monitoring capabilities
- ✅ Better performance
For organizations running nginx, Angie represents a compelling upgrade path that maintains compatibility while offering modern features and simplified certificate management.
Resources
- Angie Official Documentation
- Angie ACME Configuration Guide
- Let's Encrypt Documentation
- ACME Protocol Specification (RFC 8555)
About the Author: This migration was performed on a production environment running Next.js applications with multiple domains in February 2026.
Top comments (0)