Skip to content

SSL Certificate Management #10

SSL Certificate Management

SSL Certificate Management #10

Workflow file for this run

name: SSL Certificate Management
on:
# 每月 1 号和 15 号凌晨 3 点执行
schedule:
- cron: "0 19 1,15 * *" # UTC 19:00 = 北京时间 03:00
# 支持手动触发
workflow_dispatch:
inputs:
force_renew:
description: "强制重新申请证书"
required: false
type: boolean
default: false
env:
DOMAINS: "xkcoding.com www.xkcoding.com blog.xkcoding.com"
EMAIL: "237497819@qq.com"
SERVER_CERT_PATH: "/opt/myblog/certbot/etc/live/xkcoding.com"
jobs:
ssl-manage:
runs-on: ubuntu-latest
steps:
- name: Install acme.sh
run: |
curl https://get.acme.sh | sh -s email=${{ env.EMAIL }}
echo "$HOME/.acme.sh" >> $GITHUB_PATH
- name: Configure Aliyun DNS API
run: |
~/.acme.sh/acme.sh --set-default-ca --server letsencrypt
# 写入环境变量供后续步骤使用
echo "Ali_Key=${{ secrets.ALIYUN_ACCESS_KEY_ID }}" >> $GITHUB_ENV
echo "Ali_Secret=${{ secrets.ALIYUN_ACCESS_KEY_SECRET }}" >> $GITHUB_ENV
- name: Issue/Renew Certificate
run: |
FORCE_RENEW="${{ github.event.inputs.force_renew }}"
# 构建域名参数
DOMAIN_ARGS=""
for domain in ${{ env.DOMAINS }}; do
DOMAIN_ARGS="$DOMAIN_ARGS -d $domain"
done
# 检查是否需要强制续期
FORCE_FLAG=""
if [ "$FORCE_RENEW" = "true" ]; then
echo "🔄 强制重新申请证书..."
FORCE_FLAG="--force"
fi
# 使用 DNS-01 验证申请/续期证书
echo "🔐 申请证书: ${{ env.DOMAINS }}"
~/.acme.sh/acme.sh --issue \
--dns dns_ali \
$DOMAIN_ARGS \
$FORCE_FLAG \
--debug || {
# 如果证书已存在且未到期,--issue 会失败,这是正常的
echo "ℹ️ 证书可能已存在且未到期"
}
- name: Deploy Certificate to Server
uses: appleboy/ssh-action@v1.2.0
with:
host: ${{ secrets.ALIYUN_HOST }}
username: ${{ secrets.ALIYUN_USER }}
key: ${{ secrets.ALIYUN_SSH_KEY }}
port: ${{ secrets.ALIYUN_PORT || 22 }}
script: |
echo "🚀 部署证书到服务器..."
# 创建证书目录
CERT_DIR="${{ env.SERVER_CERT_PATH }}"
mkdir -p "$CERT_DIR"
# 证书将通过 SCP 传输(下一步)
echo "✅ 证书目录已准备: $CERT_DIR"
- name: Prepare Certificate Files
run: |
CERT_PATH="$HOME/.acme.sh/xkcoding.com_ecc"
# 检查 ECC 证书路径
if [ ! -f "$CERT_PATH/xkcoding.com.cer" ]; then
CERT_PATH="$HOME/.acme.sh/xkcoding.com"
fi
if [ ! -f "$CERT_PATH/xkcoding.com.cer" ]; then
echo "❌ 证书文件不存在"
ls -la $HOME/.acme.sh/
exit 1
fi
echo "📜 证书路径: $CERT_PATH"
# 创建工作区目录存放证书(SCP action 可以访问)
mkdir -p $GITHUB_WORKSPACE/certs
# 复制证书文件(使用 certbot 兼容的文件名)
cp "$CERT_PATH/xkcoding.com.cer" $GITHUB_WORKSPACE/certs/cert.pem
cp "$CERT_PATH/xkcoding.com.key" $GITHUB_WORKSPACE/certs/privkey.pem
cp "$CERT_PATH/fullchain.cer" $GITHUB_WORKSPACE/certs/fullchain.pem
cp "$CERT_PATH/ca.cer" $GITHUB_WORKSPACE/certs/chain.pem 2>/dev/null || cp "$CERT_PATH/fullchain.cer" $GITHUB_WORKSPACE/certs/chain.pem
# 设置权限让 SCP action 可以读取
chmod 644 $GITHUB_WORKSPACE/certs/*
echo "✅ 证书文件已准备"
ls -la $GITHUB_WORKSPACE/certs/
- name: Upload Certificate to Server
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.ALIYUN_HOST }}
username: ${{ secrets.ALIYUN_USER }}
key: ${{ secrets.ALIYUN_SSH_KEY }}
port: ${{ secrets.ALIYUN_PORT || 22 }}
source: "certs/*"
target: "${{ env.SERVER_CERT_PATH }}/"
strip_components: 1
- name: Reload Nginx
uses: appleboy/ssh-action@v1.2.0
with:
host: ${{ secrets.ALIYUN_HOST }}
username: ${{ secrets.ALIYUN_USER }}
key: ${{ secrets.ALIYUN_SSH_KEY }}
port: ${{ secrets.ALIYUN_PORT || 22 }}
script: |
echo "🔄 重新加载 Nginx 配置..."
# 检查证书文件
CERT_DIR="${{ env.SERVER_CERT_PATH }}"
if [ -f "$CERT_DIR/fullchain.pem" ] && [ -f "$CERT_DIR/privkey.pem" ]; then
echo "✅ 证书文件已就位"
ls -la "$CERT_DIR/"
# 重新加载 nginx(无需停止服务)
docker exec myblog-nginx nginx -s reload 2>/dev/null || {
echo "⚠️ Nginx reload 失败,尝试重启容器..."
docker restart myblog-nginx 2>/dev/null || true
}
echo "✅ Nginx 已重新加载证书"
else
echo "❌ 证书文件不完整"
ls -la "$CERT_DIR/" || true
exit 1
fi
- name: Verify HTTPS
run: |
echo "🔍 等待配置生效..."
sleep 10
echo "🔍 验证 HTTPS 访问..."
for domain in xkcoding.com www.xkcoding.com blog.xkcoding.com; do
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "https://$domain/" --max-time 10 || echo "000")
if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "301" ] || [ "$HTTP_CODE" = "302" ]; then
echo "✅ $domain: HTTPS 正常 (HTTP $HTTP_CODE)"
else
echo "⚠️ $domain: HTTP $HTTP_CODE"
fi
done
- name: Summary
if: always()
run: |
echo "## 🔐 SSL 证书管理" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **时间**: $(date +'%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_STEP_SUMMARY
echo "- **验证方式**: DNS-01 (Aliyun DNS)" >> $GITHUB_STEP_SUMMARY
echo "- **域名**: xkcoding.com, www.xkcoding.com, blog.xkcoding.com" >> $GITHUB_STEP_SUMMARY
echo "- **强制续期**: ${{ github.event.inputs.force_renew || 'false' }}" >> $GITHUB_STEP_SUMMARY