Why Caddy2 Is a Powerful Alternative to Nginx: Installation & Configuration Guide
This article introduces Caddy, a Go‑based web server, compares its advantages over Nginx, and provides step‑by‑step instructions for installing Go, compiling Caddy2 with plugins via xcaddy, configuring Caddyfile snippets, setting up TLS, HTTP/3, and deploying Caddy on both host and Docker environments.
Caddy Overview
Caddy is a Go‑written web server similar to Nginx. Since the release of version 2, it has become a viable alternative for small‑to‑medium sites, offering features such as automatic HTTPS, built‑in TLS configuration, modular architecture, and support for HTTP/3.
Automatic HTTPS certificate issuance (ACME HTTP/DNS challenges)
Automatic certificate renewal and OCSP stapling
Enhanced security including TLS defaults and memory safety
Friendly and powerful configuration file support
API for dynamic configuration adjustments
HTTP/3 (QUIC) support
Dynamic back‑ends (e.g., Consul, Kubernetes ingress)
Various load‑balancing strategies and health checks
Highly modular Go codebase, easy to extend (CoreDNS built on Caddy 1)
The main drawback is that its raw performance is slightly lower than Nginx, but the convenience often outweighs this difference.
Compiling Caddy 2
Go environment installation (Ubuntu 20.04 example)
wget https://golang.org/dl/go1.15.6.linux-amd64.tar.gzExtract and set up environment variables:
# Extract
tar -zxvf go1.15.6.linux-amd64.tar.gz
# Move to a directory
mkdir -p /opt/devtools
mv go /opt/devtools/go
# Create GOPATH directories
mkdir -p ${HOME}/gopath/{src,bin,pkg}
# Export 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 installation:
go version
go version go1.15.6 linux/amd64Install xcaddy
go get -u github.com/caddyserver/xcaddy/cmd/xcaddyAfter installation the xcaddy command is available.
Compile Caddy 2 with plugins
# Install dependencies
apt install -y curl git jq
# Get latest Caddy version tag
export version=$(curl -s "https://api.github.com/repos/caddyserver/caddy/releases/latest" | jq -r .tag_name)
# Build with desired 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-webdavThe build logs are shown below (truncated for brevity).
After compilation, verify included modules:
./caddy_v2.3.0 list-modules
admin.api.load
admin.api.metrics
caddy.adapters.caddyfile
caddy.listeners.tls
... (additional modules)Installing Caddy 2
Host installation (systemd)
# Install 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 binary with custom build
systemctl stop caddy
sudo rm -f /usr/bin/caddy
sudo mv ./caddy_v2.3.0 /usr/bin/caddyDocker installation
Build a custom Docker image using a Dockerfile based on xcaddy. The pre‑built image mritd/caddy is available on Docker Hub.
Configuring Caddy 2
Caddyfile is the recommended, human‑readable configuration format that the server converts to JSON internally.
Configuration snippets
# Define a reusable TLS snippet
(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
}
# Import the snippet elsewhere
import TLSModules can also be imported via glob patterns, e.g. import /etc/caddy/*.caddy.
Site configuration example
# Simple site block
example.com {
reverse_proxy localhost:8080
log {
output file /var/log/caddy.log {
roll_size 100mb
roll_keep 3
roll_keep_for 7d
}
}
import TLS
import HSTS
}Environment variables can be referenced directly, for instance dns gandi {$GANDI_API_TOKEN} for DNS‑01 challenges.
Automatic certificate acquisition
tls {
dns gandi {env.GANDI_API_TOKEN}
}After configuring, Caddy will request certificates via ACME. DNS challenges require the appropriate DNS plugin.
Running and Reloading
Start the server with systemctl start caddy. After modifying the Caddyfile, reload without downtime using systemctl reload caddy. If the configuration contains errors, the reload fails but the running instance continues serving.
Conclusion
Caddy’s modular design, built‑in TLS automation, HTTP/3 support, and easy‑to‑write Caddyfile make it a compelling choice over traditional Nginx for modern web services, especially when the slight performance trade‑off is acceptable.
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.
Open Source Linux
Focused on sharing Linux/Unix content, covering fundamentals, system development, network programming, automation/operations, cloud computing, and related professional knowledge.
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.
