如何在Ubuntu18.04上使用Caddy托管网站
作为 Write for DOnations 计划的一部分,作者选择了 Free and Open Source Fund 来接受捐赠。
介绍
Caddy 是一个围绕简单性和安全性而设计的 Web 服务器,它具有许多对托管网站有用的功能。 例如,它可以自动从 Let's Encrypt 获取和管理 TLS 证书以启用 HTTPS,并包括对 HTTP/2 的支持。 HTTPS 是一种用于保护您的用户和服务器之间的流量的系统,并且正在迅速成为任何在生产中运行的网站的基本期望——没有它,如果用户尝试提交登录,Chrome 和 Firefox 会警告您的网站“不安全”信息。
在本教程中,您将使用自定义 Caddy 构建器工具 xcaddy 从源代码构建 Caddy,并使用它来托管使用 HTTPS 保护的网站。 这需要编译它,使用 Caddyfile
配置它并安装插件。 最后,您的域将提供静态页面,同时使用 Let's Encrypt 的免费 TLS 证书进行保护。
先决条件
- 具有 root 权限和辅助非 root 帐户的 Ubuntu 18.04 服务器。 您可以按照我们的 Initial Server Setup Guide for Ubuntu 18.04 进行设置。 对于本教程,非 root 用户是
sammy
。 - 完全注册的域名。 本教程将自始至终使用
your_domain
。 您可以在 Namecheap 上购买一个域名,在 Freenom 上免费获得一个域名,或者使用您选择的域名注册商。 your_domain
的 A DNS 记录指向您服务器的公共 IP 地址。 您可以关注这个DigitalOcean DNS的介绍,详细了解如何添加它们。- 安装在您的服务器上的 Go 语言 工具链,版本 1.14 及更高版本。 按照我们关于 如何在 Ubuntu 18.04 上安装 Go 和设置本地编程环境的指南来设置最新的 Go。 您无需创建任何示例项目。
- 对您的 DigitalOcean 帐户具有读写权限的个人访问令牌(API 密钥)。 访问 如何创建个人访问令牌 创建一个。
第 1 步 - 建造球童
在这一步中,您将从源代码构建 Caddy,并能够在以后添加插件,所有这些都无需更改 Caddy 的源代码。 您将使用 xcaddy
完成此操作,它将根据您的需要为您下载和构建 Caddy 及其插件。
前往其 发布页面 并复制 linux_amd64
平台的最新版本的链接。 在下载之前,通过运行以下命令导航到 /tmp
:
cd /tmp
然后,使用 wget
下载最新版本:
wget https://github.com/caddyserver/xcaddy/releases/download/v0.1.8/xcaddy_0.1.8_linux_amd64.tar.gz
下载后,仅提取二进制文件:
tar xvf xcaddy_0.1.8_linux_amd64.tar.gz xcaddy
最后,将 xcaddy
可执行文件移动到 /usr/bin
,使其可在系统范围内访问:
sudo mv xcaddy /usr/bin
现在 xcaddy
已安装,您将构建 Caddy。 为此,创建一个单独的目录来存储它:
mkdir ~/caddy
通过运行以下命令导航到它:
cd ~/caddy
要构建最新版本的 Caddy,无需任何第三方插件,请运行以下命令:
xcaddy build
此命令需要一些时间才能完成,其输出类似于以下内容:
Output2021/02/23 21:12:07 [INFO] Temporary folder: /tmp/buildenv_2021-02-23-2112.542119152 2021/02/23 21:12:07 [INFO] Writing main module: /tmp/buildenv_2021-02-23-2112.542119152/main.go 2021/02/23 21:12:07 [INFO] Initializing Go module 2021/02/23 21:12:07 [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 2021/02/23 21:12:07 [INFO] Pinning versions 2021/02/23 21:12:07 [INFO] exec (timeout=0s): /usr/local/go/bin/go get -d -v github.com/caddyserver/caddy/v2 ... 2021/02/23 21:12:34 [INFO] Build environment ready 2021/02/23 21:12:34 [INFO] Building Caddy 2021/02/23 21:12:34 [INFO] exec (timeout=0s): /usr/local/go/bin/go mod tidy ... 2021/02/23 21:12:51 [INFO] exec (timeout=0s): /usr/local/go/bin/go build -o /home/sammy/caddy/caddy -ldflags -w -s -trimpath 2021/02/23 21:14:26 [INFO] Build complete: ./caddy 2021/02/23 21:14:26 [INFO] Cleaning up temporary folder: /tmp/buildenv_2021-02-23-2112.542119152
完成后,您将在当前文件夹中获得 caddy
可执行文件。 移动到/usr/bin
安装:
sudo mv caddy /usr/bin
您可以尝试运行 caddy
来检查它是否安装正确:
caddy version
输出将包含您刚刚编译的 Caddy 版本:
Outputv2.3.0 h1:fnrqJLa3G5vfxcxmOH/+kJOcunPLhSBnjgIvjXV/QTA=
您现在已经构建并执行了 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
用户将创建自己的主目录。 无法以 caddy
身份登录,因为它的外壳设置为 nologin
。
将 Caddy 二进制文件的所有权更改为 root 用户:
sudo chown root:root /usr/bin/caddy
这将防止其他帐户修改可执行文件。 然而,即使 root 用户将拥有 Caddy,建议仅使用系统上存在的其他非 root 帐户来执行它——就像 systemd 服务的情况一样。 这确保了在 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 从一个名为 Caddyfile
的文件中读取其配置,该文件存储在 /etc/caddy
下。 通过运行在磁盘上创建文件:
sudo touch /etc/caddy/Caddyfile
要安装 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'
修改服务文件的权限,使其只能由其所有者 root 修改:
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
中创建一个基本的 HTML 文件,称为 index.html
:
sudo nano /var/www/index.html
添加以下行:
/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 serving via Caddy 的标题。 保存并关闭文件。
打开之前创建的 Caddyfile
配置文件进行编辑:
sudo nano /etc/caddy/Caddyfile
添加以下行:
/etc/caddy/Caddy 文件
http:// { root * /var/www encode gzip file_server }
这是一个基本的 Caddy 配置,并声明到您的服务器的所有 HTTP 流量都应使用来自 /var/www
(标记为 root
)的文件(file_server
)并压缩使用 gzip
减少客户端的页面加载时间。
完成后,保存并关闭文件。
Caddy 为许多用例提供了大量不同的指令。 例如,php_fastcgi 指令可用于启用 PHP。
要测试一切是否正常,请启动 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 Tue 2020-12-08 11:19:47 UTC; 34s ago Docs: https://caddyserver.com/docs/ Main PID: 4631 (caddy) Tasks: 6 (limit: 1137) Memory: 10.4M CGroup: /system.slice/caddy.service └─4631 /usr/bin/caddy run --environ --config /etc/caddy/Caddyfile Dec 08 11:19:47 ubuntu-s-1vcpu-1gb-fra1-01 caddy[4631]: USER=caddy Dec 08 11:19:47 ubuntu-s-1vcpu-1gb-fra1-01 caddy[4631]: INVOCATION_ID=45713fb36abe48ecaf4aa72a12542658 Dec 08 11:19:47 ubuntu-s-1vcpu-1gb-fra1-01 caddy[4631]: JOURNAL_STREAM=9:33053 Dec 08 11:19:47 ubuntu-s-1vcpu-1gb-fra1-01 caddy[4631]: {"level":"info","ts":1607426387.425965,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":""} Dec 08 11:19:47 ubuntu-s-1vcpu-1gb-fra1-01 caddy[4631]: {"level":"info","ts":1607426387.4281814,"logger":"admin","msg":"admin endpoint started","address":"tcp/localhost:2019","enforce_origin":false,"origins":["127.0.0.1:2019","localhost:2019","[::1]:2019"]} Dec 08 11:19:47 ubuntu-s-1vcpu-1gb-fra1-01 caddy[4631]: {"level":"info","ts":1607426387.4285417,"logger":"http","msg":"server is listening only on the HTTP port, so no automatic HTTPS will be applied to this server","server_name":"srv0","http_port":80} Dec 08 11:19:47 ubuntu-s-1vcpu-1gb-fra1-01 caddy[4631]: {"level":"info","ts":1607426387.430661,"msg":"autosaved config","file":"/var/lib/caddy/.config/caddy/autosave.json"} Dec 08 11:19:47 ubuntu-s-1vcpu-1gb-fra1-01 caddy[4631]: {"level":"info","ts":1607426387.430849,"msg":"serving initial configuration"} Dec 08 11:19:47 ubuntu-s-1vcpu-1gb-fra1-01 caddy[4631]: {"level":"info","ts":1607426387.4311824,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc00021f0a0"} Dec 08 11:19:47 ubuntu-s-1vcpu-1gb-fra1-01 caddy[4631]: {"level":"info","ts":1607426387.4313655,"logger":"tls","msg":"cleaned up storage units"}
您现在可以在 Web 浏览器中浏览到您的服务器的 IP。 您的示例网页将显示:
您现在已将 Caddy 配置为从您的服务器提供静态文件。 在下一步中,您将通过使用插件来扩展 Caddy 的功能。
第 4 步 — 使用 Let's Encrypt 启用自动 TLS
插件提供了一种改变和扩展 Caddy 行为的方法。 通常,它们会根据您的用例提供更多配置指令供您使用。 在本节中,您将启用自动 Let's Encrypt 证书配置和续订,使用 TXT DNS 记录进行验证。 要验证使用 TXT DNS 记录,您将安装 官方插件 用于与 DigitalOcean DNS API 接口。
注意: 你可能会注意到我们在这一步中使用的官方插件被标记为已弃用。 这是因为它正在被一组基于 libdns 的更新的模块化库所取代。
但是,digitalocean 库目前处于开发状态,存在一些未解决的问题。 在问题得到解决之前,我们将使用早期的插件,尽管它被标记为已过时,但它仍然可以正常工作。
要添加插件,您需要使用 xcaddy
重新编译 Caddy,但指定应该可用的插件存储库。 运行以下命令来编译支持 DigitalOcean DNS 的 Caddy:
xcaddy build --with github.com/caddy-dns/lego-deprecated
输出将与此类似:
Output2021/02/23 21:18:46 [INFO] Temporary folder: /tmp/buildenv_2021-02-23-2118.769615504 2021/02/23 21:18:46 [INFO] Writing main module: /tmp/buildenv_2021-02-23-2118.769615504/main.go 2021/02/23 21:18:46 [INFO] Initializing Go module 2021/02/23 21:18:46 [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 2021/02/23 21:18:46 [INFO] Pinning versions 2021/02/23 21:18:46 [INFO] exec (timeout=0s): /usr/local/go/bin/go get -d -v github.com/caddyserver/caddy/v2 go get: added github.com/caddyserver/caddy/v2 v2.3.0 2021/02/23 21:18:49 [INFO] exec (timeout=0s): /usr/local/go/bin/go get -d -v github.com/caddy-dns/lego-deprecated ... 2021/02/23 21:19:17 [INFO] Build environment ready 2021/02/23 21:19:17 [INFO] Building Caddy 2021/02/23 21:19:17 [INFO] exec (timeout=0s): /usr/local/go/bin/go mod tidy ... 2021/02/23 21:19:20 [INFO] exec (timeout=0s): /usr/local/go/bin/go build -o /home/sammy/caddy/caddy -ldflags -w -s -trimpath 2021/02/23 21:20:09 [INFO] Build complete: ./caddy 2021/02/23 21:20:09 [INFO] Cleaning up temporary folder: /tmp/buildenv_2021-02-23-2118.769615504
编译完成后,通过运行将生成的二进制文件移动到 /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 令牌:
/etc/systemd/system/caddy.service
... [Service] 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 Tue 2020-12-08 13:39:17 UTC; 1s ago Docs: https://caddyserver.com/docs/ Main PID: 5440 (caddy) Tasks: 5 (limit: 1137) Memory: 9.8M CGroup: /system.slice/caddy.service └─5440 /usr/bin/caddy run --environ --config /etc/caddy/Caddyfile ...
您需要对 Caddyfile
进行一些细微的更改,因此打开它进行编辑:
sudo nano /etc/caddy/Caddyfile
将突出显示的行添加到 Caddyfile
,确保将 your_domain
替换为您的域(而不仅仅是 http://
)并添加 tls
块,指定应使用 DigitalOcean DNS:
/etc/caddy/Caddy 文件
your_domain { root * /var/www encode gzip file_server tls { dns lego_deprecated digitalocean } }
使用域而不仅仅是主机名的协议说明符将导致 Caddy 通过 HTTPS 服务请求。 tls
指令配置 Caddy 在使用 TLS
时的行为,dns
子指令指定 Caddy 应该使用 DigitalOcean DNS 系统,而不是 HTTP。
有了这个,您的网站就可以部署了。 用 systemctl
重新启动 Caddy,然后用 enable
重新启动它,这样它就会在启动时运行:
sudo systemctl restart caddy sudo systemctl enable caddy
如果您浏览到您的域,您将自动被重定向到 HTTPS,并显示相同的消息。
您的 Caddy 安装现已完成且安全,您可以根据您的用例进一步自定义。
结论
您现在已经在您的服务器上安装和配置了 Caddy,在您想要的域中提供静态页面,并使用免费的 Let's Encrypt TLS 证书进行保护。
一个好的下一步是找到一种在新版本的 Caddy 发布时收到通知的方法。 例如,您可以将 Atom 提要用于 Caddy 版本 ,或专用服务,例如 dependencies.io。
您可以浏览 Caddy 的文档 以获取有关配置 Caddy 的更多信息。