如何在Ubuntu16.04上使用Caddy托管网站

来自菜鸟教程
跳转至:导航、​搜索

本教程的早期版本由 Mateusz Papiernik 编写。

作为 Write for DOnations 计划的一部分,作者选择了 Wikimedia Foundation 来获得 200 美元的捐款。

介绍

Caddy 是一个围绕简单性和安全性而设计的 Web 服务器,它具有许多对托管网站有用的功能。 例如,它可以自动从 Let's Encrypt 获取和管理 TLS 证书以启用 HTTPS,并包括对 HTTP/2 的支持。 HTTPS 是一种用于保护您的用户和服务器之间的流量的系统,并且正在迅速成为任何在生产中运行的网站的基本期望——没有它,如果用户尝试提交登录,Chrome 和 Firefox 会警告您的网站“不安全”信息。

以前,推荐的安装 Caddy 的方法是从 Caddy 项目网站下载预构建的二进制文件。 但是,最近 Caddy 许可工作方式的变化意味着您不再被允许将这些预构建的二进制文件用于商业目的,除非您支付许可费,即使您只是在企业内部使用 Caddy。 幸运的是,Caddy 源代码仍然是完全开源的,您可以自己构建 Caddy 以避免遇到许可问题。

在本教程中,您将从源代码构建 Caddy 并使用它来托管使用 HTTPS 保护的网站。 然后您将使用 Caddyfile 配置 Caddy,安装 Caddy 插件,并了解如何在新版本发布时升级您的安装。

先决条件

在开始本指南之前,您需要具备以下条件:

  • 根据我们的 初始服务器设置指南 配置的 Ubuntu 16.04 服务器。 您应该能够通过 SSH 连接到服务器,以具有 sudo 权限的非 root 用户身份登录,并使用 UFW 设置工作防火墙。
  • 设置为使用 DigitalOcean 的 DNS 管理的域名。 您可以从任何域名注册商处购买域名,并按照我们关于 将域指向 DigitalOcean 域名服务器 的指南通过 DigitalOcean 管理您的 DNS。
  • 从您的域指向您的服务器的“A”记录,如果您希望启用 IPv6,则可以选择“AAAA”记录。 我们的 使用 DigitalOcean 设置主机名的指南解释了如何执行此操作。
  • 您的服务器上安装的 Go 语言 工具链。 按照我们关于 如何安装 Go 1.6 的指南来设置 Go。 您还应该对如何编译 Go 代码以及 go 命令行工具的功能有所了解。 按照我们关于 Building Go Executables 的指南来了解这一点。

第 1 步 - 建造球童

在这一步中,您将获取 Caddy 的源代码并确保您能够编译它。 Caddy 是用 Go 编写的,所以使用 go get 命令行工具从 GitHub 获取 Caddy 的源代码并保存到 $GOPATH/src/github.com/mholt/caddy

go get github.com/mholt/caddy/caddy

go get 使用 Git 从 GitHub 克隆代码。 Git 是一个版本控制系统,这意味着它会在您进行更改时记录项目的状态,并允许您返回到项目历史中的任何先前状态。 默认情况下,go get 命令会下载最新版本的源代码,但最好使用 Caddy 的最新稳定版本,而不是最近添加到存储库的版本,这可能会在中途发布之间。 未发布的版本可能有错误或半实现、损坏的功能。 另一方面,最新的稳定版本更有可能正确编译和运行。

要查看所有以前的版本,首先导航到保存 Caddy 源的目录:

cd $GOPATH/src/github.com/mholt/caddy

接下来,使用 git tag 命令查看所有以前版本的 Caddy:

git tag

您将看到类似于以下内容的输出:

Outputv0.10.0
v0.10.1
v0.10.10
v0.10.11
v0.10.12
v0.10.2
v0.10.3
v0.10.4
v0.10.5
. . .

每当发布稳定版本的 Caddy 时,作者都会在 Git 中通过添加标签来表示这一点。 您可以使用 Git 将代码恢复到上一个稳定版本时的状态。 在输出中找到最高的版本号; 在撰写本文时,这是 v0.10.12

由于稍后您将修改源代码以安装一些插件,因此创建一个新的 分支 来存储您的更改。 在 Git 中,分支是同时处理不同版本代码的方式。 它们允许您在带有个人更改的代码版本和代码的“官方”版本之间切换。 要创建新分支,请使用 git checkout 命令切换分支。 -b 选项将指示 Git 从版本 v0.10.12 创建一个名称为 adding_plugins 的新分支。 将 adding_plugins 替换为您希望命名分支的任何名称,并将 v0.10.12 替换为您之前确定的最新稳定版本:

git checkout -b "adding_plugins" "v0.10.12"

这会将您的 Caddy 源代码版本恢复到上一个稳定版本,并且您将位于一个新分支中,您可以在其中保留对代码的更改。 当您将来更新 Caddy 时,您会将更改合并到这个新分支中。

至此,您已准备好使用 go install 工具将源代码编译为二进制文件来构建 Caddy。 虽然命令语法看起来像是从网站(github.com)安装 Caddy,但这实际上是指我们刚刚使用 Git 存储库的服务器上的本地路径([X207X ]):

go install github.com/mholt/caddy/caddy

编译源代码后,运行caddy命令启动服务器。 请注意,为了使其正常工作,您的 Go 路径应设置为 $GOPATH/bin,如先决条件中所述:

caddy

此命令将产生以下输出:

OutputActivating privacy features... done.
http://:2015
WARNING: File descriptor limit 1024 is too low for production servers. At least 8192 is recommended. Fix with "ulimit -n 8192".

警告暂时可以忽略,等我们设置好Caddy需要的各种配置文件后解决。 按 CTRL+C 退出该命令。

为了证明 Caddy 是从您的源代码构建的,请在 Caddy 源代码中添加一行以在运行 Caddy 时打印一些文本。 使用 nano 或您喜欢的编辑器打开 $GOPATH/src/github.com/mholt/caddy/caddy/caddymain/run.go。:

nano $GOPATH/src/github.com/mholt/caddy/caddy/caddymain/run.go

此文件处理传递给 Caddy 命令的所有选项,并且是运行 Caddy 时首先执行的操作之一。

找到 Run() 函数,并将突出显示的文本添加为大括号内的第一行。 这将打印出文本“Hello from Caddy!” 在服务器运行之前:

$GOPATH/src/github.com/mholt/caddy/caddy/caddymain/run.go

. . .
// Run is Caddy's main() function.
func Run() {
        fmt.Println("Hello from Caddy!")

        flag.Parse()

        caddy.AppName = appName
        . . .
}

CTRL + XY,然后按 ENTER 保存并关闭文件。 如果再次运行 go installcaddy 命令,您将在输出顶部看到添加到 Run() 函数的消息:

go install github.com/mholt/caddy/caddy
caddy
OutputHello from Caddy!
Activating privacy features... done.
http://:2015
WARNING: File descriptor limit 1024 is too low for production servers. At least 8192 is recommended. Fix with "ulimit -n 8192".

这样,您就成功地从源代码构建了 Caddy。 如果您愿意,可以从 $GOPATH/src/github.com/mholt/caddy/caddy/caddymain/run.go 中删除添加的行,但如果您这样做,则需要重新编译代码。 在下一步中,您将安装 Caddy 作为服务,使其在启动时自动启动,然后调整其所有权和权限设置以确保服务器的安全性。

第 2 步 — 安装 Caddy

现在您已经验证您能够构建 Caddy,是时候 配置 systemd 服务 以便在系统启动时自动启动 Caddy。 Systemd 是用于在 Linux 上管理进程的综合解决方案。 Caddy 安装了一个 caddy.service 文件,systemd 可以使用它来管理 Caddy 服务。 该服务文件对 Caddy 运行的环境做出了一些假设,因此在安装之前您可能需要更改一些内容。

首先,将 Caddy 二进制文件复制到 /usr/local/bin,这是不受 Ubuntu 包管理器管理且不是系统操作关键的二进制文件的标准位置:

sudo cp $GOPATH/bin/caddy /usr/local/bin/

接下来,将 Caddy 二进制文件的所有权更改为 root 用户。 请注意,虽然 root 将拥有 Caddy,但建议您不要使用 root 帐户运行 Caddy,因为如果 Caddy 中存在漏洞,这可能是一个主要的安全问题。 但是,让 root 拥有二进制文件将阻止其他帐户使用我们将设置的权限修改它。 这是可取的,因为如果另一个权限低于 Caddy 的进程受到损害,它将无法修改 Caddy 以获得对系统的更多控制:

sudo chown root:root /usr/local/bin/caddy

接下来,将二进制文件的文件权限设置为 755 — 这将赋予 root 文件的完全读/写/执行权限,而其他用户只能读取和执行它:

sudo chmod 755 /usr/local/bin/caddy

由于 Caddy 进程不会以 root 身份运行,Linux 将阻止它绑定到端口 :80:443(分别为 HTTP 和 HTTPS 的标准端口),因为这些是特权操作。 为了在 Web 上可见,Caddy 需要绑定到这些端口之一。 否则,用户将需要在其浏览器中将特定端口号添加到服务器的 URL 以查看它将提供的内容。

使用 setcap 命令可以让 Caddy 进程绑定到低端口,而无需以 root 身份运行。 setcap 对于使进程能够执行特定的特权操作而不给它完全的超级用户权限很有用。 cap_net_bind_service=+ep 指定您希望为进程提供 CAP_NET_BIND_SERVICE 权限,从而可以绑定到特权端口:

sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/caddy

为 Caddy 二进制文件设置权限后,创建一个目录,您将在其中存储 Caddy 的配置文件。 这些文件应保存在 /etc/ 的子目录中,这是文件系统层次结构标准推荐的配置文件位置:

sudo mkdir /etc/caddy

将此目录的所有者设置为 root,并将其组设置为 www-datawww-data 是运行 Web 服务器的标准用户帐户,也是运行 Caddy 的帐户。 以这种方式设置所有权将确保您对二进制文件具有读写访问权限(通过 root 帐户),并且 Caddy 进程也可以对其进行读写(因为它将作为 运行www-data),但其他用户将无权访问它。 当与 chown 一起使用时,-R 标志会更改 /etc/caddy 目录中所有子目录和文件的所有权,而不仅仅是目录本身:

sudo chown -R root:www-data /etc/caddy

在稍后的步骤中,本教程将介绍如何使用 Let's Encrypt 启用自动 TLS。 为此,创建一个目录来存储 Caddy 将获得的任何 TLS 证书,并为其赋予与 /etc/caddy 目录相同的所有权规则:

sudo mkdir /etc/ssl/caddy
sudo chown -R root:www-data /etc/ssl/caddy

Caddy 必须能够将证书写入此目录并从中读取以加密请求。 为此,修改 /etc/ssl/caddy 目录的权限,使其只能由 rootwww-data 访问:

sudo chmod 0770 /etc/ssl/caddy

接下来,创建一个目录来存储 Caddy 将托管的文件。 /var/www/ 是存储通过 HTTP 提供的文件的事实上的标准位置:

sudo mkdir /var/www

然后将目录的所有者和组设置为 www-data,这是 Ubuntu 上 Web 服务器操作的默认用户:

sudo chown www-data:www-data /var/www

Caddy 通过一个名为 Caddyfile 的文件进行配置; 将其视为类似于 Apache 中的 httpd.conf 或 Nginx sites-available 配置目录可能会有所帮助。 Caddy 的 systemd 服务将期望这个文件存储在 /etc/caddy 中,因此使用 touch 在那里创建 Caddyfile

sudo touch /etc/caddy/Caddyfile

要安装 Caddy 服务,请将 systemd 单元文件从 Caddy 源代码复制到 /etc/systemd/system,即 systemd 服务的位置。 这样做将使 systemd 能够发现和控制 Caddy 服务:

sudo cp $GOPATH/src/github.com/mholt/caddy/dist/init/linux-systemd/caddy.service /etc/systemd/system/

修改服务文件的权限,使其只能由其所有者 root 修改:

sudo chmod 644 /etc/systemd/system/caddy.service

接下来,使用 systemctl 命令行工具重新加载 systemd。 这将导致 systemd 检测到 Caddy 服务,尽管我们还不会运行它:

sudo systemctl daemon-reload

通过运行 systemctl status 检查 systemd 是否检测到 Caddy 服务:

sudo systemctl status caddy
Output● caddy.service - Caddy HTTP/2 web server
   Loaded: loaded (/etc/systemd/system/caddy.service; disabled; vendor preset: enabled)
   Active: inactive (dead)
     Docs: https://caddyserver.com/docs

如果您看到相同的输出,则 systemd 正确检测到 Caddy。

在为 Caddy 编写配置之前,此安装过程的最后一步是调整防火墙。 按照初始服务器设置指南中的规定,您应该已经使用 UFW 运行防火墙。 防火墙是保护服务器安全的重要工具,因为它允许您配置哪些端口可公开供任何外部方连接,以及哪些端口受保护而无法访问。 如果有其他进程暴露了服务器上的端口,防火墙会阻止这些进程被访问,从而减少攻击者破坏易受攻击软件的机会。

使用 ufw 命令行工具禁用端口 :80:443 的防火墙,这将允许 Caddy 分别通过 HTTP 和 HTTPS 进行通信:

sudo ufw allow 80
sudo ufw allow 443

使用 ufw status 检查您的更改是否有效:

sudo ufw status
OutputStatus: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
80                         ALLOW       Anywhere
443                        ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
80 (v6)                    ALLOW       Anywhere (v6)
443 (v6)                   ALLOW       Anywhere (v6)

您的 Caddy 安装已完成,但此时尚未设置为执行任何操作。 接下来,我们将了解如何进行 Caddy 的全新安装并将其配置为服务于网站。

第 3 步 — 配置 Caddy

为了将您的 Caddy 安装用作功能性 Web 服务器,需要更改一些设置。 在进行这些更改时,我们将考虑 Caddyfile 配置的语法,探索几个配置方案,并通过 HTTP 提供占位符页面。

要开始配置 Caddy,请创建一个基本的 HTML 文件以供其使用。 HTML 是描述网页内容的语言,该文件将用作占位符,以演示使用 Caddy 托管网站。 如果您决定使用 Caddy 托管您自己的网站,您将使用您想要托管的任何内容替换此文件。 将此文件放在您之前设置的 /var/www/ 目录中。 名称 index.html 很重要,因为它指的是大多数 Web 服务器的“默认”页面,并且导航到您的域的用户将首先获得此文件:

sudo touch /var/www/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>

这将显示带有文本“此页面正在通过 Caddy 提供服务”的标题。

保存并关闭文件,然后打开您之前创建的 Caddyfile 配置文件:

sudo nano /etc/caddy/Caddyfile

编辑文件以包含以下内容:

/etc/caddy/Caddy 文件

:80 {
    root /var/www
}

在第一行,:80 设置服务器的主机名——在 Caddy 中,这称为 label。 主机名是 Caddy 将响应请求的域名。 在这种情况下,将其设置为:80,即服务器的端口:80。 这会暂时阻止服务器通过 HTTPS 运行,因为 Caddy 会尝试自动启用此功能,但我们希望通过插件来实现。

默认情况下,Caddy 会尝试通过 HTTP 提供资源(例如托管文件)来从 Let's Encrypt 获取 SSL 证书。 但是,如果您想使用 Caddy 运行内部服务,您可能不想将服务器公开到公共 Internet。 使用插件允许您使用 Let's Encrypt DNS 质询。 这涉及 Caddy 创建 DNS “TXT”记录以证明对服务器的控制,并允许您获取证书而不必接受外部 HTTP 请求。 这为您在未来如何运行 Caddy 提供了更多选择。

:80 之后是一个配置块,用大括号括起来,站点的配置将放在其中。 在下一行,我们看到了 root 指令。 指令是 Caddy 的实际配置选项,添加它们会改变 Caddy 在为网站提供服务时的行为。 指令可以有 arguments,它们是指令应该如何生效的选项。 在这种情况下,root 指令有一个参数:/var/www。 该指令设置 Caddy 应该服务的文件所在的目录。 但是,指令不需要有参数。 例如,您可以添加不带任何参数的 gzip 指令来在将网页发送到客户端之前对其进行压缩,从而加快它们的加载速度。

/etc/caddy/Caddy 文件

:80 {
    root /var/www
    gzip
}

指令可以配置有提供附加功能的子指令。 它们被放置在它们自己的配置块中,同样使用花括号。 例如,虽然 gzip 指令独立工作,但我们可以使用 ext 子指令来仅压缩某些文件类型,或者使用 level 子指令来控制压缩级别将发生(1 为最低,9 为最高)。

/etc/caddy/Caddy 文件

:80 {
    root /var/www
    gzip {
        ext .html .htm .php
        level 6
    }
}

Caddy 为许多用例提供了大量不同的指令。 例如,fastcgi 指令可用于启用 PHP。 markdown 指令可用于在提供之前自动将 Markdown 文件转换为 HTML,这对于创建简单的博客很有用。

保存并关闭 Caddyfile,并测试一切是否正常。 使用 systemctl 启动 Caddy 服务:

sudo systemctl start caddy

接下来,运行 systemctl status 以查找有关 Caddy 服务状态的信息:

sudo systemctl status caddy

您将看到以下内容:

Output● caddy.service - Caddy HTTP/2 web server
   Loaded: loaded (/etc/systemd/system/caddy.service; disabled; vendor preset: enabled)
   Active: active (running) since Sat 2018-01-27 11:37:06 UTC; 7min ago
     Docs: https://caddyserver.com/docs
 Main PID: 2973 (caddy)
    Tasks: 6
   Memory: 3.2M
      CPU: 24ms
   CGroup: /system.slice/caddy.service
           └─2973 /usr/local/bin/caddy -log stdout -agree=true -conf=/etc/caddy/Caddyfile -root=/var/tmp

Jan 27 11:37:06 caddy-tutorial-testing-0 systemd[1]: Started Caddy HTTP/2 web server.
Jan 27 11:37:06 caddy-tutorial-testing-0 caddy[2973]: Activating privacy features... done.
Jan 27 11:37:06 caddy-tutorial-testing-0 caddy[2973]: http://
Jan 27 11:37:06 caddy-tutorial-testing-0 caddy[2973]: 2018/01/27 11:37:06 http://

如果您浏览到您的域,您现在应该会看到 Caddy 正在运行,并且应该显示您的示例网页。 确认后,使用 systemctl 停止 Caddy 服务,因为仍有一些更改:

sudo systemctl stop caddy

虽然 Caddy 默认包含很多指令,但它不能满足所有可能的用例,您可能希望向服务器添加更多功能。 现在我们知道 Caddy 正在按预期提供内容,我们将讨论如何通过使用插件来扩展 Caddy 的功能。

第 4 步 — 使用插件

插件是改变 Caddy 行为的一种方式。 它们通常是我们可以插入到 Caddy 中的小代码片段,以便为特定用例添加更多指令。 了解插件最简单的方法是直接进入并尝试一个,所以我们将安装 minify 插件。 这个插件从一些文件中删除了多余的空格和冗余代码,减少了每个文件的大小,再次帮助加快加载时间。

首先返回 Go 保存 Caddy 源代码的位置,因为您需要修改它来安装插件:

cd $GOPATH/src/github.com/mholt/caddy

再次打开 Caddy 的 run.go 文件。 正如我们之前所说,这是要运行的 Caddy 的第一部分之一,它是安装插件的位置。

nano caddy/caddymain/run.go

在此文件中,您将看到如下所示的 import 声明:

$GOPATH/src/github.com/mholt/caddy/caddy/caddymain/run.go

. . .
import (
    "errors"
    "flag"
    "fmt"
    "io/ioutil"
    "log"
    "os"
    "runtime"
    "strconv"
    "strings"

    "gopkg.in/natefinch/lumberjack.v2"

    "github.com/xenolf/lego/acmev2"

    "github.com/mholt/caddy"
    // plug in the HTTP server type
    _ "github.com/mholt/caddy/caddyhttp"

    "github.com/mholt/caddy/caddytls"
    // This is where other plugins get plugged in (imported)
)
. . .

要安装插件,请将 _ "github.com/path/to/plugin" 添加到此 import 指令。 有些插件可能需要一些细微的配置调整,因此请务必阅读您安装的任何插件的文档。 您可以在 Caddy 文档 的左侧窗格中的 Plugins 下找到流行插件的列表。

minify 插件的 GitHub 存储库是 hacdias/caddy-minify,因此在导入声明的底部添加以下内容:

$GOPATH/github.com/mholt/caddy/caddy/caddymain/run.go

. . .
import (
    . . .
    "github.com/mholt/caddy/caddytls"
    // This is where other plugins get plugged in (imported)

    _ "github.com/hacdias/caddy-minify"
)

您需要在对代码进行更改时提交代码,以便在合并任何新更新时这些更改不会丢失。 如果您之前没有在此服务器上提交过代码,则需要设置名称和电子邮件,以便 Git 可以在日志中识别您。 git config 命令允许您设置这些选项,并且 --global 标志将它们应用于您将来可能使用的任何存储库。 除非您将代码推送到 GitHub 等公共存储库,否则这些详细信息不会公开。

git config --global user.email "sammy@example.com"
git config --global user.name "Sammy"

现在您已经设置了您的用户名和电子邮件,通过运行以下命令将您更改的所有文件添加到 Git 的 stage(用于在您提交之前存储代码状态的缓存):

git add -A .

现在运行 git commit 将您的更改保存到当前分支。 -m 选项允许您设置提交消息,以便您可以记下您所做的更改。 通过查看 Git 的日志可以找到此消息:

git commit -m "Added minify plugin"

现在,您的代码中已经有了插件的路径,但您仍然需要在本地下载插件,以便 Go 可以实际访问它。 从 $GOPATH/src/github.com/mholt/caddy 目录运行时,此命令将自动获取 Caddy 的所有依赖项:

go get ./...

每次添加新插件时,都必须重新构建 Caddy。 这是因为 Go 是一种编译型编程语言,这意味着在执行之前将源代码转换为机器码。 您对导入声明的更改已更改源代码,但在编译之前不会影响二进制文件。

使用 go install 命令编译 Caddy:

go install github.com/mholt/caddy/caddy

如果 Caddy 构建成功,此命令将退出且无输出。 将生成的二进制文件复制到 /usr/local/bin 并像以前一样设置二进制文件的权限 - 每次重建 Caddy 时都必须执行这些步骤以确保其功能和安全性。

sudo cp $GOPATH/bin/caddy /usr/local/bin/
sudo chown root:root /usr/local/bin/caddy
sudo chmod 755 /usr/local/bin/caddy
sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/caddy

要证明插件已成功安装,请打开您的 Caddyfile

sudo nano /etc/caddy/Caddyfile

通过将以下行添加到配置块来启用插件:

/etc/caddy/Caddy 文件

:80 {
    root /var/www
    gzip
    minify
}

现在使用 systemctl 启动你的服务器:

sudo systemctl start caddy

Caddy 现在正在运行,并将缩小它提供的所有文件,包括您之前创建的 index.html 文件。 您可以使用 cURL(用于发出 Web 请求的命令行工具)观察工作中的“缩小”。 在没有选项或标志的情况下运行 curl 将获取网页内容并将其显示在终端中。 运行以下命令从 Caddy 请求 index.html 文件,将 example.com 替换为您的域。

curl http://example.com

您将看到以下输出。 请注意,所有不必要的空间都已被删除,表明 minify 插件已经工作。

Output<!doctype html><title>Hello from Caddy!</title><h1 style=font-family:sans-serif>This page is being served via Caddy</h1>

同样的安装方法也适用于其他 Caddy 插件。 通过安装 tls.dns.digitalocean 插件来自动启用安全的 HTTPS 流量,您将获得更多关于添加插件的练习。

第 5 步 — 使用 Let's Encrypt 启用自动 TLS

Caddy 默认使用 Let's Encrypt 启用 HTTPS,这很有用,因为很容易弄错 HTTPS 的详细信息。 Caddy 的 HTTPS 方法是安全的,不会强迫您深入研究配置来加密您的流量。 但是,Caddy 默认使用 HTTP-01 方法来使用 Let's Encrypt 验证您是否真正拥有您的域。 此方法涉及将特殊文件(包含对 Let's Encrypt 发送的质询的响应)发布到网站上的特定位置。 虽然此方法有效,但它要求您的网站可公开访问。 这可能是某些防火墙配置的问题,或者如果您将 Caddy 作为企业的内部服务运行。

作为替代方案,您可以安装 tls.dns.digitalocean Caddy 插件,它将使用 DNS-01 验证方法代替。 该插件通过为您的域添加新的“TXT”DNS 记录来使用 Let's Encrypt 进行身份验证,这不会影响您网站的运行方式。 它使用 DigitalOcean 的 API 来控制 DNS,即使您的服务器不可公开访问,您也可以灵活地获取证书。 有关不同类型 DNS 记录的更多信息,请阅读我们的 DigitalOcean DNS 简介

安装 tls.dns.digitalocean Caddy 插件的方法与您安装 minify 插件的方法几乎相同。 首先,打开 $GOPATH/src/github.com/mholt/caddy/caddy/caddymain/run.go

nano $GOPATH/src/github.com/mholt/caddy/caddy/caddymain/run.go

添加插件的位置:

$GOPATH/github.com/mholt/caddy/caddy/caddymain/run.go

. . .
import (
    . . .
    "github.com/mholt/caddy/caddytls"
    // This is where other plugins get plugged in (imported)

    _ "github.com/hacdias/caddy-minify"
    _ "github.com/caddyserver/dnsproviders/digitalocean"
)

要更新 Caddy,请导航到 Caddy 的源存储库并将更改提交到 Git:

cd $GOPATH/src/github.com/mholt/caddy
git add -A .
git commit -m "Add DigitalOcean DNS provider"

接下来,安装所有依赖项并构建 Caddy,就像您之前所做的那样:

go get ./...
go install github.com/mholt/caddy/caddy

确保通过 systemctl 停止 Caddy,然后通过复制新构建的 Caddy 二进制文件并再次设置其所有权和权限来完成插件的安装:

sudo systemctl stop caddy
sudo cp $GOPATH/bin/caddy /usr/local/bin/
sudo chown root:root /usr/local/bin/caddy
sudo chmod 755 /usr/local/bin/caddy
sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/caddy

接下来,配置 Caddy 以使用 DigitalOcean 的 API 来设置 DNS 记录。 导航到您的DigitalOcean帐户中的API选项卡并选择生成新令牌

为您的令牌指定一个描述性名称(例如 caddy-dns)并确保选择了 Write (optional)。 然后,按生成令牌

单击生成的令牌将其复制,并将其记录在您不会丢失的地方。 Caddy 需要访问这个令牌作为环境变量来配置 DigitalOcean 的 DNS。 systemd 的服务文件允许您定义要包含在进程环境中的环境变量。 编辑 /etc/systemd/system/ 目录下的 Caddy 服务文件,而不是 Caddy Git 存储库中的版本。 将您的 API 密钥添加到 Git 存储库之外的文件版本,以避免意外将私有令牌提交到公共 Caddy 存储库:

sudo nano /etc/systemd/system/caddy.service

[Service] 部分中找到以 Environment= 开头的行。 这一行定义了应该传递给 Caddy 进程的环境变量。 在这一行的末尾添加一个空格,然后添加一个 DO_AUTH_TOKEN 变量,然后是您刚刚生成的令牌:

/etc/systemd/system/caddy.service

[Service]
Restart=on-abnormal

; User and group the process will run as.
User=www-data
Group=www-data

; Letsencrypt-issued certificates will be written to this directory.
Environment=CADDYPATH=/etc/ssl/caddy DO_AUTH_TOKEN=your_token_here

保存并关闭此文件,然后像之前一样重新加载 systemd 守护程序以确保更新配置:

sudo systemctl daemon-reload

运行 systemctl status 以检查您的配置更改是否正常:

sudo systemctl status caddy

这将产生类似于以下内容的输出。 密切注意以 Loaded: 开头的行。 loaded 状态表示您对服务配置的更改成功。 如果在配置 systemd 服务时发生错误,此行将显示 error 状态以及 systemd 无法解释服务文件的解释。 下一行,从 Active: 开始说明服务是否正在运行。 因为您在此步骤的前面停止了 Caddy,所以显示 inactive。 运行 Caddy 时,将显示 enabledrunning

Output● caddy.service - Caddy HTTP/2 web server
   Loaded: loaded (/etc/systemd/system/caddy.service; disabled; vendor preset: enabled)
   Active: inactive (dead)
     Docs: https://caddyserver.com/docs

您需要对 Caddyfile 进行一些细微的更改,因此打开它进行编辑:

sudo nano /etc/caddy/Caddyfile

将突出显示的行添加到 Caddyfile,确保将 example.com 替换为您的域。 对主机名使用域而不仅仅是端口将导致 Caddy 通过 HTTPS 服务请求。 tls 指令配置 Caddy 在使用 TLS 时的行为,dns 子指令指定 Caddy 应该使用 DNS-01 系统,而不是 [X175X ]:

/etc/caddy/Caddy 文件

example.com {
    root /var/www
    gzip
    minify
    tls {
        dns digitalocean
    }
}

您的网站已准备好部署。 首先,用 systemctl 启动服务器,然后用 enable 启动它。 这会将 Caddy 配置为在启动时启动:

sudo systemctl start caddy
sudo systemctl enable caddy

如果您浏览到您的域,您应该会自动重定向到 HTTPS。

您的 Caddy 安装已完成且安全。 接下来,我们将看看如何在新版本发布时更新 Caddy。 当您使用包管理器安装软件时,更新它通常就像运行单个命令一样简单,并且操作系统通常可以自动安装安全更新。 但是,由于您已经从源代码构建了 Caddy,因此该过程有点复杂; 您需要从源代码的更新版本重建 Caddy,然后重新设置。

第 6 步 — 更新您的 Caddy 安装

保持软件更新是一项重要的安全实践,因为过时的软件通常存在漏洞。 运行最新版本的 Caddy 将保护您的服务器免受旧版本中可能存在的任何漏洞的危害。 在此步骤中,我们将了解如何在新版本发布时更新您的 Caddy 安装。 仅当将新版本的 Caddy 推送到 Caddy GitHub 存储库时,才应执行此步骤。

我们将使用 Git 来更新源代码的状态。 首先,切换到caddy源码目录:

cd $GOPATH/src/github.com/mholt/caddy

使用 git checkout 确保您在步骤 1 中创建的分支上:

git checkout adding_plugins

接下来,使用 git fetch 从远程存储库中提取更改。 当 Git 克隆 Caddy 存储库时,它会维护一个指向 上游存储库 的链接 - 更改起源的中心位置。 Git 通过名称 origin 引用上游存储库,因此您需要从源获取:

git fetch origin

对存储库的更改现在出现在您的系统上,存储在不同的分支下。 使用 git tag 查看最新版本,因为您仍应使用已发布的 Caddy 版本,而不是版本之间的代码:

git tag

和以前一样,浏览列表,直到找到最新版本。 Git 包含一个用于合并两个不同代码分支的工具——git merge。 键入以下内容以将最新版本的更改合并到您的工作分支中。 请务必将 adding_plugins 替换为您的分支名称,并将版本号替换为您刚刚确定的最新版本:

git merge adding_plugins v0.10.13

将出现一个编辑器,您可以保存并关闭它以完成合并。 但是,当 Git 无法确定两个不同版本的代码应该如何组合在一起时,可能会发生合并冲突。 如果发生这种情况,Git 会通知您,您需要手动编辑冲突文件,然后提交以解决冲突。

假设没有合并冲突,请通过您在本教程中遵循的相同过程重新安装 Caddy。 首先,使用 go install 重建二进制文件:

go install github.com/mholt/caddy/caddy

接下来,停止 Caddy 服务并复制新的二进制文件:

sudo systemctl stop caddy
sudo cp $GOPATH/bin/caddy /usr/local/bin/

设置二进制文件的权限:

sudo chown root:root /usr/local/bin/caddy
sudo chmod 755 /usr/local/bin/caddy
sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/caddy

最后,使用 systemctl 再次启动 Caddy 服务:

sudo systemctl start caddy

Caddy 将来会继续在启动时启动,因为它没有被禁用。 至此,Caddy 已成功更新到最新版本,并且应该可以继续工作而不会中断,至少在下一个版本之前是这样。

结论

按照本教程,您已经使用 Caddy 成功部署了一个网站。 一个好的下一步是找到一种在新版本的 Caddy 发布时收到通知的方法。 例如,您可以将 Atom 提要用于 Caddy 版本 ,或使用 Sibbell 等专用服务。 创建一个脚本来自动化更新服务器的过程也是一个好主意——你甚至可以将两者结合起来,创建一个构建工具,当有新版本时自动重建 Caddy。 否则,您可以浏览 Caddy 的文档 并了解如何最好地自定义它以满足您的需求。