Following Part 3
of the series, the final component to be set up is the Caddy reverse proxy. I previously used traefik
and while it worked, there were a few hiccups I encountered. I can’t recall the exact issues I ran into, but they were enough for me to switch things up this time. On this particular VPS, I won’t be running many services so auto-discovery is irrelevant. I’m binding each service to a specific IP and port, then using Caddy to reverse proxy to them, which simplifies a lot of the management and admin. Caddy also handles automatic certificate renewal with my custom CA using the ACME endpoint I set up earlier, so that’s an added bonus.
For this specific use case, I am using Caddy to accept all incoming requests meant for AdGuard DNS and Smallstep CA and proxying them to the correct services. Each of these services will have their own private certificate that is generated by Caddy from our local Certificate Authority.
The Docker Compose file and configuration of Caddy is located in /containers/caddy
base folder.
/containers/caddy/docker-compose.yaml
services:
caddy:
image: caddy:latest
container_name: caddy
restart: unless-stopped
volumes:
- /containers/smallstep/data/certs/root_ca.crt:etc/ssl/certs/root_ca.crt:ro # load our root CA into caddy
- /containers/caddy/config:/etc/caddy
- /containers/caddy/data:/data
ports:
- '192.168.200.1:80:80/tcp' # listen for HTTP on wireguard interface (tcp)
- '192.168.200.1:443:443/tcp' # listen for HTTPS on wireguard interface (tcp)
networks:
- webproxy
networks:
webproxy:
external: true
Configure Caddy
Create the file /containers/caddy/config/Caddyfile
and add the following information to it
{
acme_ca https://smallstep-vps:9000/acme/handletec-vps/directory
acme_ca_root /etc/ssl/certs/root_ca.crt
email info@handletec.my
}
import /etc/caddy/config.d/*.conf
This config specifies we want to use our custom CA to generate certificates and with all our configuration in place, the Smallstep service will be able to connect back to Caddy for verification. We also allow including individual files for our services to more tidily manage them without cluttering the Caddyfile
. We use the container name smallstep-vps
to connect to the Smallstep service.
We create another file /containers/caddy/config/config.d/service.conf
with the following contents
ca.vps.homelab.my {
reverse_proxy https://smallstep-handletec-vps:9000
}
dns.vps.homelab.my {
reverse_proxy http://adguardhome:8000
}
This is all that’s needed for our Caddy to automatically generate certificates per domain name. Notice how we use the container names as Docker can resolve these names using its internal DNS. The reverse_proxy
directive is responsible for forwarding requests from each domain to the correct service.
Firewall
The final step is to allow the Docker network to connect to our Caddy and perform the validation of the domain name targets. Since our Caddy is listening on our specific Wireguard interface, we can create a rather lax rule to prevent any issues.
ufw allow proto tcp from any to any port 80
And that concludes our series on setting up a personal Certificate Authority for our own use. While I use this primarily for my own homelab, I can envision this being used in companies and organizations that want to utilize end-to-end TLS security for their own needs.
Happy reading!