Confd 管理 Nginx 配置的正确 check_cmd 参数

最近在使用 Confd 管理配置的过程中,发现很多文章都使用了错误的 check_cmd 配置。


检查 Confd 生成的临时文件

例如,有人使用了这样的配置:

# ...
dest = "/etc/nginx/nginx.conf"
check_cmd = "/usr/sbin/nginx -t"

Confd 会在写入目标文件前,执行 check_cmd 配置的命令进行检查,但是 nginx -t 并不能检测到刚刚生成的临时文件。会导致以下情况:

  1. 如果 Nginx 的当前文件包含了错误,那么检查永远不通过;也就意味着 Confd 生成了正确的文件也不会生效,除非手动干预来修正 Nginx 当前文件中的错误。
  2. 如果 Nginx 的当前文件不包含错误,那么检查肯定是通过的;也就意味着即使 Confd 生成了错误的文件,也会写入到目标文件中;下一次生成配置文件时,会导致情况 1 发生。

所以正确的写法应该是:

dest = "/etc/nginx/nginx.conf"
check_cmd = "/usr/sbin/nginx -t -c {{.src}}"

{{.src}} 就是 Confd 生成的最新文件的临时路径,与 dest 在相同目录,比如可能是 /etc/nginx/.nginx.conf123456789 (123456789 是一个随机的数字)。

目标非 /etc/nginx/nginx.conf 的情况

如果 dest 是一个被 Nginx include 的文件,会发生什么呢?

# ...
dest = "/etc/nginx/conf.d/proxy.conf"
check_cmd = "/usr/sbin/nginx -t -c {{.src}}"

假设最终生成的 proxy.conf 内容是:

upstream a {
    server 192.168.1.1;
}
server{
    listen 80;
    server_name _;
    location /{
        proxy_pass http://a;
    }
}

最终执行的检查命令可能是:

/usr/sbin/nginx -t -c /etc/nginx/conf.d/.proxy.conf123456789

不出意外,还是永远检查失败。因为检查时把 -c 的参数当作是唯一的配置文件,配置文件里并没有 http;如果还用了 include,那么多半还会提示找不到文件错误。

这里存在两个问题,一是配置文件不完整,二是相对路径有错。

所以合理的做法应该是:为 .proxy.conf123456789 补充缺失的语句,并复制到 /etc/nginx,然后再调用 nginx -t -c /etc/nginx/.proxy.conf123456789

下面是一个经过验证的正确工作的例子:

check_cmd = "TMP=/etc/nginx/\(basename {{.src}}\).tmp && echo \'events\{\}http\{\'>TMP && cat {{.src}} >> TMP && echo \'\}\' >>TMP && \(nginx -t -c TMP; R=?; rm -f TMP; exitR\)"

具体过程是,将 /etc/nginx/conf.d/.proxy.conf123456789events{}http{} 包裹,输出到 /etc/nginx/.proxy.conf123456789.tmp 中,校验后删除这个临时文件。

使用 acme.sh 管理 Let’s Encrypt Wildcard SSL 证书

Certbot 可以申请 Wildcard 证书,但更新不便。

安装

curl https://get.acme.sh | sh

配置 API

编辑 ~/.bashrc ,加入以下内容(以 cloudflare 为例):

export CF_Key=”123456789″

export CF_Email=”[email protected]

保存后,执行:

source ~/.bashrc

申请证书

acme.sh –issue –dns dns_fs -d dallas.lu -d *.dallas.lu

值得一提的是,如果有多个域名,各自使用不同的 DNS,可以参考以下命令:

acme.sh –issue \
-d dallas.lu –dns dns_cf \
-d *.dallas.lu –dns dns_cf \
-d a.com –dns dns_namecom \
-d *.a.com –dns dns_namecom \
-d b.com –dns dns_dp \
-d *.b.com –dns dns_dp

安装证书

acme.sh –install-cert -d dallas.lu \
–key-file /etc/nginx/certs/dallas.lu.key \
–fullchain-file /etc/nginx/certs/dallas.lu.fullchain.cer \
–reloadcmd “service nginx restart”

一切配置妥当后,开启 acme.sh 的自动版本更新:

acme.sh --upgrade --auto-upgrade

SEARCH