Building caddy with cloudflare DNS challenges on Rocky Linux

Building caddy with cloudflare DNS challenges on Rocky Linux

Caddy is a free and open source web server or reverse proxy that automatically registers and renews SSL certificates for your HTTPS websites. The default method for ACME (Automated Certificate Management Environment) to register & renew the SSL certificates with Caddy however requires that you have ports 80 exposed to the web – this is known as the HTTP challenge. If you’re like me and already have something hosted on that port (or don’t want the server accessible externally via the web), then you need to consider other options for issuing the certificate.

Caddy has 3 options for registering & renewing your SSL certificates including the aforementioned HTTP challenge, a TLS-ALPN challenge which is the same as the HTTP challenge but instead uses port 443 or HTTPS to verify the certificate & finally a DNS challenge which does not require any ports be forwarded in from the web to your server and instead queries a TXT DNS record for your domain name to verify ownership of the domain.

I set out to build a Caddy server for my home lab using the DNS challenge to issue my certificates but struggled to find an article online that walked me through what we were doing when installing Caddy. This lead me to set aside some time, learn for myself and document the steps that I had to take so I could understand what we were doing & why we were doing it. Below I have listed out the commands required to build your own Caddy server if you’re interested in securing your sites with HTTPS.


· Basic understanding of the Linux command line

· Rocky Linux OS (minimal install)

· Internet access from your server

Start off by downloading & installing Rocky Linux using the minimal install option to prevent the server from being overloaded with features we won’t be using! Once you’ve got the server up and running, SSH into the server or access it via the terminal and let’s start by installing a couple of features we’re going to need to setup this server:

dnf install wget
dnf install nano
dnf install tar
Installing pre-requisites
Command Breakdown

The above info-graphic shows you what these 3 commands are doing. This is useful to know for all Linux machines that you’ll be working on – however the first command (dnf) can be different in varying flavors of Linux.

Now that we’re got our required apps installed, we need to setup the Go Programming Language which will be utilized to execute xcaddy & caddy. You can see an article here (Download and install - The Go Programming Language ( on how to install The Go Programming language or you can refer to the commands as I’ve entered them below.

rm -rf /usr/local/go && tar -C /usr/local -xzf go1.16.6.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
nano ~/.bash_profile
Download & install the Go Programming Language

From here, add export PATH=$PATH:/usr/local/go/bin to the opened file.

The first command we ran here is simply to download the required files for installation to the current directory we’re inside of. Secondly, we’ve deleted any existing go binaries and then extracted the Go Programming Language binaries to the /user/local folder on our server. The third command sets the default path which Go will have executable files stored within (if the applications you want to execute/run are not within the “/user/local/go/bin” directory then you will not be able to run the application). The third command however only sets the default path which Go will execute from in your current session so if you logout and back in, you will lose this setting. The final command will open the default logon profile which allows you to set this variable for every logon.

Now we are going to use Go to download the latest version of xcaddy which allows us to create a custom version of caddy with plugins (such as the CloudFlare DNS challenge plugin).

go install

As mentioned above, we won’t be able to execute any files with Go unless they are stored within the “/usr/local/go/bin” folder so we now need to move xcaddy into this location with the below command and then execute the build of caddy with the CloudFlare plugin

cp xcaddy /usr/local/go/bin/xcaddy
xcaddy build \
> --with
Build caddy with the cloudflare plugin

That should have now build a version of caddy with the CloudFlare plugin installed. Again, let’s copy this to “/usr/local/go/bin” so that we can execute it.

cp caddy /usr/local/go/bin/caddy

Now it’s time to test whether this worked! Let’s try start caddy and check the version.

caddy start
caddy version
Start the caddy service & check the version

Great! We’ve now started caddy and we can see it’s working but we don’t have any configuration setup telling caddy what we want to do. Before we setup a configuration file to do this however, we need to jump into our CloudFlare portal and create an API secret key to use with caddy. Login to My Profile | Cloudflare - Web Performance & Security and click “Create Token” with the below settings. Once created, make sure to copy the secret key and keep it in a safe location.

Now let’s create a directory to store caddy and then create a configuration file to get a certificate for. Then we will create the “Caddyfile” configuration and then paste the below configuration but replace “” with your own domain name & “SECRET-API-TOKEN-FROM-CLOUDFLARE” with the your API token created above.

mkdir /etc/caddy/
touch /etc/caddy/Caddyfile
nano /etc/caddy/Caddyfile
Make a Caddyfile which will contain our configuration for the domains being served {
tls {
respond “Hello world”
This is the contents you will need to replicate in your own Caddyfile

Next, we can format the file we created using the below command & finally we will reload caddy with the

Caddy fmt
Caddy reload /etc/caddy/Caddyfile

You will see after reloading Caddy that there will be a DNS challenge issued and a successful response for the certificate to issue.

From here, you can start publishing websites directly on your Caddy server or using the reverse proxy to publish existing sites on other servers within your network.