Caddy的简单用法

Caddy 是一个强大的、企业级的、开源的 web 服务器,使用 go 语言编写,并且可以自动配置 管理HTTPS

安装

Ubuntu 安装

代码语言:javascript
复制
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo apt-key add -
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy

RHEL 安装

代码语言:javascript
复制
# RHEL 7 安装
yum install yum-plugin-copr
yum copr enable @caddy/caddy
yum install caddy

RHEL 8 安装

dnf install 'dnf-command(copr)'
dnf copr enable @caddy/caddy
dnf install caddy

使用

托管网站

代码语言:javascript
复制
caddy file-server --root ~/mysite

file-server:是 caddy 子命令,表示要启动一个文件服务的意思

--root:表示以哪个目录作为文件服务的根目录,也就是网站根目录

现在可以通过 localhost 来访问网站

caddy file-server --root ~/mysite --domain localhost

现在可以通过域名 www.xx.com 来访问网站

caddy file-server --root ~/mysite --domain www.xx.com

命令行参数

语法

代码语言:javascript
复制
# Caddy 是一个标准的 unix-like 命令,基本用法为:

command 是 caddy 的子命令,子命令是必须的,不能省略

args 是子命令的参数,可以是0个,也可以是多个

caddy <command> [<args...>]

run 命令

run 命令会运行一个前台 caddy 进程,直到用 ctrl+c 或关闭终端退出

代码语言:javascript
复制
# caddy help run

usage:
caddy run [--config <path> [--adapter <name>]] [--envfile <path>] [--environ] [--resume] [--watch] [--pidfile <fil>]

flags:
-adapter string
如果你使用的配置文件不是以Caddyfile开头的,那么要使用这个标记来指定,比如-adapter caddyfile。
-config string
启动Caddy使用的配置文件
-envfile string
从指定的文件加载环境变量,环境变量的格式为KEY=VALUE
-environ
打印环境变量
-pidfile string
这个大家都知道,用于存放PID的文件
-pingback string
启动成功的信息要回显到pingback指定的ip:port上,这里是通过tcp拨号发送回显信息的。
-resume
这个挺有意思,会使用最近一次自动保存的配置,这对于恢复一个caddy非常有用。这里需要注意的是,当使用这个标记的时候,通过config标记指定的配置就不再生效了。
-watch
这个其实就是在检测到你的配置文件发生变化的时候,自动重新加载配置,这个不要在生产环境使用,自己开发环境用用就得了。

示例1:加载当前目录下名称为Caddyfile的配置文件启动caddy,并且监控到配置文件改变的时候,自动重新加载配置。

caddy run -config Caddyfile -watch

示例2:和示例1相比,增加了一个pid文件

caddy run -config Caddyfile -watch -pidfile /var/run/flysnow.pid

start 命令

代码语言:javascript
复制
# start 命令的使用和 run 一样,不同的是 start 会启动一个在后台运行的 caddy,这意味着它不会阻塞终端的使用。

stop 命令

start 命令对应的是 stop 命令,需要使用 stop 命令通知后台正在运行的 caddy

代码语言:javascript
复制
# caddy help stop

usage:
caddy stop

flags:
-address string
The address to use to reach the admin API endpoint, if not the default

如果 start 是使用默认的 localhost:2022 管理地址启动的,那么直接使用 stop 命令就可以优雅的停止 caddy,如果不是默认的,那么需要使用 -address 来指定管理地址。
caddy stop -address localhost:2022

提示

caddy 在启动后,不仅可以通过终端命令来管理它,还可以通过 API,这组管理 API 默认的地址就是 localhost:2022,所以当 caddy 启动后,在浏览器中输入这个地址,就可以看到相应的配置了。

reload 命令

通过 start 启动的 caddy 是不能轻易停止的,因为这会导致网络服务不可用,但又想修改配置文件,就可以使用 reload 命令。

代码语言:javascript
复制
# caddy help reload

usage:
caddy reload --config <path> [--adapter <name>] [--address <interface>]

flags:
-adapter string
Name of config adapter to apply
-address string
Address of the administration listener, if different from config
-config string
Configuration file (required)
-force
Force config reload, even if it is the same

它和 run 命令基本一致,参数也差不多,可以参考 run 命令的使用。注意,这里的 address 参数和 stop 命令中的 address 是一样的,都是管理 API 的地址。

file-server 命令

这个命令可以启动一个文件服务,比如托管一个静态网站、把你的文件夹共享在网站上。

代码语言:javascript
复制
# caddy help file-server

usage:
caddy file-server [--domain <example.com>] [--root <path>] [--listen <addr>] [--browse] [--access-log]

flags:
-access-log
启用访问日志
-browse
启用目录浏览
-domain string
指定一个域名
-listen string
监听的地址,http默认是:80,https默认是:443
-root string
要托管的文件服务的根目录
-templates
启用模板渲染

reverse-proxy 命令

在 caddy 中,配置一个反向代理非常简单,使用 reverse-proxy 命令即可

代码语言:javascript
复制
# caddy help reverse-proxy

usage:
caddy reverse-proxy [--from <addr>] [--to <addr>] [--change-host-header]

flags:
-change-host-header
变更主机头,从传入的值变为上游的值
-from string
用户访问的地址,默认是localhost
-insecure
禁用TLS
-to string
被代理的上游地址,用户看不到这个地址

代码语言:javascript
复制
# 比如有个后端服务 127.0.0.1:9000,要代理到 localhost,命令如下
caddy reverse-proxy --to 127.0.0.1:9000
现在访问 localhost,其实就是访问的 127.0.0.1:9000 这个后端服务

如果想换个端口访问,比如 localhost:2022,只需要运行如下命令

caddy reverse-proxy --from :2022 --to 127.0.0.1:9000

adapt 命令

caddy 是有自己的配置文件的,叫 Caddyfile,这是一种可读性、书写性非常强的配置文件,但它并不是 caddy 的原生配置文件,caddy 的原生配置文件是 json 的,但是非常复杂。
adapt 命令就是给我们提供了 Caddyfile 转 json 原生配置的能力,让我们可以看到真实的配置是什么

代码语言:javascript
复制
# caddy help adapt

usage:
caddy adapt --config <path> [--adapter <name>] [--pretty] [--validate]

flags:
-adapter string
配置适配器的名字,默认是 caddyfile。其实就是告诉命令,要使用什么样的适配器,把相应的配置转为JSON原生配置
-config string
配置文件
-pretty
是否美化输出
-validate
可以帮助检验下输出,其实并没有真正的运行caddy

代码语言:javascript
复制
# 比如简单的 Caddyfile,只有一行 localhost,使用 adapt 命令转为 json 原生配置的结果如下:
caddy adapt --config ~/Desktop/Caddyfile --pretty
{
"apps": {
"http": {
"servers": {
"srv0": {
"listen": [
":443"
],
"routes": [
{
"match": [
{
"host": [
"localhost"
]
}
],
"terminal": true
}
]
}
}
}
}
}

fmt 命令

这是 caddy 提供的一个辅助工具,可以帮你格式化你的 Caddyfile 配置文件,让它更美观

代码语言:javascript
复制
# caddy help fmt

usage:
caddy fmt [--overwrite] [<path>]

flags:
-overwrite
用格式化后的结果,覆盖你的配置文件

代码语言:javascript
复制
# 整个命令很简单,比如我想用这个命令把我的配置文件美化下,并且把美化的结果覆盖我的配置文件
caddy fmt --overwrite ~/Desktop/Caddyfile

environ 命令

打印 caddy 的环境变量,你可以看到很多关于 caddy 自身和你的系统环境的信息,这对于调试 caddy 非常有用,比如启动不了,路径错误等等。

代码语言:javascript
复制
caddy help environ

hash-password 命令

一个自带的密码 hash 工具,主要用来为配置文件的授权提供 hash 过的密码,因为不能配置明文密码

代码语言:javascript
复制
# caddy help hash-password

usage:
caddy hash-password [--algorithm <name>] [--salt <string>] [--plaintext <password>]

flags:
-algorithm string
Hash算法,支持scrypt和bcrypt两种,默认是bcrypt
-plaintext string
要Hash的明文密码
-salt string
加点盐,仅当Hash算法是scrypt有效

代码语言:javascript
复制
# 该工具的运行效果
caddy hash-password --plaintext 1
JDJhJDE0JGJLdzc0M0R1bDUzOTNTWGVJSTV4QU9kMGpQNC5WQTBnZ1E4N3FKOVpXUmQ1NEE2dmRzMWR1

list-modules 命令

caddy 是支持模块的,而且我们可以开发自己的模块,该命令可以列出 caddy 当前已经安装的模块

代码语言:javascript
复制
caddy list-modules --packages

build-info 命令

打印 caddy 的构建信息,主要是 Go Module 的依赖信息,包括包名、版本等

trust 命令

安装一个根证书到本地信任存储中,可能会需要密码才能安装,主要用于开发环境,大部分情况下,该命令是用不到的,因为 caddy 启动的时候会自动安装证书

untrust 命令

从本地存储中卸载一个根证书,也用于开发环境,和上面的 trust 命令是对应的

代码语言:javascript
复制
# caddy help untrust
usage:
caddy untrust [--ca <id> | --cert <path>]

flags:
-ca string
要卸载CA证书的ID,默认为local
-cert string
要卸载CA证书的路径

upgrade 命令

这个是升级 caddy 的命令,它会下载最新的二进制文件,然后把本地的给替换掉,这个过程并不会停止 caddy 服务,所以不用担心,它仅仅是替换你的 caddy 文件。
为了保险起见,原来的二进制文件要先备份下。

validate 命令

这是一个验证 Caddyfile 配置文件的命令,它会模拟启动 caddy,但是并不会真正的启动,验证的过程中,遇到问题,会在控制台输出,它的使用和 adapt 命令基本一致

代码语言:javascript
复制
# caddy help validate

usage:
caddy validate --config <path> [--adapter <name>]

flags:
-adapter string
配置适配器的名字,默认是 caddyfile
-config string
配置文件的路径

version 命令

最简单的一个命令,打印出 caddy 的版本

代码语言:javascript
复制
# caddy version

Caddyfile 入门

Caddyfile 是 caddy 的配置文件,类似 Nginx 的 config,它是一个普通的文本文件,没有扩展名。

创建一个 Caddyfile 文件

代码语言:javascript
复制
vim Caddyfile
localhost

这是最简单的 Caddyfile 配置,现在使用 caddy start 命令启动即可,如果 Caddyfile 在当前目录下,则不用指定配置文件,否则需要使用 --config 参数指定配置文件
caddy start --config /data/caddy/Caddyfile

默认会启用 https,所有会监听443端口

Hello World

代码语言:javascript
复制
如果现在访问 localhost,只能看到一个空白页面,现在我们让它显示“Hello World”
vim Caddyfile
localhost
respond "Hello World"
现在运行 caddy start,通过浏览器访问 localhost,就能看到 “Hello World”

配置多个 web 服务

代码语言:javascript
复制
#既然 caddy 是一个 web 服务器,那么就不止可以托管一个 web 站点,如果要托管多个,需要怎么做呢?
vim Caddyfile
localhost {
respond "Hello World"
}
localhost:1234 {
respond "Hello World !!!"
}

如上示例,定义了两个站点,一个是 localhost,一个是 localhost:1234,执行 caddy start 启动,两个地址都可以访问。
从上面的配置可以看到,要配置多个站点,就需要使用 {} 把每个站点括起来,而只有一个站点的时候,就不需要了。

静态文件服务

代码语言:javascript
复制
vim Caddyfile
www.xx.com {
root * /var/www/website
file_server
}

示例

代码语言:javascript
复制
vim Caddyfile

www.example.com # 第一行必须是网站的地址
gzip # 表示开启 gzip 压缩功能
log /var/log/caddy/access.log # 为网站开启 log 功能
rot /var/www/website # 指定网站的根目录
tls xx@xx.com # 为网站开启 https 并自动申请证书,后面的 E-Mail 参数是告知 CA 申请人的邮箱,caddy 会默认使用 Let's encrypt 申请证书并续约,tls 也可以使用路径给出的证书 tls /etc/ssl/cert.pem /etc/ssl/key.pem

多站点配置

vim Caddyfile
example.com:80 {
gzip
log /var/log/caddy/access.log
root /var/www/website
tls /etc/ssl/cert.pem /etc/ssl/key.pem
}
example1.com:8080 {
gzip
log /var/log/caddy/access1.log
root /var/www/website1
tls /etc/ssl/cert.pem /etc/ssl/key.pem
}

反向代理

代码语言:javascript
复制
http://www.example.com {

HTTP 代理配置

此时访问 example.com,实际访问的是 127.0.0.1:8080/app/ 的内容

proxy / 127.0.0.1:8080/app/

WebSocket 代理配置

客户端请求的 wss://example.com/app/websocket, 实际为 wss://127.0.0.1/app/websocket

proxy /app/websocket 127.0.0.1:8080 {
websocket
}
}

负载均衡配置

代码语言:javascript
复制
proxy / web1.local:80 web2.local:90 web3.local:100 {
policy round_robin
}

用反向代理命令proxy 将请求循环转发到 80、90、100 三个后端服务,通过 policy 命令控制策略为 round_robin,以循环方式选择后端服务