Introduction
In my homelab setup, I have been using Nginx as a reverse proxy from the very beginning. It has served me well and in fact, I have a post dedicated to it and how happy I am with setting it up via Ansible. However, I have been wanting to try out Caddy for a while now and felt like this was a right time to try it out along with generating universal SSL certificates from Cloudflare so that I can avoid the hassle of generating local certificates and adding myself as a trusted certificate authority.
Caddy is a powerful web server that is easy to configure and has a lot of features that make it a great choice for a reverse proxy. One of the main features that attracted me to Caddy is the ability to automatically obtain SSL certificates (and renew them) from Cloudflare.
So let’s go over the steps I took to set it up.
Installing Caddy with Cloudflare DNS module
Recently, Caddy has removed many modules from the default build and instead recommends using the Cloudflare DNS module ↗️.
So instead of installing Caddy via the package manager of your OS, we will install the build with the Cloudflare DNS module.
One way of doing this is building it from source using the xcaddy
tool. However, you can also download the pre-built binaries from here: https://caddyserver.com/download ↗️
Pro Tip
Here’s an easy way to find the direct download link for your OS.
Go to this URL ↗️ and replace the os
and arch
with your OS and architecture.
The above link is for a Linux ARM64 machine.
Once you have downloaded the binary, you can make it executable with chmod +x caddy
and move it to a directory that is in your PATH
like /usr/local/bin
.
Source your shell profile for the changes to take effect and you should now be able to run caddy
in your terminal.
Configuring Caddy with Cloudflare DNS module
Perfect, so we have Caddy installed with Cloudflare DNS module. Now we need to configure it to automatically obtain SSL certificates from Cloudflare for our domains.
Create a new Caddyfile at /etc/caddy/Caddyfile
and add the following configuration:
Replace YOUR_CLOUDFLARE_API_TOKEN
with your actual Cloudflare API token. You can generate one from your Cloudflare dashboard ↗️ with minimum permissions of Edit: Zone.DNS
.
Run Caddy with SystemD
Finally, we need to run Caddy as a SystemD service. Create a new service file at /etc/systemd/system/caddy.service
and add the following configuration:
Make sure to reload the SystemD daemon for the changes to take effect:
And start the Caddy service:
And enable it to start on boot:
Now for the first time, Caddy should obtain an SSL certificate for your domain and start serving it.
You can check the logs of Caddy with sudo journalctl -u caddy -f
.
That’s it! You have successfully set up Caddy with automatic SSL certificates from Cloudflare. Go ahead and test it out by accessing your domain in the browser.
How it works?
This section is for those who are curious about how all of this works exactly.
So when I say that we are generating SSL certificates from Cloudflare, the certificate are actually generated by Let’s Encrypt ↗️ using the DNS-01 challenge ↗️. How DNS-01 challenge works is that, Let’s Encrypt will verify that we control the domain by adding a TXT record with a random string to the DNS zone of the domain.
So suppose I am using example.com
as my domain. The IP address that I add as the A record in Cloudflare is the private IP address of the machine where Caddy is running.
So it’s something like 192.168.1.100
. Now with a private IP address, Let’s Encrypt will not be able to verify that we control the domain and will not be able to issue the certificate.
To solve this, Cloudflare will act as a proxy and will add the TXT record with the random string to the DNS zone of the domain. Once Let’s Encrypt verifies this, it will issue a certificate for the domain and Caddy will be able to use it.
All of this is handled automatically by Caddy (with the help of Cloudflare DNS module) and we don’t need to worry about it.
Conclusion
Its amazing to see how easy it was to set up Caddy with automatic SSL certificates from Cloudflare and the configuration is much simpler than Nginx (not saying Nginx is complicated, it’s just that Caddy’s syntax is more straight forward and easier to understand).
I will be using Caddy for a while now and will update this post with more tips and tricks that I learn along the way.
If you have any questions or suggestions, feel free to reach out to me on Twitter ↗️ / Reddit ↗️ or in the comments below.
Happy SSLing! đź‘‹