diff --git a/backend/routers/admin.py b/backend/routers/admin.py index da2fd68..4fa6f3e 100644 --- a/backend/routers/admin.py +++ b/backend/routers/admin.py @@ -658,7 +658,7 @@ async def admin_setup_script( domain: str, server_name: str, os: str = "linux", - authorization: str = Header(None), + token: str = "", db: AsyncSession = Depends(get_db), _: bool = Depends(require_auth), ): @@ -673,18 +673,13 @@ async def admin_setup_script( ext = "ps1" if os == "windows" else "sh" download_url = f"{base_url}/admin/api/script/download?domain={domain}&server_name={server_name}&os={os}" - # 提取 admin token 用于嵌入脚本 - admin_token = "" - if authorization and authorization.startswith("Bearer "): - admin_token = authorization[7:] - template_name = "setup-cert.ps1.j2" if os == "windows" else "setup-cert.sh.j2" tpl = jinja_env.get_template(template_name) script = tpl.render( domain=domain, server_name=server_name, download_url=download_url, - admin_token=admin_token, + admin_token=token, ) filename = f"setup-{domain.replace('*', '_')}.{ext}" return PlainTextResponse( diff --git a/backend/templates_cert/setup-cert.ps1.j2 b/backend/templates_cert/setup-cert.ps1.j2 new file mode 100644 index 0000000..cafbfa9 --- /dev/null +++ b/backend/templates_cert/setup-cert.ps1.j2 @@ -0,0 +1,58 @@ +$ErrorActionPreference = "Stop" + +# === CertCenter 一键部署脚本 === +# 域名: {{ domain }} +# 服务器: {{ server_name }} +# 生成时间: 由 CertCenter 管理后台生成 + +$Domain = "{{ domain }}" +$DeployScript = "C:\cert\deploy-$($Domain -replace '[*\.]','_').ps1" +$DownloadUrl = "{{ download_url }}" +$AdminToken = "{{ admin_token }}" +$LogFile = "C:\cert\cert-deploy.log" + +Write-Host "=== CertCenter 证书自动部署安装 ===" -ForegroundColor Cyan +Write-Host "域名: $Domain" +Write-Host "" + +# 跳过 TLS 证书验证 +[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true } + +# 1. 下载部署脚本 +Write-Host "[1/4] 下载部署脚本..." -ForegroundColor Yellow +New-Item -ItemType Directory -Force -Path "C:\cert" | Out-Null +Invoke-WebRequest -Uri $DownloadUrl -Headers @{Authorization="Bearer $AdminToken"} -OutFile $DeployScript -UseBasicParsing -SkipCertificateCheck +Write-Host " 已保存到: $DeployScript" + +# 2. 首次执行 +Write-Host "[2/4] 首次执行部署脚本..." -ForegroundColor Yellow +try { + & powershell -ExecutionPolicy Bypass -File $DeployScript + Write-Host " 首次部署成功" -ForegroundColor Green +} catch { + Write-Host " ⚠ 首次执行异常(可能是证书尚未申请),不影响计划任务设置" -ForegroundColor DarkYellow +} + +# 3. 写入计划任务 +Write-Host "[3/4] 配置计划任务(每小时执行一次)..." -ForegroundColor Yellow +$TaskName = "CertDeploy-$($Domain -replace '[*\.]','_')" +$Action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-ExecutionPolicy Bypass -File `"$DeployScript`"" +$Trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Hours 1) +Register-ScheduledTask -TaskName $TaskName -Action $Action -Trigger $Trigger -Force | Out-Null +Write-Host " 已创建计划任务: $TaskName" + +# 4. 验证 +Write-Host "[4/4] 验证计划任务..." -ForegroundColor Yellow +$task = Get-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue +if ($task) { + Write-Host " ✓ 计划任务已生效 (状态: $($task.State))" -ForegroundColor Green +} else { + Write-Host " ✗ 计划任务设置失败,请手动创建" -ForegroundColor Red +} + +Write-Host "" +Write-Host "=== 安装完成 ===" -ForegroundColor Cyan +Write-Host "日志文件: $LogFile" +Write-Host "查看日志: Get-Content $LogFile -Tail 50" +Write-Host "手动执行: powershell -ExecutionPolicy Bypass -File `"$DeployScript`"" +Write-Host "查看任务: Get-ScheduledTask -TaskName '$TaskName'" diff --git a/backend/templates_cert/setup-cert.sh.j2 b/backend/templates_cert/setup-cert.sh.j2 new file mode 100644 index 0000000..ba241a3 --- /dev/null +++ b/backend/templates_cert/setup-cert.sh.j2 @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +set -euo pipefail + +# === CertCenter 一键部署脚本 === +# 域名: {{ domain }} +# 服务器: {{ server_name }} +# 生成时间: 由 CertCenter 管理后台生成 + +DOMAIN="{{ domain }}" +DEPLOY_SCRIPT="/opt/deploy-${DOMAIN//\*/}.sh" +DOWNLOAD_URL="{{ download_url }}" +AUTH_HEADER="Authorization: Bearer {{ admin_token }}" +LOG_FILE="/var/log/cert-deploy.log" + +echo "=== CertCenter 证书自动部署安装 ===" +echo "域名: ${DOMAIN}" +echo "" + +# 1. 下载部署脚本 +echo "[1/4] 下载部署脚本..." +curl -fsSLk -H "${AUTH_HEADER}" "${DOWNLOAD_URL}" -o "${DEPLOY_SCRIPT}" +chmod +x "${DEPLOY_SCRIPT}" +echo " 已保存到: ${DEPLOY_SCRIPT}" + +# 2. 首次执行 +echo "[2/4] 首次执行部署脚本..." +if "${DEPLOY_SCRIPT}"; then + echo " 首次部署成功" +else + echo " ⚠ 首次执行返回非零(可能是证书尚未申请),不影响定时任务设置" +fi + +# 3. 写入定时任务 +echo "[3/4] 配置定时任务(每小时执行一次)..." +CRON_LINE="0 * * * * ${DEPLOY_SCRIPT} >> ${LOG_FILE} 2>&1" +(crontab -l 2>/dev/null | grep -v "${DEPLOY_SCRIPT}"; echo "${CRON_LINE}") | crontab - +echo " 已添加: ${CRON_LINE}" + +# 4. 验证 +echo "[4/4] 验证定时任务..." +if crontab -l 2>/dev/null | grep -q "${DEPLOY_SCRIPT}"; then + echo " ✓ 定时任务已生效" +else + echo " ✗ 定时任务设置失败,请手动添加" +fi + +echo "" +echo "=== 安装完成 ===" +echo "日志文件: ${LOG_FILE}" +echo "查看日志: tail -f ${LOG_FILE}" +echo "手动执行: ${DEPLOY_SCRIPT}" +echo "查看任务: crontab -l" diff --git a/certcenter.service b/certcenter.service index 4209bbb..ef0e2e9 100644 --- a/certcenter.service +++ b/certcenter.service @@ -10,6 +10,8 @@ ExecStart=/usr/local/acme-auto/.venv/bin/python -m backend.main Restart=on-failure RestartSec=5 Environment=PYTHONUNBUFFERED=1 +StandardOutput=append:/var/log/certcenter.log +StandardError=append:/var/log/certcenter.log [Install] WantedBy=multi-user.target diff --git a/frontend/src/views/Domains.vue b/frontend/src/views/Domains.vue index 3420e72..6ccff93 100644 --- a/frontend/src/views/Domains.vue +++ b/frontend/src/views/Domains.vue @@ -291,6 +291,7 @@ const downloadSetupScript = async () => { domain: scriptDomain.value.domain, server_name: scriptDomain.value.server_name, os: scriptOs.value, + token: localStorage.getItem('admin_token') || '', }, responseType: 'blob', })