diff --git a/backend/main.py b/backend/main.py
index fec0dc8..1d488a1 100644
--- a/backend/main.py
+++ b/backend/main.py
@@ -19,7 +19,7 @@ from backend.routers.admin import (
list_logs,
list_acme_configs, get_acme_config, create_acme_config, update_acme_config, delete_acme_config,
issue_cert, renew_cert, auto_renew_all, list_acme_logs, get_cert_info,
- download_cert_file, admin_generate_script, admin_download_script,
+ download_cert_file, admin_generate_script, admin_download_script, admin_setup_script,
)
logging.basicConfig(level=logging.DEBUG)
@@ -95,6 +95,7 @@ app.get("/admin/api/cert-info/{domain_id}")(get_cert_info)
app.get("/admin/api/cert-download/{domain_id}/{file_type}")(download_cert_file)
app.get("/admin/api/script")(admin_generate_script)
app.get("/admin/api/script/download")(admin_download_script)
+app.get("/admin/api/script/setup")(admin_setup_script)
logger.info("=== 路由注册完成 ===")
for route in app.routes:
diff --git a/backend/routers/admin.py b/backend/routers/admin.py
index 2ba1d5d..da2fd68 100644
--- a/backend/routers/admin.py
+++ b/backend/routers/admin.py
@@ -1,5 +1,5 @@
-from fastapi import APIRouter, Depends, HTTPException, Header, Cookie
-from fastapi.responses import JSONResponse
+from fastapi import APIRouter, Depends, HTTPException, Header, Cookie, Request
+from fastapi.responses import JSONResponse, PlainTextResponse
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func
from sqlalchemy.orm import selectinload
@@ -652,6 +652,47 @@ async def admin_download_script(
)
+@router.get("/script/setup")
+async def admin_setup_script(
+ request: Request,
+ domain: str,
+ server_name: str,
+ os: str = "linux",
+ authorization: str = Header(None),
+ db: AsyncSession = Depends(get_db),
+ _: bool = Depends(require_auth),
+):
+ """生成一键安装脚本(纯文本下载)"""
+ from jinja2 import Environment, FileSystemLoader
+
+ template_dir = Path(__file__).parent.parent / "templates_cert"
+ jinja_env = Environment(loader=FileSystemLoader(str(template_dir)))
+
+ settings = get_settings()
+ base_url = str(request.base_url).rstrip("/")
+ 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,
+ )
+ filename = f"setup-{domain.replace('*', '_')}.{ext}"
+ return PlainTextResponse(
+ script,
+ headers={"Content-Disposition": f'attachment; filename="{filename}"'},
+ )
+
+
# ──────────────── 证书信息 ────────────────
@router.get("/cert-info/{domain_id}")
diff --git a/frontend/src/views/Domains.vue b/frontend/src/views/Domains.vue
index af6f93b..3420e72 100644
--- a/frontend/src/views/Domains.vue
+++ b/frontend/src/views/Domains.vue
@@ -111,65 +111,31 @@
-
-
- curl -fsSLk -H "Authorization: Bearer {{ adminToken }}" {{ scriptDownloadUrl }} -o /opt/deploy-{{ scriptDomain?.domain?.replace('*.', '') }}.sh
- chmod +x /opt/deploy-{{ scriptDomain?.domain?.replace('*.', '') }}.sh
- /opt/deploy-{{ scriptDomain?.domain?.replace('*.', '') }}.sh && echo "0 * * * * /opt/deploy-{{ scriptDomain?.domain?.replace('*.', '') }}.sh >> /var/log/cert-deploy.log 2>&1" | crontab -
- Invoke-WebRequest -Uri "{{ scriptDownloadUrl }}" -Headers @{Authorization="Bearer {{ adminToken }}"} -OutFile "C:\cert\deploy-{{ scriptDomain?.domain?.replace('*.', '') }}.ps1" -SkipCertificateCheck
- powershell -ExecutionPolicy Bypass -File "C:\cert\deploy-{{ scriptDomain?.domain?.replace('*.', '') }}.ps1"
- powershell -ExecutionPolicy Bypass -File "C:\cert\deploy-{{ scriptDomain?.domain?.replace('*.', '') }}.ps1"; schtasks /create /tn "CertDeploy-{{ scriptDomain?.domain?.replace('*.', '') }}" /tr "powershell -ExecutionPolicy Bypass -File C:\cert\deploy-{{ scriptDomain?.domain?.replace('*.', '') }}.ps1" /sc hourly /f
-
+ 在服务器上执行安装脚本: +
+bash setup-{{ scriptDomain?.domain?.replace('*.', '') }}.sh
+ powershell -ExecutionPolicy Bypass -File setup-{{ scriptDomain?.domain?.replace('*.', '') }}.ps1
+