Automated TLS Certificates: Let’s Encrypt Wildcards, ACME DNS-01 & Reverse Proxies

3 min read

Manual SSL certificate generation, CSR generation, and cron-based renewals are completely obsolete. Modern homelab and production environments automate 100% of the certificate lifecycle using ACME challenge protocols.

This guide explains how to configure DNS-01 ACME challenges using Caddy and the Cloudflare API to issue wildcard certificates (e.g. *.homelab.example.com) without exposing port 80 or 443 to the public internet.

⚡ Quick Runbook: 60-Second Implementation

TL;DR: Deploy Caddy with the Cloudflare DNS module for fully automated wildcard certificates:

# compose.yaml
services:
  caddy:
    image: caddy:2.8-alpine
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    environment:
      - CLOUDFLARE_API_TOKEN_FILE=/run/secrets/cf_token
    secrets:
      - cf_token
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
      - caddy_config:/config

secrets:
  cf_token:
    file: ./secrets/cf_token.txt

volumes:
  caddy_data:
  caddy_config:

1. Why DNS-01 Challenges Are Essential for Private Homelabs

  • HTTP-01 Challenges: Require your server to have port 80 open to the public internet so Let’s Encrypt can reach a temporary challenge file. This is incompatible with private LANs, internal homelabs, and CGNAT connections.
  • DNS-01 Challenges: Prove domain ownership by creating a temporary TXT record in your DNS provider (e.g. Cloudflare) via API. Zero open inbound firewall ports are required, and wildcard certificates (covering all subdomains under a single certificate) become possible.

2. Caddyfile Configuration for Cloudflare DNS-01 Wildcards

In your Caddyfile, specify the Cloudflare DNS provider inside the tls block:

# Global configuration
{
    email [email protected]
}

# Wildcard Certificate for All Homelab Services
*.homelab.example.com {
    tls {
        dns cloudflare {env.CLOUDFLARE_API_TOKEN}
    }

    @vault host vault.homelab.example.com
    handle @vault {
        reverse_proxy vaultwarden:80
    }

    @git host git.homelab.example.com
    handle @git {
        reverse_proxy forgejo:3000
    }

    handle {
        respond "Unauthorized" 401
    }
}

3. Securing Your Cloudflare API Token

Follow the principle of least privilege when generating your Cloudflare API token:

  1. Navigate to Cloudflare Dashboard > My Profile > API Tokens.
  2. Click Create Token and choose the Edit zone DNS template.
  3. Under Zone Resources, select Specific zone and choose only your target domain.
  4. Save the token into a secure file (e.g., ./secrets/cf_token.txt) with restrictive permissions (chmod 600) and mount it as a Docker secret.

Related Runbooks in This Series

Tags:

← Previous:
Next: →