AC2100/fix-existing-cert-renewal.sh

115 lines
4.3 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# ============================================================
# 现有 VPS 证书过期 + 续期修复脚本
# 适用场景:用旧版 vless-ws-tls-setup.sh 部署的机器,
# 证书用 --standalone 申请nginx 起来后一直占 80 端口,
# 导致 certbot renew 从第一次续期起就必定失败。
#
# 本脚本做的事:
# 1. 找到已部署的域名(从 /etc/letsencrypt/live 里找)
# 2. 用 certbot 的 nginx 插件重新签发证书nginx 不需要停)
# 3. 把 renewal 配置里的 authenticator 改成 nginx 插件
# 4. 重写 cron 续期任务,加日志、用 deploy-hook
# 5. 跑一次 --dry-run 验证以后能不能正常自动续期
# ============================================================
set -e
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'
info() { echo -e "${CYAN}[INFO]${NC} $1"; }
success() { echo -e "${GREEN}[OK]${NC} $1"; }
warning() { echo -e "${YELLOW}[!]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
[ "$EUID" -ne 0 ] && error "请使用 root 用户运行"
# 1. 找域名
if [ -n "$1" ]; then
DOMAIN="$1"
else
DOMAIN=$(ls /etc/letsencrypt/live 2>/dev/null | grep -v README | head -1)
fi
[ -z "$DOMAIN" ] && error "找不到域名请手动指定bash $0 你的域名"
info "目标域名:$DOMAIN"
# 2. 确保 nginx 插件已安装
if ! dpkg -l | grep -q python3-certbot-nginx; then
info "安装 python3-certbot-nginx..."
apt-get update -qq && apt-get install -y -qq python3-certbot-nginx
fi
# 3. 检查 nginx 是否在跑(插件依赖 nginx 正常运行)
if ! systemctl is-active --quiet nginx; then
warning "nginx 当前未运行,先启动它"
systemctl start nginx || error "nginx 启动失败,请先手动修复 nginx 再运行本脚本"
fi
# 4. 用 nginx 插件强制重签证书(不停 nginx不改端口占用
info "用 nginx 插件重新签发证书(过程中不会中断现有连接)..."
EMAIL_GUESS=$(grep -oP '(?<=--email )\S+' /var/log/letsencrypt/letsencrypt.log 2>/dev/null | tail -1)
EMAIL_GUESS=${EMAIL_GUESS:-admin@${DOMAIN}}
certbot certonly --nginx \
--cert-name "$DOMAIN" \
-d "$DOMAIN" \
--non-interactive \
--agree-tos \
--email "$EMAIL_GUESS" \
--force-renewal \
|| error "证书重签失败请检查1. 域名解析是否指向本机 2. Cloudflare 是否切成灰色云朵仅DNS后再试"
success "证书重签成功"
# 5. 确认/修正 renewal 配置里的 authenticator
RENEWAL_CONF="/etc/letsencrypt/renewal/${DOMAIN}.conf"
if [ -f "$RENEWAL_CONF" ]; then
sed -i 's/^authenticator = .*/authenticator = nginx/' "$RENEWAL_CONF"
if grep -q '^installer = ' "$RENEWAL_CONF"; then
sed -i 's/^installer = .*/installer = nginx/' "$RENEWAL_CONF"
else
sed -i '/^\[renewalparams\]/a installer = nginx' "$RENEWAL_CONF"
fi
success "已确认 $RENEWAL_CONF 中 authenticator = nginx"
else
warning "未找到 $RENEWAL_CONF,续期方式可能没有正确记录,请手动检查"
fi
# 6. 重写 cron 续期任务
mkdir -p /var/log
touch /var/log/certbot-renew.log
cat > /etc/cron.d/certbot-renew << CRONEOF
# Let's Encrypt 证书自动续期 - 每周一凌晨3点执行
0 3 * * 1 root certbot renew --deploy-hook "systemctl reload nginx" >> /var/log/certbot-renew.log 2>&1
CRONEOF
chmod 644 /etc/cron.d/certbot-renew
systemctl restart cron
success "已重写 cron 续期任务,日志输出到 /var/log/certbot-renew.log"
# 7. 让 nginx 加载新证书
systemctl reload nginx
success "nginx 已重新加载新证书"
# 8. 验证以后能不能正常自动续期(这次 nginx 是开着的,应该会通过)
info "验证自动续期是否正常dry-runnginx 全程不会停)..."
if certbot renew --dry-run >> /var/log/certbot-renew.log 2>&1; then
success "续期验证通过!以后不会再出现到期后失效的问题"
else
warning "验证仍未通过,详情见 /var/log/certbot-renew.log请贴出来我再帮你看"
fi
CERT_PATH="/etc/letsencrypt/live/${DOMAIN}/fullchain.pem"
if [ -f "$CERT_PATH" ]; then
CERT_EXPIRY=$(openssl x509 -enddate -noout -in "$CERT_PATH" | cut -d= -f2)
echo ""
success "当前证书有效期至:$CERT_EXPIRY"
fi
echo ""
info "以后排查续期问题直接看日志cat /var/log/certbot-renew.log"