🔧 fix(deploy): 证书方案从 certbot 迁移到 acme.sh
- 证书目录改为可配置 CERT_DIR(默认 /etc/nginx/ssl),适配 acme.sh --install-cert 安装位置 - nginx 模板与提示文案同步去 certbot 依赖,ACME http-01 验证路径保持 webroot 兼容
This commit is contained in:
1 parent
af9004adaf
commit
3768ec0a31
2 files changed
+35
-37
No files matched your search
+3
-1
@@ -32,8 +32,10 @@ SRC_DIR="/root/code/novel/fanqie-go"
|
||||
DOMAIN="fq.20010117.xyz"
|
||||
|
||||
# ---------- 证书 ----------
|
||||
# Certbot 申请证书的邮箱,用于接收过期提醒
|
||||
# acme.sh 申请证书的邮箱,用于账户注册与过期提醒
|
||||
CERT_EMAIL="you@example.com"
|
||||
# 证书安装目录(acme.sh --install-cert 目标,nginx 配置从此处读取)
|
||||
# CERT_DIR="/etc/nginx/ssl"
|
||||
|
||||
# ---------- 编译 ----------
|
||||
# BUILD_TARGET="./cmd/fanqie"
|
||||
|
||||
@@ -40,6 +40,7 @@ NGINX_CONF="${NGINX_CONF:-/etc/nginx/conf.d/${APP_NAME}.conf}"
|
||||
APP_PORT="${APP_PORT:-40180}" # 程序监听端口
|
||||
DOMAIN="${DOMAIN:-fq.20010117.xyz}" # 域名
|
||||
CERT_EMAIL="${CERT_EMAIL:-admin@${DOMAIN}}" # 证书申请邮箱(过期提醒)
|
||||
CERT_DIR="${CERT_DIR:-/etc/nginx/ssl}" # 证书目录(acme.sh --install-cert 安装位置)
|
||||
BUILD_TARGET="${BUILD_TARGET:-./cmd/fanqie}" # go build 的包路径
|
||||
ENV_FILE="${ENV_FILE:-${SRC_DIR}/.env}" # 应用环境变量(.env.example 为模板)
|
||||
KEEP_VERSIONS="${KEEP_VERSIONS:-5}" # 保留最近几个版本
|
||||
@@ -245,8 +246,8 @@ restart_and_verify() {
|
||||
|
||||
|
||||
# 写入 nginx 配置(--init 与 --sync-nginx 共用的唯一模板来源)
|
||||
# 模板自带完整 443/证书配置(证书存在时启用),不依赖 certbot --nginx 注入——
|
||||
# 这样 --sync-nginx 覆盖配置时不会丢失 HTTPS 段(certbot 注入式配置会被覆盖回 80-only)
|
||||
# 模板自带完整 443/证书配置(证书存在时启用),不依赖签发工具注入——
|
||||
# 这样 --sync-nginx 覆盖配置时不会丢失 HTTPS 段(注入式配置会被覆盖回 80-only)
|
||||
write_nginx_conf() {
|
||||
# 反代 location(80 无证书时与 443 共用)
|
||||
local proxy_locations
|
||||
@@ -281,7 +282,7 @@ LOC_EOF
|
||||
)
|
||||
|
||||
local ssl_block=""
|
||||
if [ -f "/etc/letsencrypt/live/${DOMAIN}/fullchain.pem" ]; then
|
||||
if [ -f "${CERT_DIR}/${DOMAIN}/fullchain.pem" ]; then
|
||||
log "检测到 ${DOMAIN} 证书,配置启用 443"
|
||||
ssl_block=$(cat <<SSL_EOF
|
||||
|
||||
@@ -289,8 +290,8 @@ 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_certificate ${CERT_DIR}/${DOMAIN}/fullchain.pem;
|
||||
ssl_certificate_key ${CERT_DIR}/${DOMAIN}/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
|
||||
access_log /var/log/nginx/${APP_NAME}.access.log;
|
||||
@@ -300,7 +301,7 @@ ${proxy_locations}
|
||||
SSL_EOF
|
||||
)
|
||||
else
|
||||
warn "未找到 /etc/letsencrypt/live/${DOMAIN}/ 证书,本次仅写 80 配置(不跳转 HTTPS);证书签发后重跑: $0 --sync-nginx"
|
||||
warn "未找到 ${CERT_DIR}/${DOMAIN}/ 证书,本次仅写 80 配置(不跳转 HTTPS);证书签发后重跑: $0 --sync-nginx"
|
||||
fi
|
||||
|
||||
# 80 端口:有证书时仅 ACME 验证 + 301 跳转;无证书时直接反代
|
||||
@@ -321,7 +322,7 @@ server {
|
||||
access_log /var/log/nginx/${APP_NAME}.access.log;
|
||||
error_log /var/log/nginx/${APP_NAME}.error.log;
|
||||
|
||||
# ACME http-01 验证(certbot webroot 模式依赖)
|
||||
# ACME http-01 验证(acme.sh webroot 模式依赖)
|
||||
location /.well-known/acme-challenge/ {
|
||||
root /var/www/html;
|
||||
}
|
||||
@@ -506,36 +507,31 @@ EOF
|
||||
write_nginx_conf
|
||||
|
||||
|
||||
# ---- Certbot 续期后自动重载 Nginx(deploy-hook 只在续期成功时执行)----
|
||||
HOOK_FILE="/etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh"
|
||||
if [ ! -f "${HOOK_FILE}" ]; then
|
||||
log "创建 Certbot 续期重载 Hook: ${HOOK_FILE}"
|
||||
$SUDO mkdir -p /etc/letsencrypt/renewal-hooks/deploy/
|
||||
$SUDO tee "${HOOK_FILE}" >/dev/null <<'HOOK'
|
||||
#!/bin/bash
|
||||
if /usr/sbin/nginx -t 2>/dev/null; then
|
||||
systemctl reload nginx
|
||||
fi
|
||||
HOOK
|
||||
$SUDO chmod +x "${HOOK_FILE}"
|
||||
fi
|
||||
|
||||
# ---- 首次初始化自动申请 HTTPS 证书(一次性;续期由 certbot.timer 自动处理)----
|
||||
if [ ! -d "/etc/letsencrypt/live/${DOMAIN}" ]; then
|
||||
if command -v certbot >/dev/null 2>&1; then
|
||||
log "未检测到证书,尝试自动申请: ${DOMAIN}"
|
||||
$SUDO mkdir -p /var/www/html
|
||||
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
|
||||
warn "未安装 certbot,跳过证书申请。可手动执行: dnf install certbot python3-certbot-nginx"
|
||||
fi
|
||||
else
|
||||
# ---- 首次初始化自动申请 HTTPS 证书(一次性;续期由 acme.sh cron 自动处理)----
|
||||
if [ -f "${CERT_DIR}/${DOMAIN}/fullchain.pem" ]; then
|
||||
log "证书已存在,跳过申请"
|
||||
else
|
||||
# 定位 acme.sh:PATH → 当前用户目录 → root 目录(sudo 后 HOME 可能被重置)
|
||||
ACME_SH="$(command -v acme.sh 2>/dev/null || true)"
|
||||
for c in "${HOME}/.acme.sh/acme.sh" "/root/.acme.sh/acme.sh"; do
|
||||
if [ -z "$ACME_SH" ] && [ -x "$c" ]; then ACME_SH="$c"; fi
|
||||
done
|
||||
if [ -z "$ACME_SH" ]; then
|
||||
err "未找到 acme.sh,请先安装: curl https://get.acme.sh | sh -s email=${CERT_EMAIL}"
|
||||
exit 1
|
||||
fi
|
||||
log "未检测到证书,使用 acme.sh 申请: ${DOMAIN}"
|
||||
$SUDO mkdir -p /var/www/html "${CERT_DIR}/${DOMAIN}"
|
||||
if $SUDO "$ACME_SH" --issue -d "${DOMAIN}" -w /var/www/html --server letsencrypt --keylength ec-256 -m "${CERT_EMAIL}" \
|
||||
&& $SUDO "$ACME_SH" --install-cert -d "${DOMAIN}" --ecc \
|
||||
--fullchain-file "${CERT_DIR}/${DOMAIN}/fullchain.pem" \
|
||||
--key-file "${CERT_DIR}/${DOMAIN}/privkey.pem" \
|
||||
--reloadcmd "systemctl reload nginx"; then
|
||||
log "证书申请成功,写入 443 配置..."
|
||||
write_nginx_conf
|
||||
else
|
||||
warn "证书申请失败,请检查域名解析与 80 端口;成功后重跑: $0 --sync-nginx"
|
||||
fi
|
||||
fi
|
||||
|
||||
if command -v getenforce >/dev/null 2>&1 && [ "$(getenforce)" != "Disabled" ]; then
|
||||
|
||||
Reference in new issue
Block a user