Docker image with Caddy web server and Route53 DNS plugin for automatic HTTPS via DNS-01 ACME challenge.
Hi! I’ll probably rewrite this part a few more times, so make sure you’re using the latest version of the repo.
As someone who loves doing things fast, I prefer using ready-to-go containers instead of building them from scratch. This time, it’s my turn to help others do things faster — without any builds.
Here you’ll find an automated setup that explains everything clearly, includes usage samples, and works right out of the box.
To be honest, I built it first and only then realized that similar solutions already exist — but I’ll try to make this one better. The repo includes all the samples and recommendations you need for a full understanding of how to use it.
And the best part? It’s fully automated. So even if I stop using it (or, you know, die 😅), the containers should keep updating — assuming GitHub doesn’t delete my account!
— IvanN.co
- Latest Caddy: Automatically updated when new versions are released
- AWS Route53 Plugin: For ACME DNS-01 challenges (perfect for wildcard certificates)
- Multi-platform: AMD64 and ARM64 support
- Fully Automated: CI/CD pipeline checks for Caddy AND Route53 plugin updates weekly
- Version Pinning: Each image tag reflects exact versions of Caddy and Route53 plugin used
- Production Ready: Optimized for security and performance
docker pull ghcr.io/ivanndotco/caddy_xcaddy_route53:latestdocker run -d \
-p 80:80 \
-p 443:443 \
-p 443:443/udp \
-e AWS_ACCESS_KEY_ID=your_access_key \
-e AWS_SECRET_ACCESS_KEY=your_secret_key \
-e AWS_REGION=us-east-1 \
-v $PWD/Caddyfile:/etc/caddy/Caddyfile \
-v caddy_data:/data \
ghcr.io/ivanndotco/caddy_xcaddy_route53:latestdocker-compose up -dSee examples/ for ready-to-use configurations.
caddy-2.10.2-route53-1.6.0- Pinned versions (Caddy 2.10.2 + Route53 1.6.0)c2.10.2-r1.6.0- Short format (same as above)
latest- Always the most recent build2.10.2- Specific Caddy version (with latest Route53 plugin at build time)v2.10.2- Same with 'v' prefixcaddy-v2.10.2- Alternative format
Recommendation: Use the full version tags (e.g., caddy-2.10.2-route53-1.6.0) for production to ensure reproducible deployments with pinned plugin versions.
example.com {
tls {
dns route53
}
respond "Hello from Caddy with Route53!"
}*.example.com, example.com {
tls {
dns route53
}
@blog host blog.example.com
handle @blog {
reverse_proxy blog:8080
}
@app host app.example.com
handle @app {
reverse_proxy app:3000
}
}Ensure your domain uses Route53 for DNS:
- Transfer domain to Route53, or
- Update nameservers to Route53
Create IAM user or role with Route53 permissions:
{
"Version": "2012-10-17",
"Statement": [
{ "Effect": "Allow",
"Action": [
"route53:ListHostedZones",
"route53:ListHostedZonesByName",
"route53:GetChange"
],
"Resource": "*"
},
{ "Effect": "Allow",
"Action": [
"route53:ListResourceRecordSets",
"route53:ChangeResourceRecordSets"
],
"Resource": "arn:aws:route53:::hostedzone/ZONEID_OF_krusche_cloud"
}
]
}Option A: Environment Variables
AWS_ACCESS_KEY_ID=your_access_key_id
AWS_SECRET_ACCESS_KEY=your_secret_access_key
AWS_REGION=us-east-1Option B: IAM Role (recommended for AWS environments)
- Attach IAM role to EC2/ECS/EKS
- No credentials needed in environment
The examples/ directory contains ready-to-use configurations:
- Simple - Single domain with HTTPS
- Reverse Proxy - Proxy to backend services
- Multiple Domains - Multiple domains and wildcards
- WordPress - WordPress with MySQL
- Monitoring - Prometheus + Grafana
- Full Stack - Frontend + Backend + Database
- Advanced - Security headers, caching, load balancing
See the examples README for detailed guides.
example.com {
tls {
dns route53
}
root * /var/www/html
file_server
encode gzip
}api.example.com {
tls {
dns route53
}
reverse_proxy backend:8080 {
health_uri /health
health_interval 10s
}
}app.example.com {
tls {
dns route53
}
reverse_proxy backend1:8080 backend2:8080 backend3:8080 {
lb_policy round_robin
health_uri /health
}
}Minimal docker-compose.yml:
version: '3.8'
services:
caddy:
image: ghcr.io/ivanndotco/caddy_xcaddy_route53:latest
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
environment:
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
- AWS_REGION=${AWS_REGION:-us-east-1}
volumes:
caddy_data:
caddy_config:Create .env file:
AWS_ACCESS_KEY_ID=your_key
AWS_SECRET_ACCESS_KEY=your_secret
AWS_REGION=us-east-1Run:
docker-compose up -ddocker-compose logs -f caddydocker-compose exec caddy caddy reload --config /etc/caddy/Caddyfiledocker-compose exec caddy caddy list-certificatesdocker-compose exec caddy caddy validate --config /etc/caddy/Caddyfile- Verify AWS credentials are correct
- Check IAM permissions for Route53
- Ensure domain DNS uses Route53
- Check logs:
docker-compose logs caddy - Use GPTs to analyze the logs from step 4.
- Verify DNS records point to your server:
dig example.com - Check firewall allows ports 80, 443 (If the server is private, make sure you can access these resources somehow (like VPN). Ports 80 and 443 do not need to be open to the world, but they should work for you.
- Wait for DNS propagation (up to 48 hours)
- Verify backend service is running
- Check service names match in docker-compose
- Test backend directly:
curl http://backend:8080
- ✅ Use environment variables for credentials
- ✅ Never commit
.envto version control - ✅ Use IAM roles when running in AWS
- ✅ Enable security headers (see advanced example)
- ✅ Keep images updated
- ✅ Restrict access to sensitive endpoints
- ✅ Monitor logs for suspicious activity
- ✅ Enable compression (
encode gzip) - ✅ Cache static assets
- ✅ Use HTTP/3 (enabled by default on port 443/udp)
- ✅ Configure health checks for backends
- ✅ Use connection pooling
This repository uses a fully automated version tracking system:
- Weekly Checks: GitHub Actions checks for new Caddy and Route53 plugin releases every Monday at 2 AM UTC
- Version Detection: Compares current versions (stored in
versions.json) with latest GitHub releases - Automatic Updates:
- Always updates
versions.jsonwith current timestamp (prevents workflow suspension after 60 days) - If versions changed: Triggers new Docker build and pushes images with updated version tags
- If no changes: Simply updates the timestamp to keep workflow active
- Always updates
- Zero Manual Intervention: Everything happens automatically - no repo updates needed!
{
"caddy": "v2.10.2",
"route53": "v1.6.0",
"last_checked": "2025-11-05T12:00:00Z",
"changed": ["caddy"]
}This file is the source of truth for which versions are built into each Docker image.
Full version tag: caddy-2.10.2-route53-1.6.0
- Caddy web server version:
2.10.2 - Route53 DNS plugin version:
1.6.0 - Use this for production! It guarantees exact versions for reproducible builds.
Short version tag: c2.10.2-r1.6.0
- Same versions, compact format
- Useful when space is limited
Traditional tags: latest, 2.10.2, v2.10.2
- Backward compatible with old deployments
- Caddy version is pinned, but Route53 plugin version is whatever was latest at build time
Using full version tags (caddy-X.X.X-route53-Y.Y.Y) ensures:
- ✅ Reproducible builds: Exact same versions every time
- ✅ Audit trail: Know exactly what's in your container
- ✅ Easy rollback: Pin to known-good version combinations
- ✅ No surprises: Plugin updates won't break your setup unexpectedly
Want to customize? Fork this repository and modify:
Edit Dockerfile:
RUN xcaddy build \
--with github.com/caddy-dns/route53${ROUTE53_VERSION:+@$ROUTE53_VERSION} \
--with github.com/caddy-dns/cloudflare \
--with your-custom-plugin# Build with specific Caddy and Route53 versions
docker build \
--build-arg CADDY_VERSION=2.10.2 \
--build-arg ROUTE53_VERSION=v1.6.0 \
-t my-caddy:custom .
# Build with latest versions (default)
docker build -t my-caddy:latest .The repository includes GitHub Actions workflows that:
- Check for Caddy AND Route53 plugin updates weekly
- Build multi-platform images (AMD64, ARM64)
- Push to Docker Hub with version-pinned tags
- Fully automated - no manual intervention needed
See CONFIG.md for setup instructions.
- GitHub Issues: Report bugs and request features
- Caddy Community: caddy.community
This project follows Caddy's Apache 2.0 license.
Built with:
- Caddy - Modern web server
- xcaddy - Caddy build tool
- caddy-dns/route53 - Route53 DNS plugin