caddy+https

2025/2/251762 字

使用 Caddy 实现 HTTPS 的个人记录

引言

最近,我有幸入手了一台 Mac mini,并借助 IPv6 搭建了自己的小型服务器,实现了动态域名解析(DDNS)。

虽然我的域名和网站已经上线,但使用的是不安全的 HTTP 协议。在得知 HTTP 数据传输是明文形式后,考虑到之前服务器曾遭受安全威胁的经历,我认为必须升级为 HTTPS 才能放心使用。

恰逢今天看到有评论提到 Caddy 能够自动获取 SSL 证书并支持自动续签,这着实让我眼前一亮。为了保障网站的安全性,我决定采用 Caddy 作为服务器的反向代理,替换掉原本使用的 Nginx,开启 HTTPS 之旅。

Caddy 的安装

首先,我在 macOS 上利用 Homebrew 这一强大的包管理工具,轻松安装了 Caddy。运行如下命令:

bash
brew install caddy

安装过程非常顺利,无需过多干预,很快便完成了。

初步配置 Caddy

安装完成后,我开始尝试配置 Caddy。基于我服务器上运行的多个服务,我编写了以下初始的 Caddyfile:

caddy
service1.example.com {
    reverse_proxy localhost:8090
}

service2.example.com {
    reverse_proxy localhost:9876
}

service3.example.com {
    reverse_proxy localhost:5244
}

随后,我启动了 Caddy:

bash
caddy run

然而,当我试图访问网站时,发现仍然无法访问。经过排查,我意识到这是因为家庭宽带的 443 端口被运营商拦截,导致外部无法通过 HTTPS 访问我的服务器。

端口修改策略

为了解决 443 端口被拦截的问题,我需要为 Caddy 配置非标准的 HTTP 和 HTTPS 端口。通过查阅资料,我了解到可以在 Caddyfile 中设置自定义端口,于是修改了配置文件:

caddy
{
    http_port  8080  # 修改默认 HTTP 端口为 8080
    https_port 8443  # 修改默认 HTTPS 端口为 8443
}

your-domain.com {
    reverse_proxy localhost:8090
}

再次启动 Caddy 后,我使用 https://your-domain.com:8443 访问网站,但仍未能成功。查看 Caddy 的日志,发现了如下错误信息:

plaintext
2025/02/24 15:35:37.870 ERROR   challenge failed        {"identifier": "ddns.hicky.top", "challenge_type": "tls-alpn-01", "problem": {"type": "urn:ietf:params:acme:error:malformed", "title": "", "detail": "Unable to contact \"ddns.hicky.top\" at \"240e:332:2a55:2900:47e:45e:8646:fb79\", no IPv4 addresses to try as fallback", "instance": "", "subproblems": null}}

原来,我的服务器只有 IPv6 公网地址,而 Let’s Encrypt 的 ACME 协议在验证时需要能够通过 IPv4 或 IPv6 地址访问服务器。由于我的服务器无法通过 IPv4 访问,ACME 协议的 tls-alpn-01 挑战失败,导致无法获取 SSL 证书。

DNS 验证解决方案

经过一番调查,我了解到可以通过 DNS 验证的方式获取 SSL 证书。DNS 验证的原理是通过向域名解析服务提供商的 DNS 服务器添加一条特定的 TXT 记录,证明对域名的所有权。这种方式无需通过服务器的 IP 地址进行验证,因此非常适合我的情况。

然而,原生的 Caddy 并不支持各种 DNS 服务的认证。为了实现这一功能,我需要使用 xcaddy 和第三方插件代码自行编译一个支持 DNS 验证的 Caddy 版本。

安装和配置 xcaddy

由于 Homebrew 不支持直接安装 xcaddy,我转而通过 Go 的模块管理功能来安装。运行以下命令:

bash
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest

安装完成后,我前往 caddy-dns 仓库 查找适合华为云 DNS 的插件,并使用以下命令编译带有该插件的 Caddy:

bash
xcaddy build --with github.com/caddy-dns/huaweicloud

编译完成后,我用新生成的 Caddy 二进制文件替换了旧版本的 Caddy。

配置 DNS 验证

接下来,我按照华为云 DNS 插件的文档配置了 Caddyfile,使用环境变量来提供域名解析账号的 ACCESS_KEY_ID 和 ACCESS_KEY_SECRET:

caddy
# globally
{
    acme_dns huaweicloud {
        access_key_id {env.HUAWEICLOUD_ACCESS_KEY_ID}
        secret_access_key {env.HUAWEICLOUD_SECRET_ACCESS_KEY}
    }
}

your-domain.com {
    reverse_proxy localhost:8090
}

同时,我将在 .env 文件中存储环境变量,并通过以下命令运行 Caddy:

bash
caddy run --envfile .env

运行后,我又遇到了新的问题,日志中显示:

plaintext
2025/02/25 03:11:40.211 INFO    panic: certificate worker: failed to get project id of region 'cn-south-1' automatically, X-IAM-Trace-Id=cache_cn-north-1_null_414765dccb7c61b4f82406a91e1b2824, confirm that the project exists in your account, or set project id manually: basic.NewCredentialsBuilder().WithAk(ak).WithSk(sk).WithProjectId(projectId).SafeBuild()

错误信息提示 Caddy 在自动获取指定区域(cn-south-1)的项目 ID 时失败了。我意识到这可能是因为我的华为云账户在该区域并没有创建项目。

解决区域问题

为了确认问题所在,我登录到华为云控制台,查看了我名下的项目列表,发现确实没有 cn-south-1 区域的项目。我拥有的项目及其所属区域如下:

  • 项目 ID:41279ad4fd3740c3aa5c584ca217d992,区域:cn-east-3(华东-上海一)
  • 项目 ID:ad810f61d17041109ee4a959141dbb92,区域:cn-north-4(华北-北京四)

由于插件默认尝试获取 cn-south-1 区域的项目 ID,而我并未在该区域创建项目,因此需要手动指定我实际使用的区域和项目 ID。

修改插件代码

我查看了华为云 DNS 插件的源代码,发现插件仅支持 ACCESS_KEY_ID 和 ACCESS_KEY_SECRET,并未提供直接设置区域和项目 ID 的选项。这让我一度陷入困境。

然而,我并未放弃。通过在插件仓库的 pull request 中搜索,我找到了一个支持自定义区域的版本。

于是,我下载了这个修改版的插件代码,重新编译了 Caddy,并更新了 Caddyfile:

caddy
{
    acme_dns huaweicloud {
        access_key_id {env.HUAWEICLOUD_ACCESS_KEY_ID}
        secret_access_key {env.HUAWEICLOUD_SECRET_ACCESS_KEY}
        region_id {env.HUAWEICLOUD_REGION_ID}
    }

    http_port  8080  # 修改默认 HTTP 端口为 8080
    https_port 8443  # 修改默认 HTTPS 端口为 8443
}

blog.hicky.top {
    reverse_proxy localhost:8090
}

ddns.hicky.top {
    reverse_proxy localhost:9876
}

nas.hicky.top {
    reverse_proxy localhost:5244
}

在 .env 文件中,我添加了如下环境变量:

env
HUAWEICLOUD_ACCESS_KEY_ID=your_access_key_id
HUAWEICLOUD_SECRET_ACCESS_KEY=your_secret_access_key
HUAWEICLOUD_REGION_ID=cn-east-4

最后,我再次运行 Caddy:

bash
caddy run --envfile .env

成功实现 HTTPS

经过一系列的努力和尝试,Caddy 终于成功通过 DNS 验证获取了 SSL 证书。现在,我的网站已经可以通过 HTTPS 协议安全地访问了。

(插一句,AList好用捏😋。界面好看好用,支持webdav协议,结合其它软件还可以实现本地挂载)

通过这次经历,我深刻体会到了 Caddy 的强大功能和灵活性,以及开源社区的力量。虽然在实现过程中遇到了不少困难,但在解决问题的过程中,我不仅学到了许多关于 HTTPS 和域名解析的知识,也提升了自己解决问题的能力。

💬 评论区

写评论

暂无评论,来发表第一条吧。

© 2026 Corn 的自留地