从 Nginx 换到 Caddy 之后,被 Caddyfile 的简洁优雅深深震撼了。特别是自动申请 SSL 证书的功能实在强大。

既然配置简化了,我们也可以尝试一些更优雅炫酷的配置方式,比如配置泛域名证书,我的期望是访问一个没有在 Caddyfile 中列出的 xxx.skywt.cn 会显示 404 页面。

泛域名证书

使用泛域名证书的另一个好处是,如果我需要解析新的子域名 abc.skywt.cn,不需要去阿里云设置 DNS 解析,直接在 Caddyfile 里加上这个域名的配置就可以,因为所有子域名默认都被解析到了这个服务器。

配置泛域名证书只能用 DNS challenge 的验证方式,需要在 DNS 提供商处设置指定的 TXT 记录。Caddy 的插件可以帮我们自动完成这一点。

在 Caddy 文档的 Common Caddyfile Patterns - Wildcard certificates 小节中介绍了配置泛域名证书的语法:

*.example.com {
    tls {
        dns <provider_name> [<params...>]
    }
    # ...
}

为了使 Caddy 支持我们使用的 DNS provider,需要使用对应的 Caddy 插件。我的 DNS 是阿里云(alidns),插件是这个 alidns

使用新的插件需要重新编译主程序。我们可以在官方的这个页面下载预装了对应 DNS 插件的 Caddy 二进制文件,也可以用 Xcaddy 这个「插件管理器」来自己编译。

用 Xcaddy 管理插件

官方的文档写得很清楚,安装好 xcaddy 后,为了编译一个带有 alidns 的 caddy,直接运行这个命令:

xcaddy build \
    --with github.com/caddy-dns/alidns

编译完成后就可以看到相同目录下多出了个 caddy 可执行文件,就是编译好的二进制文件。

替换安装目录下的 caddy 程序就可以了。安装目录一般是 /usr/bin/caddy,可以用 whereis caddy 查看。

配置 API Key

当然首先要在阿里云设置 DNS 解析,A 记录,解析 *.skywt.cn 到服务器 IP。

然后去阿里云控制台申请 API Key 和 Secret,在 Caddyfile 里写如下配置:

*.skywt.cn {
    tls {   
        dns alidns {
            access_key_id BALABALABALABALA
            access_key_secret BALABALABALABALA
                }
    }
    # ...
}

404 页面

我希望的结果是如果访问 xxx.skywt.cn,没有与 Caddyfile 配置的任何一个其他网站匹配,就显示 skywt.cn 目录下的 404.html,同时返回 404 状态码。

Caddy 的泛域名配置默认优先级最低(阿里云 DNS 也是),所以无需担心这个配置影响其他网站正常运行。

为了显示 404.html,可以 rewrite * /404.html

返回状态码则可以直接在 file_server 小节中加上 status 404。这个功能貌似是经过了一番讨论之后加上的。文档中的相关说明在这里

由于 404.html 引用了同目录下的资源文件,但是如果直接访问的话引用地址(如 //xxx.skywt.cn/assets)又没有进行重定向,资源会加载不出。解决方法是 redir /assets/* https://skywt.cn{uri}(当然 rewrite 也可以)。

404 页面放一句一言。有内味了。

404 页面的截图

Caddyfile

完整的 Caddyfile(部分)如下:

*.skywt.cn {
    tls {
        dns alidns {
            access_key_id BALABALABALABALA
            access_key_secret BALABALABALABALA
        }
    }
    redir /assets/* https://skywt.cn{uri}
    root * /data/www/skywt.cn
    rewrite * /404.html
    file_server {
        status 404
    }
}

skywt.cn {
    # ...
}

blog.skywt.cn {
    # ...
}