Caddy server SSL setup for wildcard domains

Pinterest LinkedIn Tumblr
CI/CD Illustration


This week, at Truemark we are setting up branch based deployments for all out apps with gitlab-ci and caddy. Our initial setup utilised the ssl auto generation that comes out of the box with caddy but it was not working as expected with branch based deployments.
Our caddy config was handling all the branch deployments via wildcard domains(eg: we would listen to *.preview.awesome.app and if one visits branch1.preview.awesome.app, they would see the content from /var/www/html/awesome_app/branch1 and if they visited branch2.preview.awesome.app they would see content from /var/www/html/awesome_app/branch2 folder.

However, achieving wildcard domain support in Caddy Server involved a specific step:— configuring a DNS provider to allow Let’s Encrypt to validate domain ownership and issue wildcard SSL certificates.
One crucial aspect to understand about Caddy Server is that, it doesn’t come prepackaged with built-in DNS plugins.
If you want to leverage DNS providers for tasks like wildcard domain verification, you must compile Caddy with the specific plugins you need. In this blog post, we’ll guide you through step by step process.


To compile caddy with the specific plugins, we need to install xcaddy (it’s a tool for building custom packages of plugin). The best way to install xcaddy is via golang. One of the preferred way to install golang is to do it via asdf

  1. Installing asdf: asdf is command line interface tool, or CLI tool, for managing different runtime versions across multiple programming languages. It is recommended that to download asdf with git, with ubuntu. To get the latest version of asdf, pull latest branch of asdf repository.
    git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.10.2

    asdf required installation method depending upon the shell type. Since ubuntu use bash by default for it’s shell, ~/.bashrc file for configuration and customization. To enable the usage of the asdf command, you will have to add the following line

    echo ". $HOME/.asdf/asdf.sh" >> ~/.bashrc

    Now, we need to make sure changes are applied to current session too.

    source ~/.bashrc
  2. Installing Golang: Next, we’ll integrate Golang into your ubuntu environment by adding the Golang plugin using the asdf command.
    asdf plugin add golang https://github.com/asdf-community/asdf-golang.git

    After adding the plugin, you can install a specific version of Golang using the asdf install command.

    asdf install golang 1.21.1

    Set the installed Golang version as the current version by running

    asdf global golang 1.21.1

    Verify that Golang is correctly installed and set as the current version by running

    go version
  3. Configuring Caddy with xcaddy: With Golang in place, let’s proceed to install xcaddy.
    go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest

    After installing xcaddy, we can move forward and install caddy.

    $ xcaddy build --with github.com/caddy-dns/cloudflare

    This generated caddy file in the folder it, we have to move the caddy binary to /usr/bin.

    sudo mv caddy /usr/bin/

    Now, we need to create caddy user and user group.

    sudo groupadd --system caddy
    sudo useradd --system \
        --gid caddy \
        --create-home \
        --home-dir /var/lib/caddy \
        --shell /usr/sbin/nologin \
        --comment "Caddy web server" \

    Moving on, we need to create systemd service.

    sudo nano /etc/systemd/system/caddy.service

    and add the following content within caddy service file.

    # caddy.service
    # For using Caddy with a config file.
    # Make sure the ExecStart and ExecReload commands are correct
    # for your installation.
    # See https://caddyserver.com/docs/install for instructions.
    # WARNING: This service does not use the --resume flag, so if you
    # use the API to make changes, they will be overwritten by the
    # Caddyfile next time the service is restarted. If you intend to
    # use Caddy's API to configure it, add the --resume flag to the
    # `caddy run` command or use the caddy-api.service file instead.
    After=network.target network-online.target
    ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
    ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile
  4. Caddy server configuration:
    we can now create caddy configuration file at /etc/caddy.
    > sudo mkdir /etc/caddy/
    > sudo nano /etc/caddy/Caddyfile

    you can update the Caddyfile as required.

     *.review.example.com {
        tls {
          dns cloudflare w***********a  //cloudflare api token

    Note:You can follow along this article to create cloudflare API token

    Finally, we need to reload and start caddy.

      > sudo systemctl daemon-reload
      > sudo systemctl enable caddy
      > sudo systemctl start caddy


If you have reached this section, we have come far together. Congratulations!

Thank you for reading !


Write A Comment