Inhaltsverzeichnis

ACME Integration

Complexity: Medium
Duration: 1-2 hours setup
Prerequisite: DNS/HTTP challenge access

Integration of the ACME protocol (RFC 8555) for automatic certificate renewal with post-quantum support.


Architecture

sequenceDiagram participant Client as ACME Client participant CA as ACME CA participant DNS as DNS/HTTP Server participant App as Application Client->>CA: 1. Create account Client->>CA: 2. Create order (CSR) CA->>Client: 3. Challenge (DNS-01/HTTP-01) Client->>DNS: 4. Fulfill challenge CA->>DNS: 5. Validate challenge CA->>Client: 6. Issue certificate Client->>App: 7. Deploy certificate Client->>App: 8. Reload service


Certbot Installation

# Debian/Ubuntu
apt update && apt install certbot python3-certbot-nginx
 
# RHEL/CentOS
dnf install certbot python3-certbot-nginx
 
# With DNS plugin (Cloudflare)
apt install python3-certbot-dns-cloudflare

HTTP-01 Challenge

For publicly accessible web servers:

# Nginx
certbot --nginx -d example.com -d www.example.com
 
# Apache
certbot --apache -d example.com -d www.example.com
 
# Standalone (port 80 free)
certbot certonly --standalone -d example.com
 
# Webroot (existing server)
certbot certonly --webroot -w /var/www/html -d example.com

Auto-Renewal Cron:

# Automatically activated during certbot installation
# Check manually:
systemctl status certbot.timer
 
# Manual test
certbot renew --dry-run

DNS-01 Challenge

For internal servers or wildcards:

Cloudflare

# /etc/letsencrypt/cloudflare.ini
dns_cloudflare_api_token = YOUR_API_TOKEN
chmod 600 /etc/letsencrypt/cloudflare.ini
 
certbot certonly \
    --dns-cloudflare \
    --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
    -d example.com \
    -d "*.example.com"

Route53 (AWS)

# AWS credentials in ~/.aws/credentials
certbot certonly \
    --dns-route53 \
    -d example.com \
    -d "*.example.com"

Azure DNS

# With certbot-dns-azure plugin
pip install certbot-dns-azure
 
certbot certonly \
    --authenticator dns-azure \
    --dns-azure-credentials /etc/letsencrypt/azure.ini \
    -d example.com

Deployment Hooks

Hooks are executed after successful renewal.

Nginx Reload

# /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
#!/bin/bash
systemctl reload nginx
echo "$(date): Nginx reloaded" >> /var/log/certbot-deploy.log
chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

Apache Reload

# /etc/letsencrypt/renewal-hooks/deploy/reload-apache.sh
#!/bin/bash
systemctl reload apache2

Docker Container

# /etc/letsencrypt/renewal-hooks/deploy/docker-reload.sh
#!/bin/bash
docker exec nginx nginx -s reload
# or
docker-compose restart nginx

Notification

# /etc/letsencrypt/renewal-hooks/post/notify.sh
#!/bin/bash
DOMAINS=$(echo $RENEWED_DOMAINS | tr ' ' '\n')
echo "Renewed: $DOMAINS" | mail -s "Certificate renewed" admin@example.com

Private ACME CA (Step-CA)

For internal PKI with ACME support:

# Install Step-CA
wget https://github.com/smallstep/certificates/releases/download/v0.25.0/step-ca_0.25.0_amd64.deb
dpkg -i step-ca_0.25.0_amd64.deb
 
# Initialize CA
step ca init --name="Internal CA" --dns=ca.internal.example.com --address=:443

Add ACME Provisioner:

step ca provisioner add acme --type ACME

Certbot with private CA:

certbot certonly \
    --server https://ca.internal.example.com/acme/acme/directory \
    --standalone \
    -d internal-server.example.com

Post-Quantum Note

Status 2024: ACME protocol and Let's Encrypt do not yet support PQ signatures.

Hybrid Strategy:

# 1. ACME certificate for TLS handshake (ECDSA)
certbot certonly --nginx -d example.com
 
# 2. Additional PQ certificate for hybrid mode
# (parallel via own PKI with WvdS)
// C#: Create hybrid certificate in parallel
using var ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP384);
var request = new CertificateRequest(
    "CN=example.com", ecdsa, HashAlgorithmName.SHA384);
 
// With PQ extension for future-proof clients
var cert = request.CreateSelfSigned(
    DateTimeOffset.UtcNow,
    DateTimeOffset.UtcNow.AddDays(90),
    CryptoMode.Hybrid);

Monitoring

# Certbot logs
tail -f /var/log/letsencrypt/letsencrypt.log
 
# Check certificate expiry
certbot certificates
 
# Prometheus Exporter (cert-exporter)
# Monitors all certificates for expiry

Troubleshooting

Problem Cause Solution
—————-———-
Challenge failed Port 80/443 blocked Check firewall
DNS propagation DNS cache Wait (up to 60 min) or reduce TTL
Rate limit exceeded Too many requests Use staging server
unauthorized Domain validation failed Check DNS records
# Staging server for tests (no rate limits)
certbot certonly --staging --nginx -d test.example.com
 
# Debug mode
certbot certonly --nginx -d example.com --debug

Checklist

# Checkpoint Done
——————
1 DNS/HTTP challenge configured
2 Certbot installed and tested
3 Auto-renewal activated (timer)
4 Deploy hook configured
5 Monitoring set up
6 Notification on error


« <- Automation | -> CI/CD Code Signing »


Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional