From 097087519be1ba5f87e0b8303ed3008942b73c63 Mon Sep 17 00:00:00 2001 From: Niranjan Date: Tue, 7 Apr 2026 10:29:29 +0530 Subject: [PATCH] new changes --- .../app/api/__pycache__/ssl.cpython-314.pyc | Bin 9406 -> 12089 bytes YakPanel-server/backend/app/api/ssl.py | 101 +++++++++++++++--- YakPanel-server/backend/requirements.txt | 3 + 3 files changed, 88 insertions(+), 16 deletions(-) diff --git a/YakPanel-server/backend/app/api/__pycache__/ssl.cpython-314.pyc b/YakPanel-server/backend/app/api/__pycache__/ssl.cpython-314.pyc index 678fc7b3bc753690b7ea6d258fd30c3b6f69b79b..87744e90da1ed08739e9efa826dab38bb2be1c29 100644 GIT binary patch delta 5001 zcmbUlZERE5^}hG~{p~o3o!E|FK1eVm4usI~(RHLDk=>-hJhD)V6W57f5|6|-_q_mt z4yWs+0zxG8Ra=nQ;72!s)cvS3Ra$>c+q8+cbX5vWxDO`QsZ+J7(t-f3YkzF#KKq$K zVeNJ$pL_1T=j)z(?z!jrSCL;1+t%8wCIs!~scWet-qSV@wS2m%AxA|tqGlLzbVM80 ziMp^})Q1hCA%I|xi5SBs(WKy-h&gN#EefuUSi?5arr^4WJ?s!23a*bh!)0Qbf*T^P zaJg8n;KoQrxKgZCa8tw`_J|$@H%F@a!qsAR*eiOK2}{Hm_KW@i8q(Dw&dS+B6ld?C ziP;E=HC#Xpa1J-(oNhGf5LvDaaF>GD4%I}vrH{*8yUW|D0{xJ_77bNCFmkA)4K!B) zyp@D^l4>t7AhEszfnGPPc!q54OkrAV0NK4nc4w8!|249!L4x-o*^R1&8-0(KvVr3K zz*qASUlT{wqaeGeq1z}EF^T-{gr#jv{kB-qH3&6V7xw@iM>p&5k6H;k^EW~%>o6}) z<8*(JmNkzT&2&vx8qCpg8h~Jthj&3iSnx$e|RYXjuVjRP1+8Jr9vnoJm=|Q@wxR4w| z$cJJEl`d+MKDN80Z2^~WkXGGTBHl!Zy(ngrI`zI>EgGabEvMu3Aq{8X48!Gvh%J zIv&3f?N>Gec7b+HG$1+cuFa+O0E)4yQU~hkLMW@-o!ktbABU6hpN>SfHTuF+GDAJTzElBINBeYUp zN&jQ)Q{|NU2hHpK*L`t8%i$i57c!Fvcs7B@53pIxkEIT=Vur=jX?B#y;z&l^!tNbO zr4x8&h|OSj@AmABIFU&=vn^B2D#=ht)g^8JVDmMK|Z6m!_v z(sF>uLMoFUxF~7et8zg~)?^dn1f(u~LFfiqS3rVJOkOsb8Rtb=4kjl9x@w^hg$GMtMPy8L(S66;k48Cdtdr9w6z@h&`FTPrR#}8+dxhK%8tV-qqQ^J+i%XpnF%)h#^>! zY#@fm4)+wPBKQWJkQSyn(L-@ zOQv-fMrONi=}jjwp_@B;{OH2yb$i_vd)+c^Hac%Qs()mA)s}ab&nFim=Z`EoHsk~K z`HHH%r#fGrbKf=VoVH_~%Qob2&b@g2#fAOX>}=lST^KmOdCA?f>fB*ANi-~b7S7jf`D z1gXSMSSa3pHYKp>jL4?af|!_`aih%mhGNI8f?KJgUui5QB1A4-hJ+X;scRuXpHg01%mD;S+e+=!JcE*f!pl5plZNbDDVuc0{`PjY z@)(DxhhmiIQyOQDRjIgI^m2^)xiUcw>Np!`=NwQ5)1(ZxItR5}8Rz1l5RGccOs;~f zG1_pSO2wea zJqV6ZO8<6fDWlZl44B=8jRXB^snxlP@=5`RPulNvwfG(_!-CrAtZAh;227k^deiBp z)=HfLm%l~T77MAET60F%6AE)_KH4UE%WA2O(znW*TvgwN^l*rpW%{%xlr;~Sqa9MM z!yB*+Sk#k9ipohqQCVnvnxk8!H_QAF@mdG0(Qgqyx74VbRSDzUhy<<%d=}u?*tba~co-;goPZYy&=5e%5=>4MH%WUu z?2b-?l60YzUbvND>j;2v41`JC;`IPzoghLkz)BCw@J_M<1uMc(sUlKI@tDVb(%(G| zxm{#>4FTXY6tv@g1TWoVnHe1$m-UcMG6$h{VjvY^@&O0)Q^`W1r6JD%{vKf)R90~2 zpsdCGIG@G`U_u~D8yg$d`U?6&N|7CcAk9_T&2vET5}`zlbg}Aojn#kE8kp_5Wp>`Q zc`q>6+WW4y_g}N^STgMRv&kX7UcGLM*H*5(hiqouY}Z{DnVXbK3~B`J^VCgy)!fk& zNAnhY-W$j}EAr*;yu$@ml*4pPv+P-HCBvSZ<_hTrUq`OL ziMrqf@OD=xrbxPjvu%|A`uaf2hzC=-bfGG9Ne`1hN{K`Ct`A_cuu%{~#5XGX4hY z{l(Y(AJRIK-XR|LvF!!4Tly*6L*=E<*nqAWE6&>TEtrsT1dt1l;R}<*MFxv}GN@I~ zS2j$-+Zj)$pfV-_Dkv`ph#sk3qx}icUzSeS{*_{+zi8I99(J~pcbL3@t;J{#u9o%j zcrr5@j~9Y;BT=LTW%J_6Is-MaiA>xNS|!TJe6KxMan1&~(GRf&l z{we%(ScMyfgwFs#)kRSsp(k%3;|*lJft)vxN%}{9Tg9?QZ zNrGpA%$3BV60{`wa8F80^{qAKxMBA^d>vbZ>_SQ$D$yO0PnrGGwPB4Lm!WY-THShy~Vupmg)&IP+y9E8ua%i5! zgIRcrJQh4Jd?5g^=G=Kb_*WQpRy z@&IW?lTakyn4i2KwUb{&MNTXalT=~|#>gkp@rU9}tLNqZ>;RLdwza~-H-;Qqw#o@I z7mI!)+vDAzD=aU@sIZh6qjz)5<2}y(`My?pg8Vd=f>UHSmhnZtO>g#PxW%30ZJ=#i zwv}hdS|pmZFWbMo`-Ffl7khO2p$KIV^L%HYi6n zOkYWsMBYkdG9fwobqy8FadDtR3pn=~{cg{2D$EY;e3n>;Fh$DJGw^Zpwse(@r!dTt zzgvek)gyXQugJ$0CpBAGdal)J*7H)SsbN|Nl8U7fC4V6=t+lbF9y5EDF0D1|lG4;V zNMVYqCbgPUd2zXzKYu0EbBfiAN?mGosH2BxC$y{%u7r=_4U6d|) z=5kv_N?o^g8)>aoS7=wlwAzs|Qx)_uTZEPwKyK!ZHY)`w-A=$a)Qc+C`?MPQ&p>}{ zipjYP3P!AMvMzLvSsizWiFE&*Za)sJx~?{Lu6D6b8y?*+Vx1YW`ls7&UDA1^Tu_?m zDaz1X6o!X~$!0oj|1PCjr_eq%k$2MfY<)v_`!ZWk{8{voUk^^?<8HgKb^36?#eWMP zxWn65Z(QATxc8#TJ#S#oA3X4k-Sy;;?1IO3-F%qX86KL2!{fjaKLTdnf8dJlg`#`D z3r9TXwjBz<<3F@;R{xO*9Q|Z-xUji&68_9f;r8hW#rJ}7hBJ#fI{iMCK34#{<}{^u zM|=$DgB1VZU!11X9T6^_FyFC889fwYcnU7fn(r(yPw$5d6#wW=Fr2V3EaaA^xDV1E zhErzB`Ct~BmQIpFW(AIrmotO#+RjeqLzBR&pWc8QqtjjTG60m=koGfzjHH_e`9> w*s6CL$^v?w3fQ}#?Nd19AcP--`F&vB2hM%qC6)Z7<(~q5(hvRQC;3 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 diff --git a/YakPanel-server/backend/requirements.txt b/YakPanel-server/backend/requirements.txt index 793f3d7e..0dee7631 100644 --- a/YakPanel-server/backend/requirements.txt +++ b/YakPanel-server/backend/requirements.txt @@ -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