new changes

This commit is contained in:
Niranjan
2026-04-07 10:47:27 +05:30
parent 8a08a95a17
commit cc45fac342
3 changed files with 61 additions and 26 deletions

View File

@@ -7,6 +7,7 @@ from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from pydantic import BaseModel
from typing import Optional
from app.core.database import get_db
from app.core.config import get_runtime_config
@@ -98,6 +99,27 @@ def _certbot_missing_message() -> str:
)
async def _le_hostnames_for_domain_row(db: AsyncSession, dom_row: Optional[Domain], primary: str) -> list[str]:
"""All distinct hostnames for the site (for -d flags). Falls back to primary."""
if not dom_row:
return [primary] if primary else []
result = await db.execute(select(Domain).where(Domain.pid == dom_row.pid).order_by(Domain.id))
rows = result.scalars().all()
seen: set[str] = set()
out: list[str] = []
for d in rows:
n = (d.name or "").strip()
if not n:
continue
key = n.lower()
if key not in seen:
seen.add(key)
out.append(n)
if primary and primary.lower() not in seen:
out.insert(0, primary)
return out if out else ([primary] if primary else [])
def _reload_panel_and_common_nginx() -> None:
"""Reload nginx so new vhost (ACME path) is live before certbot HTTP-01."""
cfg = get_runtime_config()
@@ -189,41 +211,53 @@ async def ssl_request_cert(
if not prefix:
raise HTTPException(status_code=500, detail=_certbot_missing_message())
cmd = prefix + [
"certonly",
"--webroot",
"-w",
webroot_norm,
"-d",
dom,
hostnames = await _le_hostnames_for_domain_row(db, dom_row, dom)
base_flags = [
"--non-interactive",
"--agree-tos",
"--email",
body.email,
"--preferred-challenges",
"http",
"--no-eff-email",
]
env = environment_with_system_path()
try:
proc = subprocess.run(
cmd,
capture_output=True,
text=True,
timeout=180,
env=env,
)
except FileNotFoundError:
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
cmd_webroot = prefix + ["certonly", "--webroot", "-w", webroot_norm, *base_flags]
for h in hostnames:
cmd_webroot.extend(["-d", h])
cmd_webroot.extend(["--preferred-challenges", "http"])
if proc.returncode != 0:
msg = (proc.stderr or proc.stdout or "").strip() or f"certbot exited with code {proc.returncode}"
cmd_nginx = prefix + ["certonly", "--nginx", *base_flags]
for h in hostnames:
cmd_nginx.extend(["-d", h])
env = environment_with_system_path()
proc: subprocess.CompletedProcess[str] | None = None
last_err = ""
for cmd, label in ((cmd_webroot, "webroot"), (cmd_nginx, "nginx")):
try:
proc = subprocess.run(
cmd,
capture_output=True,
text=True,
timeout=300,
env=env,
)
except FileNotFoundError:
raise HTTPException(status_code=500, detail=_certbot_missing_message()) from None
except subprocess.TimeoutExpired:
raise HTTPException(status_code=500, detail="certbot timed out (300s)") from None
if proc.returncode == 0:
break
chunk = (proc.stderr or proc.stdout or "").strip() or f"exit {proc.returncode}"
last_err = f"[{label}] {chunk}"
if proc is None or proc.returncode != 0:
msg = last_err or "certbot failed"
hint = (
" Check: DNS A/AAAA for this domain points to this server; port 80 is reachable; "
"the website is enabled in YakPanel; nginx on port 80 loads this sites vhost (same server as panel nginx if used)."
" Webroot and nginx plugins both failed. Check: "
"DNS A/AAAA for every -d name points to this server; port 80 reaches the nginx that serves these hosts; "
"site is enabled; install python3-certbot-nginx if the nginx method reports a missing plugin. "
"If you use a CDN proxy, pause it or use DNS validation instead."
)
raise HTTPException(status_code=500, detail=(msg + hint)[:8000])