#!/usr/bin/env python3 """Deploy auto-SSL provisioner + nginx wildcard + enable Celery SSL env.""" from __future__ import annotations import base64 import sys from pathlib import Path import paramiko sys.stdout.reconfigure(encoding="utf-8", errors="replace") ROOT = Path(__file__).resolve().parents[1] PASS = "Moli@5404" REMOTE = "/home/morteza/torbatyar" def connect(host: str, user: str): c = paramiko.SSHClient() c.set_missing_host_key_policy(paramiko.AutoAddPolicy()) c.connect(host, username=user, password=PASS, timeout=30, allow_agent=False, look_for_keys=False) return c def run(c, cmd: str, *, sudo: bool = False, timeout: int = 300) -> str: if sudo: b64 = base64.b64encode(cmd.encode()).decode() full = f"echo {PASS!r} | sudo -S -p '' bash -c 'echo {b64} | base64 -d | bash'" else: full = cmd _, o, e = c.exec_command(full, timeout=timeout, get_pty=True) text = (o.read() + e.read()).decode("utf-8", "replace") print(text[-8000:] if len(text) > 8000 else text) return text def put_b64(c, remote_path: str, content: str) -> None: b64 = base64.b64encode(content.encode("utf-8")).decode("ascii") run(c, f"mkdir -p $(dirname {remote_path}) && echo {b64} | base64 -d > {remote_path}") def main() -> None: ngx = connect("192.168.10.156", "torbatyaruser") put_b64(ngx, "/tmp/torbatyar.ir.conf", (ROOT / "infrastructure/nginx/torbatyar.ir.conf").read_text(encoding="utf-8")) put_b64( ngx, "/tmp/torbatyar-tenant-ssl.map", (ROOT / "infrastructure/nginx/torbatyar-tenant-ssl.map").read_text(encoding="utf-8"), ) put_b64( ngx, "/tmp/provision_ssl.py", (ROOT / "infrastructure/nginx/provision_ssl.py").read_text(encoding="utf-8"), ) run( ngx, """ set -e cp /tmp/torbatyar.ir.conf /etc/nginx/conf.d/torbatyar.ir.conf cp /tmp/torbatyar-tenant-ssl.map /etc/nginx/conf.d/torbatyar-tenant-ssl.map mkdir -p /opt/torbatyar/bin cp /tmp/provision_ssl.py /opt/torbatyar/bin/provision_ssl.py chmod 755 /opt/torbatyar/bin/provision_ssl.py nginx -t systemctl reload nginx echo NGX_OK python3 /opt/torbatyar/bin/provision_ssl.py torbatkaracademy.torbatyar.ir """, sudo=True, timeout=360, ) ngx.close() app = connect("192.168.10.162", "morteza") for rel in [ "backend/core-service/app/core/config.py", "backend/core-service/app/services/ssl_provision.py", "backend/core-service/app/services/onboarding_service.py", "backend/core-service/app/services/domain_service.py", "backend/core-service/app/workers/tasks.py", "backend/core-service/requirements.txt", "infrastructure/nginx/torbatyar.ir.conf", "infrastructure/nginx/torbatyar-tenant-ssl.map", "infrastructure/nginx/provision_ssl.py", ".env.example", "infrastructure/deploy/.env.production.example", ".env", ]: put_b64(app, f"{REMOTE}/{rel}", (ROOT / rel).read_text(encoding="utf-8")) print("uploaded", rel) run( app, f""" set -e cd {REMOTE} docker compose exec -T celery-worker pip install -q 'paramiko==3.4.1' || true docker compose up -d --force-recreate core-service celery-worker celery-beat sleep 12 docker compose exec -T celery-worker pip install -q 'paramiko==3.4.1' docker compose exec -T celery-worker python -c "from app.workers.tasks import provision_domain_ssl; r=provision_domain_ssl.delay('torbatkaracademy.torbatyar.ir'); print('task', r.id); print(r.get(timeout=180))" curl -sS -m 10 http://127.0.0.1:8000/health || true echo echo DEPLOY_SSL_DONE """, timeout=420, ) app.close() if __name__ == "__main__": main()