Prepare LXC

  • Unprivileged container
  • Ubuntu 24.04

Create a user with name caddy, we will run caddy with this user.

  • For Ubuntu LXC templates, by default, there won’t be a 1000:1000 user:group pair be created.
  • Ubuntu LXC template by default will throw you in a shell with ‘root’ user.
groupadd -g 1000 caddy
useradd -u 1000 -g 1000 -m -s /bin/bash caddy

There is no need to set password for this user.

Download Caddy

I’m using cloudflare as my domain provider, so this note will focus on CloudFlare.

  • Donwload the caddy binary with CloudFlare module baked in
    • https://caddyserver.com/download
      • Change the ‘platform’ to match your hardware and OS.
      • Make sure you’ve selected ‘dns-provider/cloudflare’ module
    • Download with curl -o caddy "<download_url>".

Then, we just move caddy binary to correct location:

mv caddy /usr/local/bin/
chmod a+x /usr/local/bin/caddy

Verify ‘cloudflare’ module is there:

caddy list-modules
 
# my output:
# dns.providers.cloudflare
 
#   Non-standard modules: 1

Config Caddyfile

Usually we put it in /etc/caddy/Caddyfile

awesome.dev, *.awesome.dev {
    # Configure Automatic HTTPS with a wildcard certificate
    # using the DNS-01 challenge.
    tls {
        dns cloudflare {env.CLOUDFLARE_API_TOKEN}
    }

    # This is where you define how to handle the traffic.
    # Caddy can route requests based on the subdomain used.
    @blog host blog.awesome.dev
    handle @blog {
        reverse_proxy 192.168.217.12:3456
    }

    # Fallback for any other subdomain or the main domain
    handle {
        reverse_proxy localhost:80
    }
}

WARNING

The blank space between @blog and { must be there. I.e. handle @blog{ is invalid, it must be handle @blog {.

The env.CLOUDFLARE_API_TOKEN will be obtained from cloudflare and passed in via systemd config.

CloudFlare API Token

  1. Log in to your Cloudflare dashboard.
  2. Go to My Profile > API Tokens.
  3. Click Create Token.
  4. Find the “Edit zone DNS” template and click Use template.
  5. Configure the token:
  • Token name: Give it a descriptive name, like “Caddy DNS-01 Token”.
  • Permissions: The “Zone: DNS: Edit” permission should already be selected. This is what Caddy needs.
  • Zone Resources: Select “Specific zone” and choose awesome.dev from the dropdown list. This is crucial for security, as it limits the token’s power to only that specific domain.
  1. Click Continue to summary, then click Create Token.
  2. Copy the generated token immediately! Cloudflare will only show it to you once. Store it securely.

Systemd

Config Location: /etc/systemd/system/caddy.service:

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

For debugging you can use to print all env variables (--environ):

ExecStart=/usr/local/bin/caddy run --environ --config /etc/caddy/Caddyfile

Then, to load it:

systemctl daemon-reload # <- this will refresh the actual configs in-use by systemd
 
systemctl enable caddy.service
 
systemctl start caddy.service