Setup Caddy with automatic SSL certificates with Cloudflare

📆 · ⏳ 5 min read · ·

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:

Terminal window
https://example.com {
reverse_proxy localhost:8080
dns cloudflare {
api_token YOUR_CLOUDFLARE_API_TOKEN
}
}

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:

Terminal window
[Unit]
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Requires=network-online.target
[Service]
Type=notify
User=caddy
Group=caddy
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile --force
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target

Make sure to reload the SystemD daemon for the changes to take effect:

Terminal window
sudo systemctl daemon-reload

And start the Caddy service:

Terminal window
sudo systemctl start caddy

And enable it to start on boot:

Terminal window
sudo systemctl enable caddy

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! đź‘‹

You may also like

  • # homelab# selfhosted# networking

    Tailscale — Accessing Homelab services outside my network

    Tailscale is another service that I use in my homelab setup to access my services outside my network. It's a VPN service that makes it easy to access your devices, services, and networks securely.

  • # homelab# selfhosted# networking

    AdGuard Home — Network Wide Ad Blocking in your Homelab

    Let's talk about AdGuardHome, a network-wide ad blocking software that you can run in your homelab. It's a great way to block ads and trackers on your network without having to install ad blockers on every device.

  • # homelab# selfhosted# networking

    Nginx — The reverse proxy in my Homelab

    Nginx is a powerful reverse proxy that I use in my homelab to expose services to the internet. In this post, I'll show you how I use it and how you can use it too.