This Ansible repo sets up a Caddy reverse proxy for my homelab services. It integrates with the Crowdsec plugin that runs on my OPNsense box.
- OPNsense: Protectli FW4C, Intel Pentium J3710, 4GB RAM
- VM on Proxmox host, 2GB RAM, 4 CPU of Intel Celeron N5105
Dustin Casto wrote an outstanding guide on this setup on his website. I automated it with Ansible.
Caddy runs on a VM in Proxmox on a DMZ network. I access it via Tailscale, and it redirects me to the desired service.
Every service runs with a valid HTTPS certificate. I use a wildcard certificate because it's easier to manage. I also found that retrieving certificates for each subdomain is very unreliable on my network and might take hours.
I also do some SSH hardening and set up a UFW firewall.
- Cloudflare account with an API key with permissions:
Zone.Zone Read
andZone.DNS Edit
. You need to set up this keyroles/reverse_proxy/files/caddy_override.conf
file. - I use OPNsense as my firewall. However, it should be possible to modify this playbook to just install and set up Caddy.
- A domain name, since we want valid HTTPS certificates.
- Ubuntu. This setup has been tested on Ubuntu 24.04, but should work on any Debian-based system.
- I use Ubuntu cloud images to quickly bootstrap new virtual machiens on Proxmox.
- An
inventory
file which contains the Caddy machine IP, username and the relevant SSH key. For example,
[caddy]
192.168.100.100 ansible_user=artur ansible_ssh_private_key_file=~/.ssh/id_ed25519
This repo assumes that you have set up Crowdsec on OPNsense according to Dustin's guide. During the playbook's run, it will pause and ask you to validate the Caddy machine in OPNsense. Make sure you do it as described in the guide.
This repo builds Caddy with the Cloudflare plugin to perform the DNS-01 challenge to validate that you own a domain. This guide might be helpful
- Create the inventory. The repo assumes the file is called
inventory
. - Define host variables in
host_vars/caddyDMZ.yml
. The comments in the example file should be helpful. - Set up your Caddyfile in
roles/reverse_proxy/files
. See the provided example for ideas. I am using Authentik for some of the apps that do not provide built-in authentication. - Set up
caddy_override.conf
. It only contains the Cloudflare API token. Keep it safe!
Remove the .example
extension from the provided files.
Provided you have Ansible installed and inventory
and ansible.cfg
, run ansible-playbook caddy.yml
.
- I use
unattended-upgrades
to upgrade the system. It also might reboot if it's necessary after the update. That's not ideal if you want 100% availability and stability because things can break after an update. Ubuntu is a rather stable system, and I only automatically install security updates; it should not break after a reboot. - I took steps to harden SSH and set up a firewall, but it is not a super-protected system. I do not expose any ports on my home network and use public key authentication for SSH, so this security level works for me.
- If you are inside your home network, you can set up OPNsense to override IP address that are returned by DNS. Now, if you request
service.example.com
, you will not query a remote DNS server, and the domain will resolve immediately to your local IP. See Unbound DNS Override Aliases in OPNsense for more information.
This is still work-in-progress. I use Tailscale to access my network. Currently, I install and set up Tailscale manually.
- Dustin Casto for the amazing guide, Set Up a Caddy Reverse Proxy with Let's Encrypt and CrowdSec Using OPNsense LAPI, this repo is based.
- Jay LaCroix's excellent Ansible video series.
- Jim's Garage for changing the way I create new VMs.
- Software developers whose work made this repo possible.
The repo is available on: