您当前的位置:首页 > 计算机 > 服务器 > 网络服务

抛弃 nginx,转用 caddy

时间:09-06来源:作者:点击数:

之所以不用 nginx 了,是因为它配置和使用真的没有 caddy 简单方便。

安装

官网为: caddyserver 商业网/

mac 上安装

$ brew install caddy
$ brew services start caddy

Debian 安装

$ sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
$ curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
$ 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

其他架构可以前往官网查看安装命令

基础命令

  • caddy 列出可用子命令,或使用 caddy help 查看说明
  • caddy run 在当前目录下运行一个前台 caddy 进程(默认网站根路径为当前目录,且读取当前目录配置文件),使用 Ctrl + c 停止
  • caddy start 在后台运行 caddy,执行 caddy stop 停止
  • caddy fmt 格式化配置文件
  • caddy reload 重载配置

配置文件

Caddy 的配置文件有两种,一种是 JSON 格式的(字段太多,不想用),一种是 Caddyfile 文件,里面配置很简单

基础配置文件

新建文件 Caddyfile 输入内容

PLAINTEXT

:8080

respond "Hello, caddy!"
  • 第一行是地址
    • 完整的 https://example.com:1234/api/ 协议 主机名 端口号 路径
    • 可以直接写主机名,例如 localhost(省略端口 80)
    • 端口号,例如 localhost:8080,其中 localhost 可以省略,直接写成 :8080
    • 解析到服务器的域名,例如 example.com(省略端口 443),这里是域名的话会自动为域名申请 SSL 证书
    • IP 地址,例如 127.0.0.1
    • http:// 省略了服务器 IP
    • 通配符,例如 *.example.comexample.com/api/*
  • 下面是对应域名/网站的配置,这里是回应了一个字符串

现在在这个配置文件目录下执行 caddy run 就会默认使用这个配置文件启动,接着访问 http://localhost:8080 就能看到网页了

配置文件除了上面那样写,还可以在域名后面跟 {},把这个网站的配置包裹住,尤其是同时写多个网站的配置的时候(多个网站的时候地址必须唯一,不能多次指向同一个地址)

示例:

PLAINTEXT

# Caddyfile 配置文件中,这个是注释,和 Nginx 配置文件一样
test.vonne.me {
  respond "Welcome!"
}

:8080, :8090 {
  respond "Hello"
}

localhost {
  respond "80"
}

我已经将 test.vonne.me 解析到了服务器的 IP

执行 caddy run 将会自动为域名 test.vonne.me 申请 SSL 证书,之后就可以直接访问 https://test.vonne.me 了

注意:如果服务器已经有其他 web 服务了,例如 Nginx,有可能 80 和 443 端口都被占用了,这个时候需要先停止其他 web 服务,再重新执行 caddy run 命令

我觉得自动申请证书简单配置就能使用,这两点就已经足够让我替换掉 Nginx 了

文件服务器

通过上面的示例,已经知道怎么配置它了,但是我们需要的是让他能够处理网页,而不是单纯返回一个字符串

我们可以先尝试通过运行命令的方式启动一个文件服务器,它可以托管一个静态网站、把你的文件共享在网络上

SH

$ caddy file-server --root ~/mysite --listen :2015 --browse

可以不带参数,就默认以当前目录为站点,但可能监听不了低端口

  • --root 指定文件夹作为网站根目录
  • --listen 绑定其他端口号,使用域名的话,可以使用 --domain example.com 替代 --listen :2015
  • --browse 没有索引文件也可以显示文件列表

如果使用配置文件的话,例如新建 /etc/caddy/Caddyfile,内容为

PLAINTEXT

localhost:2015 {
  root * ~/mysite
  file_server browse
}

需要在其他目录运行,则可以添加 --config 参数指定配置文件路径,例如 caddy run --config /etc/caddy/Caddyfile 这样就会以这个配置文件启动一个文件服务器

模版页面

如果在 HTML 中使用了模版语法({{}})那么就可以在配置文件中添加 templates,例如 HTML 文件中使用了

HTML

Page loaded at: {{now | date "Mon Jan 2 15:04:05 MST 2006"}}

那么配置文件可以写成

PLAINTEXT

localhost:2015 {
  root * ~/mysite
  templates
  file_server
}

如果是使用的命令,则多加一个 --templates 参数

启用 Gzip 和 Zstandard 支持

PLAINTEXT

localhost:2015 {
  root * ~/mysite
  encode zstd gzip
  templates
  file_server
}

重定向

例如把 www 域名重定向到 @

PLAINTEXT

www.domain.com {
  redir https://domain.com{uri} permanent
}

domain.com {
  root * /data/www
  file_server
}

这里 {} 包裹的是占位符,{uri} 等价于 {http.request.uri},是通用资源符

加上了 permanent 就是 301 永久重定向

反向代理

使用命令

SH

$ caddy reverse-proxy --from :2080 --to :9000
  • --from 用户访问的地址,默认是 localhost
  • --to 被代理的地址

省略 --from,就是默认的 localhost,如果 http 就是 80 端口,https 就是 443 端口

SH

$ caddy reverse-proxy --to :9000

其他域名

SH

$ caddy reverse-proxy --from example.com --to https://example.com:9000

如果两个主机名不同,则需要加参数

SH

$ caddy reverse-proxy --from example.com --to https://localhost:9000 --change-host-header

使用的 Caddyfile 配置

PLAINTEXT

localhost

reverse_proxy :9000

如果反代的只是某个路径下的,就可以使用匹配器令牌,例如只匹配 api/ 下的

PLAINTEXT

yourdomain.com {
    reverse_proxy /api/* 127.0.0.1:9000
}

除了上面这种,还可以这样写

PLAINTEXT

yourdomain.com {
  reverse_proxy /api/* {
    to 127.0.0.1:9000
  }
}

负载均衡

例如

PLAINTEXT

yourdomain.com {
  reverse_proxy /api/* {
    to 127.0.0.1:9000 127.0.0.1:9001 127.0.0.1:9002
  }
}

负载均衡策略(调度方式)默认是随机的,我们可以通过 lb_policy 来指定不同的负载均衡策略

  1. first:选取第一个可用的上游
  2. random:随机选取一个可用的上游
  3. least_conn:选取当前请求数最少的上游,这个比较适合长连接的场景
  4. ip_hash:根据IP的Hash值选取一个固定的上游
  5. random_choose :随机选取2个或者更多个上游,然后再从中选择负载最小的,n通常为2
  6. header:这个是根据请求头的Hash选取一个固定的上游,和 ip_hash 很像,只不过它是根据指定的请求头的值进行Hash,然后选取上游的。所以这里的用法是 header <request_header_name> ,要指定一个请求头。
  7. uri_hash:这个也和 ip_hash 很像,只不过它是根据请求的URI进行Hash,然后选取一个上游。
  8. round_robin:这个策略是循环迭代,挨个使用一个个上游,每个上游都可以被用到,轮着来。
  9. cookie [<name>[<secret>]] :如果你理解了以上几个基于Hash的负载均衡策略,那么这个 cookie 的也会很好理解,其实它就是通过cookie的值的hash来选取一个上游。在这里 name 表示要获取cookie值的 name ,默认是 lb , secret 是用于Hash的密钥,使用的是Hamc256算法。

例如

PLAINTEXT

yourdomain.com {
  reverse_proxy /api/* 127.0.0.1:9000 127.0.0.1:9001 127.0.0.1:9002 {
    lb_policy round_robin
  }
}

使用 lb_try_duration 5s 设定重试等待时间为 5s,lb_try_interval 250ms 默认的重试时间间隔 250 毫秒

单页面应用 Caddyfile 配置

PLAINTEXT

example.com {
  root * /root/www/admin
  try_files {path} {file} /index.html
  file_server
  encode gzip
}

添加跨域请求头

PLAINTEXT

https://example.com {
   reverse_proxy /path http://localhost:54321 {
      header_up Host {http.reverse_proxy.upstream.hostport} 
      header_down Access-Control-Allow-Headers * 
      header_down Access-Control-Allow-Origin *
   }
}
  • header_up:用于添加(header_up +Content-Type 'application/json')、移除(header_up -Content-Type)和设置客户端到上游主机(后端)的请求头信息。也就是说利用它,可以修改客户端请求的头信息,然后再传给上游后端服务。+ 表示添加一个头信息, - 表示移除一个头信息,都没有的时候表示设置一个头信息。可以同时有多个header_up 。
  • header_down :和header_up 的作用一样,只不过它是用于修改后端服务响应的头信息,然后再传给客户端,方向正好是反的。

Docker 使用

先拉取镜像到本地,然后再运行这个镜像

$ docker pull caddy

由于大多时候都连不上官方仓库,所以使用镜像加速

$ docker pull hub.vonne.me/caddy

创建 Caddyfile

PLAINTEXT

http:// {
  root * /srv/www/localhost/
  file_server
}

创建 sites/localhost/index.html

PLAINTEXT

Hello, I'm in Docker.

docker run

之后直接运行(没用镜像就不需要前面的 hub.vonne.me/

$ docker run --name caddyweb -d -p 80:80 -p 443:443 -p 443:443/udp \
    -v $PWD/Caddyfile:/etc/caddy/Caddyfile \
    -v ./sites/:/srv/www/ \
    -v caddy_data/:/data/ \
    -v caddy_config:/config/ \
    hub.vonne.me/caddy

配置参数

  • --name 容器名 设置容器名
  • -d 后台运行
  • -p 主机端口:容器端口 端口映射
  • -v 主机路径或文件:容器路径或文件 挂载点,其中 /etc/caddy/Caddyfile 是配置文件,/srv/www/ 目录下放的是各个网站(默认的配置文件管理的网站目录为 /usr/share/caddy),/data 目录存放 Caddy 数据,/config 目录存放配置
  • 最后一行是镜像名称,如果没有配置参数的话应该是 docker run hub.vonne.me/caddy

docker compose

或者编写 docker-compose.yml,这样可以同时启动多个服务(services 下可以放更多服务,例如 redisruby 等)

YAML

services:
    caddyweb:
        image: hub.vonne.me/caddy
        restart: unless-stopped
        ports:
            - '80:80'
            - '443:443'
            - '443:443/udp'
    volumes:
        - ./Caddyfile:/etc/caddy/Caddyfile
        - ./sites/:/srv/www/
        - caddy_data/:/data/
        - caddy_config:/config/
volumes:
    caddy-data:
        external: true
    caddy-config:

然后执行命令 dcoker-compose up -d 启动

需要执行 caddy 相关的命令,可以先进入容器的终端

SH

$ docker exec -it 容器名或id sh

然后在正常执行 caddy 命令,例如 caddy reload

构建自己的镜像

新建 Dockerfile 文件

PLAINTEXT

FROM node:18 as builder

# Create work directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
ENV PATH /usr/src/app/node_modules/.bin:$PATH
COPY ./web/package.json /usr/src/app/package.json

RUN apk upgrade --update-cache --available
RUN npm install yarn --legacy-peer-deps
RUN yarn install --silent
COPY ./web /usr/src/app

RUN yarn run build

# ====== RUN CADDY =======
FROM caddy:2.8

COPY Caddyfile /etc/caddy/Caddyfile
COPY --from=builder /usr/src/app/build /srv/www

运行命令

SH

$ docker build -t myweb:1 .
$ docker run --name myweb -d -p 80:80 -p 443:443 -p 443:443/udp myweb:1

其他

API 管理

在启动 caddy 的时候你可能注意到它下面的日志

SH

$ caddy run
2024/10/29 05:30:29.168	INFO	using adjacent Caddyfile
2024/10/29 05:30:29.173	INFO	admin	admin endpoint started	{"address": "localhost:2019", "enforce_origin": false, "origins": ["//[::1]:2019", "//127.0.0.1:2019", "//localhost:2019"]}

它会启动一个管理地址,你可以通过它对 Caddy 进行管理(默认端口号为 2019

有一些 API 可供使用,例如下面两个

  • GET /config/ 可以获取它使用的配置文件(JSON 格式)
  • POST /load 设置或替换当前配置文件(JSON 格式)
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐