Caddy

Caddy

A high-performance web server and reverse proxy written in Go.

Documentation: https://caddyserver.com/docs/
Repository: https://github.com/caddyserver/caddy


Install

Bare-Metal

Run the following commands.

# debian or ubuntu
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
chmod o+r /usr/share/keyrings/caddy-stable-archive-keyring.gpg
chmod o+r /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy

Docker

  1. Create a caddy/compose.yaml file.
services:
  caddy:
    image: caddy:latest
    container_name: caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
        ./srv:/var/www/html
      - caddy_data:/data
      - caddy_config:/config
    command:
      [
        "caddy",
        "run",
        "--config",
        "/etc/caddy/Caddyfile",
        "--adapter",
        "caddyfile",
        "--watch",
      ]

volumes:
  caddy_data:
  caddy_config:
  1. Run the container.
cd caddy
docker compose up -d

Setup Cloudflare

  1. Open https://dash.cloudflare.com/profile/api-tokens.
  2. Click Create Token.
  3. Create two zone permissions.
    1. Zone - Zone - Read
    2. Zone - DNS - Edit
  4. Create at least one zone permission.
    1. Include - Specific zone - <your-domain>
  5. Click Confirm. Then save the api-token securely.

!600

  1. Add Cloudflare snippet to the beginning of Caddyfile.
(cloudflare) { 
    tls {
        dns cloudflare <CLOUDFLARE_API_TOKEN>
        resolvers 1.1.1.1
    }
}
  1. Modify all entries to include Cloudflare snippet.
<domain> {
    import cloudflare
    ...
}

Modify Bare-Metal Install

  1. Install xcaddy.
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/xcaddy/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-xcaddy-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/xcaddy/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-xcaddy.list
sudo apt update
sudo apt install xcaddy
  1. Install Go.
wget https://go.dev/dl/go1.26.1.linux-amd64.tar.gz
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.26.1.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
go version
  1. Build binary with Cloudflare module.
xcaddy build --with github.com/caddy-dns/cloudflare
sudo dpkg-divert --divert /usr/bin/caddy.default --rename /usr/bin/caddy
sudo mv ./caddy /usr/bin/caddy.custom
sudo update-alternatives --install /usr/bin/caddy caddy /usr/bin/caddy.default 10
sudo update-alternatives --install /usr/bin/caddy caddy /usr/bin/caddy.custom 50
sudo systemctl restart caddy

Modify Docker Install

Replace

    image: caddy:latest

With

    build:
      context: .
      dockerfile: Dockerfile

For https challenges, port 80 must be publicly accessible on the server. Otherwise #Setup Cloudflare.

Reverse Proxy

qbittorrent.home.nodusk.me {
    import cloudflare
    reverse_proxy media:8080
}
dusk.home.nodusk.me {
    import cloudflare
    reverse_proxy 192.168.2.101:8006 {
        transport http {
            tls
            tls_insecure_skip_verify
        }
    }
}

Web Server

  1. Clone static website files to server.
git clone <git-repo-url> /var/www/html
# ex. git clone https://gitea.nodusk.me/jay/mercury-publish.git /var/www/html
  1. Edit Caddyfile /etc/caddy/Caddyfile.
:80 {
    root * /var/www/html
    file_server
}
  1. Reload Caddy.
systemctl restart caddy
  1. Open server at http://localhost or http://<server-ip>:80 if hosted remotely.
  2. (optional) Use Pangolin, Caddy, or another reverse proxy to add domain name and remote access.
Powered by Forestry.md