如何在 Ubuntu 22.04 上使用 Caddy 托管网站
作者选择了 Write for DOnations 计划。
介绍
让我们加密以启用 HTTPS,并包括对 HTTP/2 的支持。 HTTPS 是一种用于保护用户和服务器之间流量的系统,并且正在迅速成为任何在生产环境中运行的网站的基本期望——没有它,如果用户尝试提交,Chrome 和 Firefox 将警告您的网站“不安全”登录信息。
在本教程中,您将使用自定义 Caddy 构建工具 xcaddy 从源代码构建 Caddy,并使用它来托管受 HTTPS 保护的网站。这需要编译它,使用 Caddyfile
配置它并安装插件。最后,您的域将提供静态页面,同时使用 Let's Encrypt 提供的免费 TLS 证书进行保护。
先决条件
- 具有 root 权限的 Ubuntu 22.04 服务器,至少 2 GB RAM 和辅助的非 root 帐户。您可以按照我们的 Ubuntu 22.04 初始服务器设置指南进行设置。对于本教程,非根用户是
sammy
。 - 如何在 Ubuntu 20.04 上安装 Go 以设置最新的 Go 版本(Caddy 需要 Go 版本 17 或更高版本)。
- 一个完全注册的域名。本教程将始终使用
your_domain
。您可以在 Freenom 上购买域名,或使用您选择的域名注册商。 - A DNS 记录,
your_domain
指向您服务器的公共 IP 地址,CNAME DNS 记录,www.your_domain
指向@
。您可以按照 DigitalOcean DNS 的介绍了解如何添加它们的详细信息。 - 个人访问令牌(API 密钥),具有您的 DigitalOcean 帐户的读写权限。访问如何创建个人访问令牌以创建一个。
第 1 步 — 构建 Caddy
在这一步中,您将从源代码构建 Caddy,并能够在以后添加插件,而无需更改 Caddy 的源代码。您将使用 xcaddy
根据您的需要下载和构建 Caddy 及其插件。
访问 xcaddy
发布页面并复制 linux_amd64
平台的最新发布链接。下载之前,通过运行以下命令导航到 /tmp
:
- cd /tmp
然后,使用 wget
下载最新版本:
- wget https://github.com/caddyserver/xcaddy/releases/download/v0.3.1/xcaddy_0.3.1_linux_amd64.tar.gz
下载后,仅提取二进制文件:
- tar xvf xcaddy_0.3.1_linux_amd64.tar.gz xcaddy
最后,将 xcaddy
可执行文件移动到 /usr/bin
,使其在系统范围内可访问:
- sudo mv xcaddy /usr/bin
现在安装了 xcaddy
,您将构建 Caddy。为此,创建一个单独的目录来存储它:
- mkdir ~/caddy
通过运行以下命令导航到它:
- cd ~/caddy
要在没有任何第三方插件的情况下构建最新版本的 Caddy,请运行以下命令:
- xcaddy build
此命令需要一些时间才能完成,但它会打印类似于以下内容的输出:
Output2022/08/10 15:55:18 [INFO] Temporary folder: /tmp/buildenv_2022-08-10-1555.834895411
2022/08/10 15:55:18 [INFO] Writing main module: /tmp/buildenv_2022-08-10-1555.834895411/main.go
package main
import (
caddycmd "github.com/caddyserver/caddy/v2/cmd"
// plug in Caddy modules here
_ "github.com/caddyserver/caddy/v2/modules/standard"
)
func main() {
caddycmd.Main()
}
2022/08/10 15:55:18 [INFO] Initializing Go module
2022/08/10 15:55:18 [INFO] exec (timeout=10s): /usr/local/go/bin/go mod init caddy
go: creating new go.mod: module caddy
go: to add module requirements and sums:
go mod tidy
2022/08/10 15:55:18 [INFO] Pinning versions
2022/08/10 15:55:18 [INFO] exec (timeout=0s): /usr/local/go/bin/go get -d -v github.com/caddyserver/caddy/v2
go: downloading github.com/caddyserver/caddy v1.0.5
...
2022/08/10 15:55:49 [INFO] Build environment ready
2022/08/10 15:55:49 [INFO] Building Caddy
2022/08/10 15:55:49 [INFO] exec (timeout=0s): /usr/local/go/bin/go mod tidy
...
2022/08/10 15:55:57 [INFO] exec (timeout=0s): /usr/local/go/bin/go build -o /home/sammy/caddy/caddy -ldflags -w -s -trimpath
2022/08/10 15:58:48 [INFO] Build complete: ./caddy
2022/08/10 15:58:48 [INFO] Cleaning up temporary folder: /tmp/buildenv_2022-08-10-1555.834895411
完成后,您将在当前文件夹中获得可用的 caddy
可执行文件。将它移动到 /usr/bin
以安装它:
- sudo mv caddy /usr/bin
您可以尝试运行 caddy
来检查它是否安装正确:
- caddy version
输出将包含您刚刚编译的 Caddy 版本:
Outputv2.6.1 h1:EDqo59TyYWhXQnfde93Mmv4FJfYe00dO60zMiEt+pzo=
您现在已经构建并执行了 Caddy。在下一步中,您将安装 Caddy 作为一项服务,以便它在启动时自动启动,然后您将调整所有权和权限设置以确保服务器的安全。
第 2 步 — 安装 Caddy
现在您已经确认您能够构建和运行 Caddy,您可以配置 systemd
服务,以便 Caddy 在系统启动时自动启动。要了解有关 systemd
的更多信息,请访问我们的 Systemd Essentials 教程。
Caddy 需要自己的用户和组才能作为 systemd
服务运行。使用以下命令创建组:
- sudo groupadd --system caddy
然后,创建一个名为 caddy
的新用户,它属于 caddy
组:
- sudo useradd --system \
- --gid caddy \
- --create-home \
- --home-dir /var/lib/caddy \
- --shell /usr/sbin/nologin \
- --comment "Caddy web server" \
- caddy
新的 caddy
用户将创建自己的主目录。因为它的 shell 设置为 nologin
,所以无法以 caddy
身份登录。
将 Caddy 二进制文件的所有权更改为 root
用户:
- sudo chown root:root /usr/bin/caddy
此更改将阻止其他帐户修改可执行文件。然而,虽然 root
用户将拥有 Caddy,但建议您使用系统中存在的其他非 root 帐户来执行它,就像 systemd
一样服务。从非 root 帐户运行命令可确保攻击者无法修改二进制文件或在 Caddy(或其他程序)遭到破坏时以 root
身份执行命令。
接下来,将二进制文件的权限设置为755
,这将授予root
对该文件的完整读/写/执行权限,而其他用户将只能读取和执行它:
- sudo chmod 755 /usr/bin/caddy
您现在已经完成了 Caddy 二进制文件的设置并准备好开始 Caddy 配置。
创建一个目录,您将在其中存储 Caddy 的配置文件:
- sudo mkdir /etc/caddy
然后为其设置用户和组权限:
- sudo chown -R root:caddy /etc/caddy
将用户设置为 root
并将组设置为 caddy
确保 Caddy 将具有对该文件夹的读写权限(通过 caddy
组)并且只有超级用户帐户才具有相同的读取和修改权限。
在后面的步骤中,您将从 Let's Encrypt 启用自动 TLS 证书配置。为此,创建一个目录来存储 Caddy 将获得的任何 TLS 证书,并为其赋予与 /etc/caddy
目录相同的所有权规则:
- sudo mkdir /etc/ssl/caddy
- sudo chown -R root:caddy /etc/ssl/caddy
Caddy 必须能够将证书写入此目录并从中读取以加密请求。为此,修改 /etc/ssl/caddy
目录的权限,使其只能由 root
和 caddy
访问:
- sudo chmod 0770 /etc/ssl/caddy
接下来创建一个目录来存储 Caddy 将托管的文件:
- sudo mkdir /var/www
然后将目录的所有者和组设置为 caddy
:
- sudo chown caddy:caddy /var/www
要安装 Caddy 服务,请通过运行以下命令将 systemd
单元文件从 Caddy GitHub 存储库下载到 /etc/systemd/system
:
- sudo sh -c 'curl https://raw.githubusercontent.com/caddyserver/dist/master/init/caddy.service > /etc/systemd/system/caddy.service'
你会收到这样的回复:
Output % Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1030 100 1030 0 0 4698 0 --:--:-- --:--:-- --:--:-- 4703
```
Modify the service file's permissions so it can only be modified by its owner, `root`:
```command
sudo chmod 644 /etc/systemd/system/caddy.service
然后,重新加载 systemd
以检测 Caddy 服务:
- sudo systemctl daemon-reload
通过运行 systemctl status
检查 systemd
是否检测到 Caddy 服务:
- sudo systemctl status caddy
您将收到类似于以下内容的输出:
Output● caddy.service - Caddy
Loaded: loaded (/etc/systemd/system/caddy.service; disabled; vendor preset: enabled)
Active: inactive (dead)
Docs: https://caddyserver.com/docs/
如果您有相同的输出,则 systemd
检测到新服务。
作为初始服务器设置的一部分,您启用了 ufw
并允许 SSH 连接。为了让 Caddy 为来自您的服务器的 HTTP 和 HTTPS 流量提供服务,您需要通过运行以下命令在 ufw
中允许它们:
- sudo ufw allow proto tcp from any to any port 80,443
输出将是:
OutputRule added
Rule added (v6)
使用 ufw status
验证您的更改:
- sudo ufw status
您将收到以下输出:
OutputStatus: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
80,443/tcp ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
80,443/tcp (v6) ALLOW Anywhere (v6)
您的 Caddy 安装现已完成,但尚未配置为提供任何服务。在下一步中,您将配置 Caddy 以提供来自 /var/www
目录的文件。
第 3 步 — 配置 Caddy
在本节中,您将编写基本的 Caddy 配置,用于从您的服务器提供静态文件。
在 /var/www
中创建一个名为 index.html
的基本 HTML 文件:
- sudo nano /var/www/index.html
添加以下行:
<!DOCTYPE html>
<html>
<head>
<title>Hello from Caddy!</title>
</head>
<body>
<h1 style="font-family: sans-serif">This page is being served via Caddy</h1>
</body>
</html>
当在 Web 浏览器中显示时,此文件将显示一个标题,其中包含文本 This page is being served via Caddy。保存并关闭文件。
Caddy 从存储在 /etc/caddy
下的名为 Caddyfile
的文件中读取其配置。创建并打开文件进行编辑:
- sudo nano /etc/caddy/Caddyfile
添加以下行:
- http:// {
- root * /var/www
- encode gzip
- file_server
- }
这个基本的 Caddy 配置声明所有到您服务器的 HTTP 流量都应该使用来自 /var/www
(标记为 root)的文件(
压缩以减少客户端的页面加载时间。file_server
)提供code>) 并使用 gzip
Caddy 对许多用例有不同的指令。例如,指令的官方文档页面。
完成后,保存并关闭文件。
要测试一切是否正常工作,请启动 Caddy 服务:
- sudo systemctl start caddy
接下来,运行 systemctl status
来查找有关 Caddy 服务状态的信息:
- sudo systemctl status caddy
您将收到以下内容:
Output● caddy.service - Caddy
Loaded: loaded (/etc/systemd/system/caddy.service; disabled; vendor preset: enabled)
Active: active (running) since Wed 2022-08-10 15:02:41 UTC; 2s ago
Docs: https://caddyserver.com/docs/
Main PID: 5443 (caddy)
Tasks: 7 (limit: 1119)
Memory: 7.5M
CPU: 30ms
CGroup: /system.slice/caddy.service
└─5443 /usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
您现在可以在网络浏览器中访问您服务器的 IP。您的示例网页将显示:

您现在已经将 Caddy 配置为从您的服务器提供静态文件。在下一步中,您将通过插件扩展 Caddy 的功能。
第 4 步 — 使用 Let's Encrypt 启用自动 TLS
插件可以改变和扩展 Caddy 的行为。通常,他们会根据您的用例提供更多配置指令。在此步骤中,您将启用自动 Let's Encrypt 证书配置和更新,使用 TXT DNS 记录进行验证。要使用 TXT DNS 记录进行验证,您将安装官方插件以与 DigitalOcean DNS API 交互。
要添加插件,您需要使用 xcaddy
重新编译 Caddy,指定应该可用的插件存储库。运行以下命令编译支持 DigitalOcean DNS 的 Caddy:
- xcaddy build --with github.com/caddy-dns/digitalocean@master
输出将与此类似:
Output...
2022/08/10 15:03:24 [INFO] exec (timeout=0s): /usr/local/go/bin/go get -d -v github.com/caddy-dns/digitalocean@master github.com/caddyserver/caddy/v2
go: downloading github.com/caddy-dns/digitalocean v0.0.0-20220527005842-9c71e343246b
go: downloading github.com/libdns/digitalocean v0.0.0-20220518195853-a541bc8aa80f
go: downloading github.com/digitalocean/godo v1.41.0
go: downloading github.com/google/go-querystring v1.0.0
go: downloading golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c
go: downloading google.golang.org/appengine v1.6.6
go: added github.com/caddy-dns/digitalocean v0.0.0-20220527005842-9c71e343246b
go: added github.com/digitalocean/godo v1.41.0
go: added github.com/libdns/digitalocean v0.0.0-20220518195853-a541bc8aa80f
2022/08/10 15:03:33 [INFO] exec (timeout=0s): /usr/local/go/bin/go get -d -v
go: downloading github.com/antlr/antlr4 v0.0.0-20200503195918-621b933c7a7f
go: downloading github.com/Masterminds/semver v1.4.2
go: downloading github.com/cenkalti/backoff v2.2.1+incompatible
go: downloading github.com/cpuguy83/go-md2man v1.0.10
go: downloading github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220804214150-8b0cc382067f
go: downloading github.com/antlr/antlr4 v4.10.1+incompatible
go: upgraded github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed => v0.0.0-20220804214150-8b0cc382067f
go: upgraded golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c => v0.0.0-20211104180415-d3ed0bb246c8
go: upgraded google.golang.org/appengine v1.6.6 => v1.6.7
2022/08/10 15:03:39 [INFO] Build environment ready
2022/08/10 15:03:39 [INFO] Building Caddy
2022/08/10 15:03:39 [INFO] exec (timeout=0s): /usr/local/go/bin/go mod tidy
2022/08/10 15:03:40 [INFO] exec (timeout=0s): /usr/local/go/bin/go build -o /home/sammy/caddy/caddy -ldflags -w -s -trimpath
2022/08/10 15:03:56 [INFO] Build complete: ./caddy
2022/08/10 15:03:56 [INFO] Cleaning up temporary folder: /tmp/buildenv_2022-08-10-1503.1377463227
编译完成后,通过运行以下命令将生成的二进制文件移动到 /usr/bin
:
- sudo mv caddy /usr/bin
然后,设置适当的权限:
- sudo chown root:root /usr/bin/caddy
- sudo chmod 755 /usr/bin/caddy
接下来,您将配置 Caddy 以使用 DigitalOcean 的 API 来设置 DNS 记录。 Caddy 需要读取您的 API 令牌作为环境变量来配置 DigitalOcean 的 DNS,因此您将编辑其 systemd
单元文件。打开文件进行编辑:
- sudo nano /etc/systemd/system/caddy.service
在 [Service]
部分添加突出显示的行,将 your_token_here
替换为您的 API 令牌:
...
[Service]
Type=notify
User=caddy
Group=caddy
Environment=DO_AUTH_TOKEN=your_token_here
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE
...
保存并关闭此文件,然后重新加载 systemd
守护进程以确保配置已更新:
- sudo systemctl daemon-reload
运行 systemctl restart
以检查您的配置更改:
- sudo systemctl restart caddy
然后运行 systemctl status
检查它是否正确运行:
- sudo systemctl status caddy
您将收到以下输出:
Output● caddy.service - Caddy
Loaded: loaded (/etc/systemd/system/caddy.service; disabled; vendor preset: enabled)
Active: active (running) since Wed 2022-08-10 15:06:01 UTC; 2s ago
Docs: https://caddyserver.com/docs/
Main PID: 5620 (caddy)
Tasks: 7 (limit: 1119)
Memory: 7.5M
CPU: 37ms
CGroup: /system.slice/caddy.service
└─5620 /usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
接下来,你需要对你的 Caddyfile
做一些小改动,打开它进行编辑:
- sudo nano /etc/caddy/Caddyfile
将突出显示的行添加到 Caddyfile
,将 your_domain
替换为您的域(而不是 http://
)和添加指定 DigitalOcean DNS 的 tls
块:
your_domain {
root * /var/www
encode gzip
file_server
tls {
dns digitalocean {env.DO_AUTH_TOKEN}
}
}
使用域而不是主机名的协议说明符将导致 Caddy 通过 HTTPS 服务请求。 tls
指令在使用 TLS
时配置 Caddy 的行为,您命令它使用 digitalocean
插件来设置 DNS 记录和请求证书。 dns
子指令指定 Caddy 应该使用 DigitalOcean DNS 系统而不是 HTTP。
保存并关闭文件。
这样,您的网站就可以部署了。使用 systemctl
重启 Caddy,然后 enable
让它在启动时运行:
- sudo systemctl restart caddy
- sudo systemctl enable caddy
当您访问您的域时,您将被自动重定向到 HTTPS,并使用相同的 This page is served via Caddy 消息。
您的 Caddy 安装现已完成且安全,您可以根据您的用例进一步自定义。
结论
您现在已经在您的服务器上安装和配置了 Caddy,在您想要的域中提供静态页面,并使用免费的 Let's Encrypt TLS 证书进行保护。
下一步是为新版本的 Caddy 发布时设置通知。例如,您可以使用 Caddy 的文档来获取有关配置 Caddy 的更多信息。
您还可以通过我们的“如何使用 Go 编写代码”系列了解有关使用 Go 语言的更多信息。