# xcaddy

xcaddy is awesome for setting up your LetsEncrypt certs with a DNS challenge (handy if you don't often - or ever - want to expose port 80/443 to the www)

# Install xcaddy

# Get regular caddy first so xcaddy compiles right
wget https://github.com/caddyserver/caddy/releases/download/v2.11.0-beta.1/caddy_2.11.0-beta.1_linux_amd64.tar.gz
tar -xzvf caddy_2.11.0-beta.1_linux_amd64.tar.gz

# Then download/extract xcaddy
wget https://github.com/caddyserver/xcaddy/releases/download/v0.4.5/xcaddy_0.4.5_linux_amd64.tar.gz
tar -xzvf xcaddy_0.4.5_linux_amd64.tar.gz

# Download/install go
sudo apt install golang -y

# Build the custom xcaddy
./xcaddy build \
  --with github.com/mholt/caddy-dynamicdns \
  --with github.com/caddy-dns/cloudflare

# Get a CloudFlare API token

Do that here.

# Adjust DNS zone

For the domain you want xcaddy to be able to edit:

  • Grant Zone > DNS > Edit permissions
  • Grant Zone > Zone > Read permissions

# Create the Caddy file

Here's an example:

some.cool.site.com {
    tls {
        dns cloudflare {env.CF_API_TOKEN}
    }

    reverse_proxy reverse_proxy http://127.0.0.1:8000

    log {
        output file /var/log/caddy/yoursiteslog.log
    }
}

# Run xcaddy

CF_API_TOKEN=xxx sudo --preserve-env=CF_API_TOKEN ./caddy run --config ./Caddyfile

# Troubleshooting

# Upgrade golang

When I was trying to compile xcaddy, I got complaints about not being able to compile the github.com/mholt/caddy-dynamicdns component. The fix was:

# 1) grab latest 1.25.x (adjust version if you want)
cd /tmp
wget https://go.dev/dl/go1.25.5.linux-amd64.tar.gz

# 2) install to /usr/local/go
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.25.5.linux-amd64.tar.gz

# 3) ensure your shell uses it
echo 'export PATH=/usr/local/go/bin:$PATH' >> ~/.profile
source ~/.profile

go version