文档
一个 项目

使 Caddy 持续运行

虽然可以直接使用 Caddy 的命令行界面运行 Caddy,但使用服务管理器来保持其运行有诸多优点,例如确保系统重启时自动启动并捕获 stdout/stderr 日志。

Linux 服务

在使用 systemd 的 Linux 发行版上,推荐使用我们官方的 systemd 单元文件来运行 Caddy。

Unit 文件

我们提供了两种不同的 systemd 单元文件,你可以根据使用场景选择:

  • caddy.service —— 如果你使用 Caddyfile 来配置 Caddy。若你更喜欢使用其他配置适配器或 JSON 配置文件,可以覆盖 ExecStart 和 ExecReload 命令。

  • caddy-api.service —— 如果你仅通过其 API 配置 Caddy。该服务使用 --resume 选项,这将使用默认持久化的 autosave.json 启动 Caddy。

它们非常相似,但在 ExecStart 和 ExecReload 命令上有所不同,以适应不同的工作流程。

如果需要在这两种服务之间切换,应在启用并启动另一个服务之前先禁用并停止之前的服务。例如,要从 caddy 服务切换到 caddy-api 服务:

sudo systemctl disable --now caddy
sudo systemctl enable --now caddy-api

手动安装

一些安装方法会自动将 Caddy 设置为以服务运行。如果你选择的方法没有这样做,可以按照以下说明操作:

需求:

  • 你已下载或从源码构建 的 caddy 二进制文件
  • systemctl --version 需为 232 或更新版本
  • sudo 权限

将 caddy 二进制文件移入你的 $PATH,例如:

sudo mv caddy /usr/bin/

测试是否生效:

caddy version

创建名为 caddy 的用户组:

sudo groupadd --system caddy

创建一个名为 caddy 的用户,并带有可写的主目录:

sudo useradd --system \
    --gid caddy \
    --create-home \
    --home-dir /var/lib/caddy \
    --shell /usr/sbin/nologin \
    --comment "Caddy web server" \
    caddy

如果使用配置文件,请确保该配置文件对你刚创建的 caddy 用户可读。

接下来,根据你的使用场景选择一个 systemd 单元文件。

再次确认 ExecStart 和 ExecReload 指令。 确保二进制位置和命令行参数与您的安装相符!例如:如果使用配置文件,请根据实际情况修改 --config 路径(若与默认不同)。

通常将服务文件保存到:/etc/systemd/system/caddy.service

保存服务文件后,可以通过常用的 systemctl 操作首次启动服务:

sudo systemctl daemon-reload
sudo systemctl enable --now caddy

验证其是否正在运行:

systemctl status caddy

现在你就可以使用该服务了!

使用服务

如果使用 Caddyfile,可以使用 nano、vi 或你喜欢的编辑器编辑配置:

sudo nano /etc/caddy/Caddyfile

你可以将静态站点文件放在 /var/www/html 或 /srv 中。确保 caddy 用户有权限读取这些文件。

要验证服务是否正在运行:

systemctl status caddy

status 命令还会显示当前正在运行的服务文件的位置。

当使用我们的官方服务文件运行时,Caddy 的输出将被重定向到 journalctl。要读取完整日志并避免行被截断:

journalctl -u caddy --no-pager | less +G

如果使用配置文件,在进行更改后可以优雅地重新加载 Caddy:

sudo systemctl reload caddy

你可以使用以下命令停止服务:

sudo systemctl stop caddy

Caddy 进程将以 caddy 用户身份运行,其 $HOME 被设置为 /var/lib/caddy。这意味着:

  • 默认的数据存储位置(用于证书及其他状态信息)将是 /var/lib/caddy/.local/share/caddy。
  • 默认的配置存储位置(用于自动保存的 JSON 配置,主要对 caddy-api 服务有用)将是 /var/lib/caddy/.config/caddy。

使用 systemd 的本地 HTTPS

在本地开发使用 HTTPS 时,你可能会使用像 localhost 或 app.localhost 这样的主机名。这将启用使用 Caddy 本地 CA 签发证书的本地 HTTPS。

由于以服务方式运行时 Caddy 会以 caddy 用户运行,因此它没有权限将其根 CA 证书安装到系统信任存储。为此,请运行 sudo caddy trust 来执行安装。

如果你希望在使用 internal issuer 时其他设备也能连接到你的服务器,则需要在那些设备上也安装根 CA 证书。你可以在 /var/lib/caddy/.local/share/caddy/pki/authorities/local/root.crt 找到根 CA 证书。许多 Web 浏览器现在使用自己的信任存储(忽略系统的信任存储),因此你可能还需要在浏览器中手动安装该证书。

覆盖配置

覆盖服务文件某些配置的最佳方式是使用以下命令:

sudo systemctl edit caddy

这会在你的默认终端文本编辑器中打开一个空文件,你可以在其中覆盖或添加单元定义指令。这称为“drop-in” 文件。

环境变量

如果你需要为配置定义环境变量,可以像下面这样做:

[Service]
Environment="CF_API_TOKEN=super-secret-cloudflare-tokenvalue"

类似地,如果你更愿意将环境变量保存在单独文件(envfile)中,可以使用 EnvironmentFile 指令,如下:

[Service]
EnvironmentFile=/etc/caddy/.env

那么你的 /etc/caddy/.env 文件可以如下(不要在值周围使用 " 引号):

CF_API_TOKEN=super-secret-cloudflare-tokenvalue

run 与 reload 覆盖

如果需要将配置文件从默认的 Caddyfile 更改为使用 JSON 文件(注意 Exec* 指令在设置新值之前必须先用空字符串重置):

[Service]
ExecStart=
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/caddy.json
ExecReload=
ExecReload=/usr/bin/caddy reload --config /etc/caddy/caddy.json

崩溃时重启

如果你希望在 Caddy 意外崩溃后 5 秒内自动重启:

[Service]
# 如果退出代码不是 1,则自动重启 caddy
RestartPreventExitStatus=1
Restart=on-failure
RestartSec=5s

然后,保存文件并退出文本编辑器,重启服务以使其生效:

sudo systemctl restart caddy

SELinux 注意事项

在启用 SELinux 的系统上,你有两个选择:

  1. 使用 COPR 仓库 安装 Caddy。你的 systemd 文件和 caddy 二进制文件将已被正确创建并标记(因此你可以忽略本节)。如果你希望使用自定义构建的 Caddy,则需要按下文所述标记可执行文件。

  2. 从本站下载 Caddy或使用 xcaddy 编译。在任一情况下,你都需要自己标记文件。

Systemd 单元文件及其可执行文件在未被标记为 systemd_unit_file_t 和 bin_t 时不会被运行。

systemd_unit_file_t 标签会自动应用于创建在 /etc/systemd/... 下的文件,所以请确保按手动安装 的说明将 caddy.service 文件创建在那里。

要标记 caddy 二进制文件,你可以使用以下命令:

semanage fcontext -a -t bin_t /usr/bin/caddy && restorecon -Rv /usr/bin/caddy

Windows 服务

在 Windows 上以服务方式运行 Caddy 有两种方法:sc.exe 或 WinSW。

sc.exe

创建服务,请运行:

sc.exe create caddy start= auto binPath= "YOURPATH\caddy.exe run"

(将 YOURPATH 替换为实际的 caddy.exe 路径)

启动:

sc.exe start caddy

停止:

sc.exe stop caddy

WinSW

按下述说明在 Windows 上将 Caddy 安装为服务。

需求:

  • 你已下载或从源码构建 的 caddy.exe 二进制文件
  • 来自最新发布版本的任意 .exe,来自 WinSW 服务包装器(下面的服务配置为 v2.x 发行版 编写)

将所有文件放入一个服务目录。以下示例中我们使用 C:\caddy。

将 WinSW-x64.exe 文件重命名为 caddy-service.exe。

在相同目录下添加 caddy-service.xml:

<service>
  <id>caddy</id>
  <!-- Display name of the service -->
  <name>Caddy Web Server (powered by WinSW)</name>
  <!-- Service description -->
  <description>Caddy Web Server (https://caddyserver.com/)</description>
  <executable>%BASE%\caddy.exe</executable>
  <arguments>run</arguments>
  <log mode="roll-by-time">
    <pattern>yyyy-MM-dd</pattern>
  </log>
</service>

现在你可以使用以下命令安装服务:

caddy-service install

你可能想打开 Windows 服务控制台查看服务是否运行正确:

services.msc

请注意,Windows 服务不能被 reload,因此你必须直接告诉 caddy 重新加载:

caddy reload

可以通过常规的 Windows 服务命令重启服务,例如通过任务管理器的 “服务” 选项卡。

如需自定义服务包装器,请参阅 WinSW 文档

Docker Compose

使用 Docker 最简单的方式是使用 Docker Compose。有关官方 Caddy Docker 镜像的更多详细信息,请参阅 Docker Hub 上的文档。

设置

首先,创建一个文件 compose.yml(或将此服务添加到你现有的文件中):

services:
  caddy:
    image: caddy:<version>
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - ./conf:/etc/caddy
      - ./site:/srv
      - caddy_data:/data
      - caddy_config:/config

volumes:
  caddy_data:
  caddy_config:

确保将镜像的 <version> 填写为最新版本号,你可以在 Docker Hub 的 “Tags” 部分找到。

此配置的作用:

  • 使用 unless-stopped 重启策略,确保在机器重启时 Caddy 容器会自动重启。
  • 绑定端口 80 和 443 分别用于 HTTP 和 HTTPS,同时绑定 443/udp 以支持 HTTP/3。
  • 将包含 Caddyfile 配置的 conf 目录绑定挂载到容器中。
  • 将 site 目录绑定挂载到 /srv,用于提供站点静态文件。
  • 为 /data 和 /config 使用命名卷,以持久化重要信息。

然后,在 conf 目录中创建一个名为 Caddyfile 的文件,并写入你的 Caddyfile 配置。

如果你有静态文件要提供,可以在与配置文件并列的目录中放一个 site/,然后使用 root * /srv 设置 root。如果没有静态文件,可以移除 /srv 的卷挂载。

如果你需要带有插件的自定义 Caddy 构建,请按照 Docker 构建说明 创建自定义 Docker 镜像。将 Dockerfile 与 compose.yml 放在一起,然后在 compose.yml 中将 image: 行替换为 build: .。

使用

然后,你可以启动容器:

docker compose up -d

在对 Caddyfile 做出更改后重新加载 Caddy:

docker compose exec -w /etc/caddy caddy caddy reload

查看 Caddy 最近的 1000 条日志,并使用 f 跟随以查看新日志流入:

docker compose logs caddy -n=1000 -f

使用 Docker 的本地 HTTPS

在使用 Docker 本地开发并启用 HTTPS 时,你可能会使用像 localhost 或 app.localhost 这样的主机名。这将启用使用 Caddy 本地 CA 签发证书的本地 HTTPS。这意味着容器外的 HTTP 客户端不会信任 Caddy 提供的 TLS 证书。为了解决此问题,你可以在宿主机的信任存储中安装 Caddy 的根 CA 证书:

docker compose cp \
    caddy:/data/caddy/pki/authorities/local/root.crt \
    /usr/local/share/ca-certificates/root.crt \
  && sudo update-ca-certificates
docker compose cp \
    caddy:/data/caddy/pki/authorities/local/root.crt \
    /tmp/root.crt \
  && sudo security add-trusted-cert -d -r trustRoot \
    -k /Library/Keychains/System.keychain /tmp/root.crt
docker compose cp \
    caddy:/data/caddy/pki/authorities/local/root.crt \
    %TEMP%/root.crt \
  && certutil -addstore -f "ROOT" %TEMP%/root.crt

许多 Web 浏览器现在使用它们自己的信任存储(忽略系统的信任存储),因此你可能还需要在浏览器中手动安装该证书,使用上面从容器中复制出来的 root.crt 文件。

  • 对于 Firefox,进入 偏好设置 > 隐私与安全 > 证书 > 查看证书 > 权威机构 > 导入,然后选择 root.crt 文件。

  • 对于 Chrome,进入 设置 > 隐私与安全 > 安全性 > 管理证书 > 权威机构 > 导入,然后选择 root.crt 文件。