Build and Deploy a Custom Caddy 2 Server with Plugins, Docker, and Systemd
This guide introduces Caddy 2, explains its advantages over Nginx, walks through compiling it with xcaddy and third‑party plugins, shows host and Docker installation methods, and demonstrates modular Caddyfile configuration, TLS automation, and service management with systemd.
Overview
Caddy is a Go‑based web server that provides automatic HTTPS via ACME, built‑in TLS with strong defaults, a human‑readable configuration language (Caddyfile), an API for dynamic updates, HTTP/3 (QUIC) support, and a modular plugin architecture.
Automatic ACME HTTP/DNS certificate issuance and renewal with OCSP stapling
Memory‑safe Go codebase and sensible TLS defaults
Simple, declarative configuration files (Caddyfile) that are internally converted to JSON
Dynamic back‑ends (Consul, Kubernetes ingress, etc.) and multiple load‑balancing/health‑check strategies
Extensible via plugins compiled with
xcaddyCompiling Caddy 2
1. Install Go (Ubuntu 20.04 example)
wget https://golang.org/dl/go1.15.6.linux-amd64.tar.gz
# Extract
tar -zxvf go1.15.6.linux-amd64.tar.gz
# Move to a permanent location
mkdir -p /opt/devtools
mv go /opt/devtools/go
# Create GOPATH directories
mkdir -p ${HOME}/gopath/{src,bin,pkg}
# Export environment variables (add to ~/.bashrc or ~/.zshrc)
export GOROOT='/opt/devtools/go'
export GOPATH="${HOME}/gopath"
export GOPROXY='https://goproxy.cn'
export PATH="${GOROOT}/bin:${GOPATH}/bin:${PATH}"
source ~/.zshrcVerify the installation:
go version
# Expected output: go version go1.15.6 linux/amd642. Install xcaddy
go get -u github.com/caddyserver/xcaddy/cmd/xcaddyAfter installation the xcaddy command should be available in ${GOPATH}/bin.
3. Build Caddy with desired plugins
# Install helper tools
apt install -y curl git jq
# Retrieve the latest release tag from GitHub
export version=$(curl -s "https://api.github.com/repos/caddyserver/caddy/releases/latest" | jq -r .tag_name)
# Build Caddy with selected plugins
xcaddy build ${version} --output ./caddy_${version} \
--with github.com/abiosoft/caddy-exec \
--with github.com/caddy-dns/cloudflare \
--with github.com/caddy-dns/dnspod \
--with github.com/caddy-dns/duckdns \
--with github.com/caddy-dns/gandi \
--with github.com/caddy-dns/route53 \
--with github.com/greenpau/caddy-auth-jwt \
--with github.com/greenpau/caddy-auth-portal \
--with github.com/greenpau/caddy-trace \
--with github.com/hairyhenderson/caddy-teapot-module \
--with github.com/kirsch33/realip \
--with github.com/porech/caddy-maxmind-geolocation \
--with github.com/caddyserver/format-encoder \
--with github.com/mholt/caddy-webdavAfter a short build the binary caddy_${version} is produced.
Verify compiled modules:
./caddy_${version} list-modules
# Output includes admin.api, dns.providers.cloudflare, http, tls, etc.Installing Caddy 2
Systemd installation (Debian/Ubuntu)
# Add Caddy repository and install the official package
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/cfg/gpg/gpg.155B6D79CA56EA34.key' | sudo apt-key add -
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/cfg/setup/config.deb.txt?distro=debian&version=any-version' | sudo tee -a /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy
# Replace the binary with the custom build
systemctl stop caddy
sudo rm -f /usr/bin/caddy
sudo mv ./caddy_${version} /usr/bin/caddyDocker installation
Build a Docker image from a Dockerfile that runs xcaddy build … with the required plugins, then push the image to a registry (e.g., mritd/caddy).
Configuring Caddy 2
Caddyfile is a concise, human‑readable configuration format that the server translates to JSON. The full syntax is documented at https://caddyserver.com/docs/caddyfile (refer to the URL as plain text).
Configuration snippets (reusable blocks)
# TLS snippet – defines protocols and cipher suites
(TLS) {
protocols tls1.2 tls1.3
ciphers TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 \
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 \
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
}
# Log snippet – parameterized log file path
(LOG) {
log {
output file "{args.0}" {
roll_size 100mb
roll_keep 3
roll_keep_for 7d
}
}
}Modular imports
# Import all Caddyfiles in a directory
import /etc/caddy/*.caddySite block example with automatic HTTPS, DNS‑01 challenge, reverse proxy and log import
example.com {
# Automatic HTTPS using DNS‑01 via Gandi (token from environment variable)
tls {
dns gandi {env.GANDI_API_TOKEN}
}
# Import the log snippet, passing the log file path as argument
import LOG "/var/log/caddy/example.com.log"
# Simple reverse proxy to an upstream service
reverse_proxy localhost:8080
}Environment variables can be referenced directly with {env.VAR_NAME} (or {$VAR_NAME}) to keep secrets out of the file.
Running and Reloading
Start the service:
systemctl start caddyAfter any configuration change, reload without stopping the process:
systemctl reload caddyIf the new Caddyfile contains errors, the reload fails and the existing instance continues serving traffic.
Example Directory Layout
caddy/
├── Caddyfile # Global snippets and imports
├── example.com.caddy # Site‑specific configuration
└── other-site.caddy # Additional site configurationsSummary
Caddy 2 offers a modern, feature‑rich alternative to traditional web servers. With automatic TLS, HTTP/3, a flexible plugin system, and a concise Caddyfile syntax, it simplifies the deployment of secure web services. The steps above cover setting up the Go toolchain, compiling a custom Caddy binary with plugins, installing it via systemd or Docker, and configuring common scenarios such as TLS via DNS‑01, logging, and reverse proxying.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
