Caddy 是一個 Go 編寫的 Web 服務(wù)器,類似于 Nginx
Caddy 是一個 Go 編寫的 Web 服務(wù)器,類似于 Nginx,Caddy 提供了更加強大的功能,隨著 v2 版本發(fā)布 Caddy 已經(jīng)可以作為中小型站點 Web 服務(wù)器的另一個選擇;相較于 Nginx 來說使用 Caddy 的優(yōu)勢如下:
自動的 HTTPS 證書申請(ACME HTTP/DNS 挑戰(zhàn))
自動證書續(xù)期以及 OCSP stapling 等
更高的安全性包括但不限于 TLS 配置以及內(nèi)存安全等
友好且強大的配置文件支持
支持 API 動態(tài)調(diào)整配置(有木有人可以搞個 Dashboard)
支持 HTTP3(QUIC)
支持動態(tài)后端,例如連接 Consul、作為 k8s ingress 等
后端多種負載策略以及健康檢測等
本身 Go 編寫,高度模塊化的系統(tǒng)方便擴展(CoreDNS 基于 Caddy1 開發(fā))
……
就目前來說,Caddy 對于我個人印象唯一的缺點就是性能沒有 Nginx 高,但是這是個仁者見仁智者見智的問題;相較于提供的這些便利性,在性能可接受的情況下完全有理由切換到 Caddy。
編譯 Caddy2
注意: 在 Caddy1 時代,Caddy 官方發(fā)布的預(yù)編譯二進制文件是不允許進行商業(yè)使用的,Caddy2 以后已經(jīng)全部切換到 Apache 2.0 License,具體請參考 issue#2786。
在默認情況下 Caddy2 官方提供了預(yù)編譯的二進制文件,以及自定義 build 下載頁面,不過對于需要集成一些第三方插件時,我們?nèi)孕璨捎霉俜教峁┑?xcaddy 來進行自行編譯;以下為具體的編譯過程:
1.1、Golang 環(huán)境安裝
本部分編譯環(huán)境默認為 Ubuntu 20.04 系統(tǒng),同時使用 root 用戶,其他環(huán)境請自行調(diào)整相關(guān)目錄以及配置;編譯時自行處理好科學(xué)上網(wǎng)相關(guān)配置,也可以直接用國外 VPS 服務(wù)器編譯。
首先下載 go 語言的 SDK 壓縮包,其他平臺可以從 https://golang.org/dl/ 下載對應(yīng)的壓縮包:
wget https://golang.org/dl/go1.15.6.linux-amd64.tar.gz
下載完成后解壓并配置相關(guān)變量:
# 解壓
tar -zxvf go1.15.6.linux-amd64.tar.gz
# 移動到任意目錄
mkdir -p /opt/devtools
mv go /opt/devtools/go
# 創(chuàng)建 go 相關(guān)目錄
mkdir -p ${HOME}/gopath/{src,bin,pkg}
# 調(diào)整變量配置,將以下變量加入到 shell 初始化配置中
# bash 用戶請編輯 ~/.bashrc
# zsh 用戶請編輯 ~/.zshrc
exportGOROOT= '/opt/devtools/go'
exportGOPATH= " ${HOME}/gopath"
exportGOPROXY= 'https://goproxy.cn'# 如果已經(jīng)解決了科學(xué)上網(wǎng)問題,GOPROXY 變量可以刪除,否則可能會起反作用
exportPATH= " ${GOROOT}/bin: ${GOPATH}/bin: ${PATH}"
# 讓配置生效
# bash 用戶替換成 ~/.basrc
# 重新退出登錄也可以
source~/.zshrc
配置完成后,應(yīng)該在命令行執(zhí)行 go version 并有以下成功返回:
bleem ? ~ go version
go version go1.15.6 linux/amd64
1.2、安裝 xcaddy
按照官方文檔直接命令行執(zhí)行 go get -u github.com/caddyserver/xcaddy/cmd/xcaddy 安裝即可:
bleem ? ~ go get -u github.com/caddyserver/xcaddy/cmd/xcaddy
go: downloading github.com/caddyserver/xcaddy v0.1.7
go: found github.com/caddyserver/xcaddy/cmd/xcaddy ingithub.com/caddyserver/xcaddy v0.1.7
go: downloading github.com/Masterminds/semver/v3 v3.1.0
go: github.com/Masterminds/semver/v3 upgrade => v3.1.1
go: downloading github.com/Masterminds/semver/v3 v3.1.1
.....
安裝完成后應(yīng)當(dāng)在命令行可以直接執(zhí)行 xcaddy 命令:
# xcaddy 并沒有提供完善的命令行支持,所以 `--help` 報錯很正常
bleem ? ~ xcaddy -- help
go: cannot match "all": working directory is not part of a module
2021/01/07 12:15:56 [ERROR] exec[go list -m -f={{if .Replace}}{{.Path}} => {{.Replace}}{{end}} all]: exitstatus 1:
1.3、編譯 Caddy2
編譯之前系統(tǒng)需要安裝 jq 、 curl 、 git 命令,沒有的請使用 apt install -y curl git jq 命令安裝;
自行編譯的目的是增加第三方插件方便使用,其中官方列出的插件可以從 Download 頁面獲取到:
其他插件可以從 GitHub 上尋找或者自行編寫,整理好這些插件列表以后只需要使用 xcaddy 編譯即可:
# 獲取最新版本號,其實直接去 GitHub realse 頁復(fù)制一下就行
# 這里轉(zhuǎn)化為腳本是為了方便自動化
exportversion=$(curl -s "https://api.github.com/repos/caddyserver/caddy/releases/latest"| jq -r .tag_name)
# 使用 xcaddy 編譯
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-webdav
編譯過程日志如下所示,稍等片刻后將會生成編譯好的二進制文件:
編譯成功后可以通過 list-modules 子命令查看被添加的插件是否成功編譯到了 caddy 中:
bleem ? ~ ./caddy_v2.3.0 list-modules
admin.api.load
admin.api.metrics
caddy.adapters.caddyfile
caddy.listeners.tls
caddy.logging.encoders.console
caddy.logging.encoders.filter
caddy.logging.encoders.filter.delete
caddy.logging.encoders.filter.ip_mask
caddy.logging.encoders.formatted
caddy.logging.encoders.json
caddy.logging.encoders.logfmt
caddy.logging.encoders.single_field
caddy.logging.writers.discard
caddy.logging.writers.file
caddy.logging.writers.net
caddy.logging.writers.stderr
caddy.logging.writers.stdout
caddy.storage.file_system
dns.providers.cloudflare
dns.providers.dnspod
dns.providers.duckdns
dns.providers.gandi
dns.providers.route53
exec
http
http.authentication.hashes.bcrypt
http.authentication.hashes.scrypt
http.authentication.providers.http_basic
http.authentication.providers.jwt
......
安裝 Caddy22.1、宿主機安裝
宿主機安裝 Caddy2 需要使用 systemd 進行守護,幸運的是 Caddy2 官方提供了各種平臺的安裝包以及 systemd 配置文件倉庫;目前推薦的方式是直接采用包管理器安裝標(biāo)準(zhǔn)版本的 Caddy2,然后替換自編譯的可執(zhí)行文件:
# 安裝標(biāo)準(zhǔn)版本 Caddy2
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
# 替換二進制文件
systemctl stop caddy
rm -f /usr/bin/caddy
mv ./caddy_v2.3.0 /usr/bin/caddy
2.2、Docker 安裝
Docker 用戶可以通過 Dockerfile 自行編譯 image,目前我編寫了一個基于 xcaddy 的 Dockerfile,如果有其他插件需要集成自行修改重新編譯即可;當(dāng)前 Dockerfile 預(yù)編譯的鏡像已經(jīng)推送到了 Docker Hub 中,鏡像名稱為 mritd/caddy 。
配置 Caddy2
Caddy2 的配置文件核心采用 json,但是 json 可讀性不強,所以官方維護了一個轉(zhuǎn)換器,抽象出稱之為 Caddyfile 的新配置格式;關(guān)于 Caddyfile 的完整語法請查看官方文檔 https://caddyserver.com/docs/caddyfile,本文僅做一些基本使用的樣例。
3.1、配置片段
Caddyfile 支持類似代碼中 function 一樣的配置片段,這些配置片段可以在任意位置被 import ,同時可以接受參數(shù),以下為配置片斷示例:
# 括號內(nèi)為片段名稱,可以自行定義
(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
}
# 在任意位置可以引用此片段從而達到配置復(fù)用
import TLS
3.2、配置模塊化
import 指令除了支持引用配置片段以外,還支持引用外部文件,同時支持通配符,有了這個命令以后我們就可以方便的將配置文件進行模塊化處理:
# 引用外部的 /etc/caddy/*.caddy
import /etc/caddy/*.caddy
3.3、站點配置
針對于站點域名配置,Caddyfile 比較自由化,其格式如下:
地址 {
站點配置
}
關(guān)于這個 “地址” 接受多種格式,以下都為合法的地址格式:
localhost
example.com
:443
http://example.com
localhost:8080
127.0.0.1
[::1]:2015
example.com/foo/*
*.example.com
http://
3.4、環(huán)境變量
Caddyfile 支持直接引用系統(tǒng)環(huán)境變量,通過此功能可以將一些敏感信息從配置文件中剔除:
# 引用環(huán)境變量 GANDI_API_TOKEN
dns gandi { $GANDI_API_TOKEN}
3.5、配置片段參數(shù)支持
針對于配置片段,Caddyfile 還支持類似于函數(shù)代碼的參數(shù)支持,通過參數(shù)支持可以讓外部引用時動態(tài)修改配置信息:
(LOG) {
log{
format json {
time_format "iso8601"
}
# "{args.0}" 引用傳入的第一個參數(shù),此處用于動態(tài)傳入日志文件名稱
output file "{args.0}"{
roll_size 100mb
roll_keep 3
roll_keep_for 7d
}
}
}
# 引用片段
import LOG "/data/logs/mritd.com.log"