🔧 fix(deploy): nginx 模板自带 443 配置,防止 --sync-nginx 覆盖证书段

- 原模板仅 80,443 依赖 certbot --nginx 注入,--sync-nginx 整文件覆盖会抹掉注入配置导致证书回退
- 检测 /etc/letsencrypt/live/<域名>/ 证书存在时自动启用 443,80 仅留 ACME 验证与 301 跳转
- certbot 改用 certonly --webroot,不再改写 nginx 配置;反代 location 抽取为 80/443 共享段
This commit is contained in:
chenxin committed 2026-10-10 01:14:05 +08:00
1 parent 096f6c222d
commit 803e6fb3fd
1 file changed
+63 -9
+63 -9
View File
@@ -212,14 +212,12 @@ restart_and_verify() {
# 写入 nginx 配置(--init 与 --sync-nginx 共用的唯一模板来源) # 写入 nginx 配置(--init 与 --sync-nginx 共用的唯一模板来源)
# 模板自带完整 443/证书配置(证书存在时启用),不依赖 certbot --nginx 注入——
# 这样 --sync-nginx 覆盖配置时不会丢失 HTTPS 段(certbot 注入式配置会被覆盖回 80-only)
write_nginx_conf() { write_nginx_conf() {
$SUDO tee "${NGINX_CONF}" >/dev/null <<NGINX_EOF # 反代 location(80 无证书时与 443 共用)
server { local proxy_locations
listen 80; proxy_locations=$(cat <<LOC_EOF
server_name ${DOMAIN};
access_log /var/log/nginx/${APP_NAME}.access.log;
error_log /var/log/nginx/${APP_NAME}.error.log;
# 视频解密代理:关闭缓冲,分片(Range/206)直通,避免 nginx 对大文件二次落盘 # 视频解密代理:关闭缓冲,分片(Range/206)直通,避免 nginx 对大文件二次落盘
location /video/proxy/ { location /video/proxy/ {
@@ -246,9 +244,60 @@ server {
proxy_read_timeout 300s; proxy_read_timeout 300s;
proxy_send_timeout 300s; proxy_send_timeout 300s;
} }
LOC_EOF
)
local ssl_block=""
if [ -f "/etc/letsencrypt/live/${DOMAIN}/fullchain.pem" ]; then
log "检测到 ${DOMAIN} 证书,配置启用 443"
ssl_block=$(cat <<SSL_EOF
server {
listen 443 ssl http2;
server_name ${DOMAIN};
ssl_certificate /etc/letsencrypt/live/${DOMAIN}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${DOMAIN}/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
access_log /var/log/nginx/${APP_NAME}.access.log;
error_log /var/log/nginx/${APP_NAME}.error.log;
${proxy_locations}
} }
SSL_EOF
)
else
warn "未找到 /etc/letsencrypt/live/${DOMAIN}/ 证书,本次仅写 80 配置(不跳转 HTTPS);证书签发后重跑: $0 --sync-nginx"
fi
# 80 端口:有证书时仅 ACME 验证 + 301 跳转;无证书时直接反代
local root_location
if [ -n "${ssl_block}" ]; then
root_location=' location / {
return 301 https://$host$request_uri;
}'
else
root_location="${proxy_locations}"
fi
$SUDO tee "${NGINX_CONF}" >/dev/null <<NGINX_EOF
server {
listen 80;
server_name ${DOMAIN};
access_log /var/log/nginx/${APP_NAME}.access.log;
error_log /var/log/nginx/${APP_NAME}.error.log;
# ACME http-01 验证(certbot webroot 模式依赖)
location /.well-known/acme-challenge/ {
root /var/www/html;
}
${root_location}
}${ssl_block}
NGINX_EOF NGINX_EOF
} }
# 更新已部署服务器的 nginx 配置:备份 → 重写 → 校验 → 失败回滚 # 更新已部署服务器的 nginx 配置:备份 → 重写 → 校验 → 失败回滚
sync_nginx_conf() { sync_nginx_conf() {
local backup="" local backup=""
@@ -428,8 +477,13 @@ HOOK
if [ ! -d "/etc/letsencrypt/live/${DOMAIN}" ]; then if [ ! -d "/etc/letsencrypt/live/${DOMAIN}" ]; then
if command -v certbot >/dev/null 2>&1; then if command -v certbot >/dev/null 2>&1; then
log "未检测到证书,尝试自动申请: ${DOMAIN}" log "未检测到证书,尝试自动申请: ${DOMAIN}"
$SUDO certbot --nginx -d "${DOMAIN}" --non-interactive --agree-tos -m "${CERT_EMAIL}" --redirect \ $SUDO mkdir -p /var/www/html
|| warn "证书申请失败,请检查域名解析与 80 端口;可稍后手动执行 certbot --nginx -d ${DOMAIN}" if $SUDO certbot certonly --webroot -w /var/www/html -d "${DOMAIN}" --non-interactive --agree-tos -m "${CERT_EMAIL}"; then
log "证书申请成功,写入 443 配置..."
write_nginx_conf
else
warn "证书申请失败,请检查域名解析与 80 端口;成功后重跑: $0 --sync-nginx"
fi
else else
warn "未安装 certbot,跳过证书申请。可手动执行: dnf install certbot python3-certbot-nginx" warn "未安装 certbot,跳过证书申请。可手动执行: dnf install certbot python3-certbot-nginx"
fi fi