CreaRack-SL

DCA · Runbook de despliegue (Hetzner)

DCA · Runbook de despliegue (Hetzner)

DCA corre en un Hetzner CX23 (62.238.33.149, Ubuntu 26.04 LTS). La migración desde PythonAnywhere se cerró del todo (Fase 4, 2026-06-11): ya no queda nada de PA.

Stack de producción

ComponenteVersiónNota
Python3.14.4sistema y venv (/home/dca/dca/venv)
Flask3.0.3pin en requirements.txt
PyMuPDF1.27.2.3wheel abi3 manylinux cp314 → instala sin compilar
whitenoise6.12.0fijado
gunicorn26.0.0systemd --workers 4 --timeout 120

Gunicorn (4 workers) tras Nginx (reverse proxy, sirve estáticos directamente, client_max_body_size 25M) tras Cloudflare (proxy + Let’s Encrypt vía certbot-dns-cloudflare). En Cloudflare hay una Cache Rule (Bypass) para sw.js / js_modules/* / css/* → los deploys de código propagan solos.

Auto-deploy (lo normal)

Cada push a main (salvo docs-only) despliega solo en ~30 s vía un runner autoalojado de GitHub Actions en el propio Hetzner (~/actions-runner, etiqueta hetzner): conecta SALIENTE a GitHub (no hace falta abrir el firewall) y ejecuta deploy.sh localmente. Workflow: .github/workflows/deploy.yml.

  • Disparo manual: pestaña Actions → Run workflow.
  • Estado del runner: gh api repos/Esquembri/domo-channel-assistance/actions/runners.
  • Arranque persistente: crontab de usuario (@reboot + watchdog */5), sin root.

Deploy manual (si el runner falla)

ssh dca@62.238.33.149
bash /home/dca/dca/deploy/deploy.sh   # git pull + pip install + systemctl restart dca

El usuario dca solo tiene NOPASSWD para systemctl restart dca (no tiene sudo general). Para ver permisos reales: sudo -n -l (NO sudo -n true, que da falso negativo).

CI

.github/workflows/ci.yml (separado del deploy): instala requirements.txt + requirements-dev.txt en Python 3.14 y corre pytest en cada push/PR a main → caza la deriva “pin sin wheel” antes del deploy.

Arquitectura de la app: [[concept—dca-tech—arquitectura]].

Véase también

  • [[concept—dca-tech—overview]]
  • [[concept—dca-tech—arquitectura]]