DEBUG.WIKI
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

Caddy 报 unrecognized directive: dns:先把 tls 放进正确站点块

Caddyfile 转换报 unrecognized directive: dns,先核对站点、tls 与 dns 子块层级,再检查运行构建的提供商模块和证书验证阶段。

Caddy 启动时在 adapting config using caddyfile 阶段失败,随后提示 unrecognized directive: dns。Caddyfile 最前面写了 tls 邮箱地址 { ... },域名站点却放在后面时,先检查配置层级。解析器可能把 tls 和邮箱读成站点地址,随后把 dns 当作普通站点指令。

本文针对 Caddy 2 的 HTTP Caddyfile,且错误发生在配置转换阶段。DNS API 权限、TXT 传播和证书签发还没有因此得到验证;不要仅凭这个报错就更换 Cloudflare 令牌或关闭 TLS。

域名在站点块外,tls 和 dns 各有自己的层级

下面是使用 Cloudflare DNS 验证的结构示例。域名、邮箱、上游地址及环境变量名均需按实际部署调整:

wiki.example.com {
    tls admin@example.com {
        dns cloudflare {env.CLOUDFLARE_API_TOKEN}
    }
    reverse_proxy 192.0.2.10:80
}

站点地址 wiki.example.com 后打开站点块,tls 在其中,dns 再放入 tls 的子块。把 dns 移到 reverse_proxy 旁边,或者只多加一对外层花括号,都不会得到这个结构。

开括号应放在对应行末尾,前面留空格;闭括号单独一行。缩进帮助阅读,但实际层级由花括号确定。多个站点要分别界定块,不能靠空行结束前一个站点。

Caddyfile 可以在最前面有一个无站点名称的全局选项块,不过它只接收全局选项。全局的 email 与站点 tls 指令也不是同一个层级。这里修正的是 tls 下面的 DNS 配置位置,不能据此推断所有版本都不存在名称为 dns 的全局选项。

层级正确后,再核对运行二进制中的模块

使用与服务相同的二进制或容器查看模块:

caddy version
caddy list-modules

使用上述 Cloudflare 配置时,应有 dns.providers.cloudflare。DNS 提供商模块需要包含在 Caddy 构建中,写上名称不会自动安装。宿主机另一个 Caddy 有模块,也不能证明实际容器镜像有。

如果修正层级后变成模块未注册一类错误,检查镜像或构建的模块清单,再按现有版本管理流程准备包含所需模块的构建。保留旧镜像和配置,确认其他已有模块也被保留;不要为了加插件直接替换成版本和能力未知的二进制。

当前 Cloudflare 模块可从环境占位符读取 API Token,要求管理目标区域所需的 Zone Read 与 DNS Edit 权限。令牌必须对实际 Caddy 进程可见;交互终端设置过变量,不等于服务管理器或容器启动时也取得了它。核对时避免输出令牌本身。

转换成功与能够签发证书是不同检查

在受控环境中,可以先转换准备好的配置:

caddy adapt --config /etc/caddy/Caddyfile --adapter caddyfile

它用于发现层级和适配问题,不应用配置。输出的 JSON 可能含展开后的敏感值,只在受控终端查看,不公开完整结果。

模块加载和 provision 阶段仍可能出错。caddy validate 比仅转换更深入,但会实际 provision 模块;某些模块会获取独占资源,运行中的实例可能影响校验。按当前部署流程选择校验方式,不把它当成完全无副作用的文本检查。

对已运行服务,保存原配置后按现有管理方式重载。使用 caddy reload 需要可用的管理端点;不要因端点不可用临时停止全部站点。失败时查看具体阶段:语法错误、模块缺失、API 认证失败、DNS 传播或上游不可达分别处理,不通过关掉验证来掩盖后续错误。

成功标准是配置被实际运行实例接受,所需证书签发或加载正常,目标域名 HTTPS 访问及代理功能正常。回退时恢复原配置和必要的原镜像,保留证书存储;仅修正括号不能保证证书和后端同时恢复。