Automatisierte Zertifikatserstellung
Reverse Proxy & SSL Automation Documentation
Target System: RHEL (edge.example.com)
Container Engine: Podman
SSL Provider: Let’s Encrypt
1. Environment Architecture
The system uses a Native Certbot installation on the RHEL host to manage certificates and a Podman Container to serve the Nginx reverse proxy.
- Host Path:
/etc/letsencrypt(Certificates) - Webroot Path:
/var/www/letsencrypt(ACME Challenges) - Container Name:
reverse-proxy - Image:
quay.io/mshn/reverseproxy:latest
2. Infrastructure Prerequisites
Network & Firewall
Inbound traffic on Port 80 and 443 must be allowed through the RHEL firewall and forwarded from the external router to this host’s IP (85.195.230.53).
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
Host Permissions & SELinux
Certbot directories are restricted by default. These commands allow the containerized Nginx process to traverse the directory tree and read the certificate files.
# Set directory traversal permissions
sudo chmod 755 /etc/letsencrypt /etc/letsencrypt/live /etc/letsencrypt/archive
sudo chmod 755 /etc/letsencrypt/live/mkdir-bundle /etc/letsencrypt/archive/mkdir-bundle
# Set file read permissions
sudo chmod 644 /etc/letsencrypt/archive/mkdir-bundle/*.pem
# Ensure challenge directory exists
sudo mkdir -p /var/www/letsencrypt
sudo chmod 755 /var/www/letsencrypt
# Apply SELinux labels for Podman volume access
sudo chcon -Rt svirt_sandbox_file_t /etc/letsencrypt
sudo chcon -Rt svirt_sandbox_file_t /var/www/letsencrypt
3. Nginx Configuration (nginx.conf)
The configuration must handle the .well-known/acme-challenge/ path locally to allow Certbot to verify domain ownership without interfering with proxied traffic.
# Example Server Block for Port 80 (Redirect & Challenge)
server {
listen 80;
server_name timeline.example.com immich.example.com www.goboi.ch trading.example.com;
location /.well-known/acme-challenge/ {
root /var/www/letsencrypt;
}
location / {
return 301 https://$host$request_uri;
}
}
# Example Server Block for Port 443 (SSL & Proxy)
server {
listen 443 ssl;
server_name immich.example.com;
ssl_certificate /etc/letsencrypt/live/mkdir-bundle/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mkdir-bundle/privkey.pem;
location /.well-known/acme-challenge/ {
root /var/www/letsencrypt;
}
location / {
proxy_pass https://router-default.apps.mnp.example.com;
# ... proxy headers ...
}
}
4. Automation & Services
Systemd Container Service
Path: /etc/systemd/system/container-reverse-proxy.service
[Unit]
Description=Podman Nginx Reverse Proxy Container (Auto-Pull)
After=network-online.target
Wants=network-online.target
[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=always
TimeoutStopSec=70
ExecStart=/usr/bin/podman run \
--name reverse-proxy \
--rm \
--replace \
--pull=always \
-v /etc/letsencrypt:/etc/letsencrypt:Z \
-v /var/www/letsencrypt:/var/www/letsencrypt:Z \
-v /var/log/nginx:/var/log/nginx:Z \
-p 80:80 -p 443:443 \
quay.io/mshn/reverseproxy:latest
ExecStop=/usr/bin/podman stop -t 10 reverse-proxy
ExecStopPost=/usr/bin/podman rm -f reverse-proxy
Type=simple
[Install]
WantedBy=multi-user.target
Certbot Renewal Timer
The systemd timer handles automated renewal checks twice daily.
# Enable the timer
sudo systemctl enable --now certbot-renew.timer
5. Maintenance Commands
| Task | Command |
|---|---|
| Apply Nginx Config Changes | Rebuild/Push Image then: sudo systemctl restart container-reverse-proxy |
| Dry-Run Renewal | sudo certbot renew --dry-run |
| Check Active Timers | systemctl list-timers |
| View Container Logs | podman logs -f reverse-proxy |
| Update Cert Domains | Run certbot certonly --webroot ... (with -d flags) |
Troubleshooting
If the container fails to start with “Permission Denied” errors:
- Re-run the
chmodcommands in Section 2. - Ensure the SELinux labels (
chcon) are applied to the/etc/letsencryptfolder. - Check the container logs using
journalctl -u container-reverse-proxy -f.