new changes
This commit is contained in:
Binary file not shown.
@@ -2,6 +2,7 @@
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy import select
|
||||
@@ -17,15 +18,83 @@ from app.services.site_service import regenerate_site_vhost
|
||||
|
||||
router = APIRouter(prefix="/ssl", tags=["ssl"])
|
||||
|
||||
_CERTBOT_PATH_CANDIDATES = (
|
||||
"/usr/bin/certbot",
|
||||
"/usr/local/bin/certbot",
|
||||
"/snap/bin/certbot",
|
||||
)
|
||||
|
||||
def _certbot_executable() -> str:
|
||||
w = shutil.which("certbot")
|
||||
if w:
|
||||
return w
|
||||
for p in ("/usr/bin/certbot", "/usr/local/bin/certbot"):
|
||||
if os.path.isfile(p):
|
||||
return p
|
||||
return "certbot"
|
||||
|
||||
def _certbot_command() -> list[str] | None:
|
||||
"""Resolve argv prefix to run certbot: [binary] or [python, -m, certbot]."""
|
||||
env = environment_with_system_path()
|
||||
path_var = env.get("PATH", "")
|
||||
|
||||
exe = getattr(sys, "executable", None) or ""
|
||||
if exe and os.path.isfile(exe):
|
||||
try:
|
||||
r = subprocess.run(
|
||||
[exe, "-m", "certbot", "--version"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=20,
|
||||
env=env,
|
||||
)
|
||||
if r.returncode == 0:
|
||||
return [exe, "-m", "certbot"]
|
||||
except (FileNotFoundError, OSError, subprocess.TimeoutExpired):
|
||||
pass
|
||||
|
||||
tried: list[str] = []
|
||||
w = shutil.which("certbot", path=path_var)
|
||||
if w and os.path.isfile(w):
|
||||
tried.append(w)
|
||||
|
||||
for p in _CERTBOT_PATH_CANDIDATES:
|
||||
if p not in tried and os.path.isfile(p):
|
||||
tried.append(p)
|
||||
|
||||
for exe in tried:
|
||||
try:
|
||||
r = subprocess.run(
|
||||
[exe, "--version"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=15,
|
||||
env=env,
|
||||
)
|
||||
if r.returncode == 0:
|
||||
return [exe]
|
||||
except (FileNotFoundError, OSError, subprocess.TimeoutExpired):
|
||||
continue
|
||||
|
||||
for py_name in ("python3", "python"):
|
||||
py = shutil.which(py_name, path=path_var)
|
||||
if not py or not os.path.isfile(py):
|
||||
continue
|
||||
try:
|
||||
r = subprocess.run(
|
||||
[py, "-m", "certbot", "--version"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=20,
|
||||
env=env,
|
||||
)
|
||||
if r.returncode == 0:
|
||||
return [py, "-m", "certbot"]
|
||||
except (FileNotFoundError, OSError, subprocess.TimeoutExpired):
|
||||
continue
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def _certbot_missing_message() -> str:
|
||||
return (
|
||||
"certbot is not installed or not reachable from the panel process. "
|
||||
"On the server, run one of: apt install certbot | dnf install certbot | yum install certbot | snap install certbot. "
|
||||
"Alternatively: pip install certbot (panel can use python3 -m certbot). "
|
||||
"If certbot is already installed, ensure /usr/bin is on PATH for the YakPanel service."
|
||||
)
|
||||
|
||||
|
||||
@router.get("/domains")
|
||||
@@ -75,9 +144,11 @@ async def ssl_request_cert(
|
||||
raise HTTPException(status_code=400, detail="Webroot must be under www_root or setup_path")
|
||||
|
||||
dom = body.domain.split(":")[0].strip()
|
||||
certbot_bin = _certbot_executable()
|
||||
cmd = [
|
||||
certbot_bin,
|
||||
prefix = _certbot_command()
|
||||
if not prefix:
|
||||
raise HTTPException(status_code=500, detail=_certbot_missing_message())
|
||||
|
||||
cmd = prefix + [
|
||||
"certonly",
|
||||
"--webroot",
|
||||
"-w",
|
||||
@@ -93,19 +164,17 @@ async def ssl_request_cert(
|
||||
"--no-eff-email",
|
||||
]
|
||||
|
||||
env = environment_with_system_path()
|
||||
try:
|
||||
proc = subprocess.run(
|
||||
cmd,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=180,
|
||||
env=environment_with_system_path(),
|
||||
env=env,
|
||||
)
|
||||
except FileNotFoundError:
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail="certbot not found. Install it (e.g. apt install certbot) and ensure it is on PATH.",
|
||||
) from None
|
||||
raise HTTPException(status_code=500, detail=_certbot_missing_message()) from None
|
||||
except subprocess.TimeoutExpired:
|
||||
raise HTTPException(status_code=500, detail="certbot timed out (180s)") from None
|
||||
|
||||
|
||||
@@ -20,6 +20,9 @@ python-dotenv>=1.0.0
|
||||
redis>=5.0.0
|
||||
celery>=5.3.0
|
||||
|
||||
# Let's Encrypt (optional if system certbot/snap not used; enables python -m certbot from panel venv)
|
||||
certbot>=3.0.0
|
||||
|
||||
# Utils
|
||||
psutil>=5.9.0
|
||||
croniter>=2.0.0
|
||||
|
||||
Reference in New Issue
Block a user