如何使用 acme.sh 优雅地给被 Nginx 反向代理的服务签发证书
2025年3月4日大约 2 分钟
博客在用的评论服务(Artalk),搜索服务(meilisearch),都是 Docker 部署,然后用 Nginx 反向代理,同时在 Nginx 中配置了 http 重定向 https。之前使用 acme.sh 签发证书的时候,我是先改 Nginx 的配置,让 80 端口放通,等签发成功之后,再改回原来的配置,这样导致证书的续期根本没法做自动化,而且每三个月这么来一次,非常地不方便,还容易改坏 Nginx 的配置,影响其它服务。在网上好一顿查,终于找到个优雅地方式,在此记录一下。
我的 Nginx 配置之前大概长这样:
server {
listen 80;
server_name example.ehnap.com;
location / {
rewrite ^(.*)$ https://$host$1 permanent;
}
}
server {
listen 443 ssl;
server_name test.ehnap.com;
ssl_certificate /home/example.ehnap.com_ecc/fullchain.cer;
ssl_certificate_key /home/example.ehnap.com_ecc/example.ehnap.com.key;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:66666;
}
}
第一时间想到底是用 acme.sh 的 --nginx 命令,但是我调整了很多次 nginx.conf 的写法,均提示我 nginx 配置错误,无法签发。在网上也没有找到解决方案,遂放弃。
又搜了一下,发现其实可以考虑对 acme.sh 签发证书时候的验证路径单独放通来实现这个需求。在 80 端口增加如下路径解析
location /.well-known/acme-challenge/ {
alias /var/www/example/.well-known/acme-challenge/;
}
完整的 conf 如下:
server {
listen 80;
server_name example.ehnap.com;
location /.well-known/acme-challenge/ {
alias /var/www/example/.well-known/acme-challenge/;
}
location / {
rewrite ^(.*)$ https://$host$1 permanent;
}
}
server {
listen 443 ssl;
server_name example.ehnap.com;
ssl_certificate /home/example.ehnap.com_ecc/fullchain.cer;
ssl_certificate_key /home/example.ehnap.com_ecc/example.ehnap.com.key;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:66666;
}
}
然后调用 acme.sh 脚本:
acme.sh --issue -d example.ehnap.com -w /var/www/example
即可正常签发证书。后续续期,只要把这条脚本加到定时任务里,三个月跑一次即可。可以在后边加上一个 --force 强制签发证书,达到续期的效果。
赞助