Caddy

温馨提醒

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

安装

  • Ubuntu 安装

    1
    2
    3
    4
    5
    
    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 安装

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    # 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

使用

  • 托管网站

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    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

命令行参数

  • 语法

    1
    2
    3
    4
    
    # Caddy 是一个标准的 unix-like 命令,基本用法为:
    # command 是 caddy 的子命令,子命令是必须的,不能省略
    # args 是子命令的参数,可以是0个,也可以是多个
    caddy <command> [<args...>]
  • run 命令

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

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    
    # 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 命令

    1
    
    # start 命令的使用和 run 一样,不同的是 start 会启动一个在后台运行的 caddy,这意味着它不会阻塞终端的使用。
  • stop 命令

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 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 命令。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    
    # 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 命令

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

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    # 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 命令即可

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    
    # 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
            被代理的上游地址,用户看不到这个地址
    1
    2
    3
    4
    5
    6
    
    # 比如有个后端服务 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 原生配置的能力,让我们可以看到真实的配置是什么

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    
    # caddy help adapt
    
    usage:
      caddy adapt --config <path> [--adapter <name>] [--pretty] [--validate]
    
    flags:
      -adapter string
            配置适配器的名字,默认是 caddyfile。其实就是告诉命令,要使用什么样的适配器,把相应的配置转为JSON原生配置
      -config string
            配置文件
      -pretty
            是否美化输出
      -validate
            可以帮助检验下输出,其实并没有真正的运行caddy
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    
    # 比如简单的 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 配置文件,让它更美观

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    # caddy help fmt
    
    usage:
      caddy fmt [--overwrite] [<path>]
    
    
    flags:
      -overwrite
            用格式化后的结果,覆盖你的配置文件
    1
    2
    
    # 整个命令很简单,比如我想用这个命令把我的配置文件美化下,并且把美化的结果覆盖我的配置文件
    caddy fmt --overwrite ~/Desktop/Caddyfile
  • environ 命令

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

    1
    
    caddy help environ
  • hash-password 命令

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

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    
    # 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有效
    1
    2
    3
    
    # 该工具的运行效果
    caddy hash-password  --plaintext 1
    JDJhJDE0JGJLdzc0M0R1bDUzOTNTWGVJSTV4QU9kMGpQNC5WQTBnZ1E4N3FKOVpXUmQ1NEE2dmRzMWR1
  • list-modules 命令

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

    1
    
    caddy list-modules --packages
  • build-info 命令

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

  • trust 命令

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

  • untrust 命令

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

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    # 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 命令基本一致

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    # caddy help validate
    
    usage:
      caddy validate --config <path> [--adapter <name>]
    
    flags:
      -adapter string
            配置适配器的名字,默认是 caddyfile
      -config string
            配置文件的路径
  • version 命令

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

    1
    
    # caddy version

Caddyfile 入门

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

  • 创建一个 Caddyfile 文件

    1
    2
    3
    4
    5
    6
    7
    
    vim Caddyfile
    localhost
    
    这是最简单的 Caddyfile 配置,现在使用 caddy start 命令启动即可,如果 Caddyfile 在当前目录下,则不用指定配置文件,否则需要使用 --config 参数指定配置文件
    caddy start --config /data/caddy/Caddyfile
    
    默认会启用 https,所有会监听443端口
  • Hello World

    1
    2
    3
    4
    5
    
    如果现在访问 localhost,只能看到一个空白页面,现在我们让它显示“Hello World”
    vim Caddyfile
    localhost
    respond "Hello World"
    现在运行 caddy start,通过浏览器访问 localhost,就能看到 “Hello World”
  • 配置多个 web 服务

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    #既然 caddy 是一个 web 服务器,那么就不止可以托管一个 web 站点,如果要托管多个,需要怎么做呢?
    vim Caddyfile
    localhost {
        respond "Hello World"
    }
    localhost:1234 {
        respond "Hello World !!!"
    }
    
    如上示例,定义了两个站点,一个是 localhost,一个是 localhost:1234,执行 caddy start 启动,两个地址都可以访问。
    从上面的配置可以看到,要配置多个站点,就需要使用 {} 把每个站点括起来,而只有一个站点的时候,就不需要了。
  • 静态文件服务

    1
    2
    3
    4
    5
    
    vim Caddyfile
    www.xx.com {
        root * /var/www/website
        file_server
    }

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
vim Caddyfile

www.example.com:80				# 第一行必须是网站的地址
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
}
  • 反向代理

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    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:8080/app/websocket
      proxy /app/websocket 127.0.0.1:8080 {
        websocket
      }
    }
  • 负载均衡配置

    1
    2
    3
    4
    5
    
    proxy / web1.local:80 web2.local:90 web3.local:100 { 
      policy round_robin 
    }
    
    # 用反向代理命令proxy 将请求循环转发到 80、90、100 三个后端服务,通过 policy 命令控制策略为 round_robin,以循环方式选择后端服务