Despliegue continuo a un cPanel que no tiene rsync
Subir archivos por el administrador de archivos de cPanel o por FTP funciona para un sitio que cambia una vez al año. Para sistemas que se actualizan varias veces por semana, cada despliegue manual es una oportunidad de olvidar un archivo. Todos mis proyectos en hosting compartido se despliegan solos con cada cambio en la rama principal. Así está armado, incluso sin las herramientas que uno da por sentadas.
Una llave por proyecto
El flujo corre en GitHub Actions y se conecta al servidor por SSH. Cada proyecto tiene su propia llave, con un nombre que identifica el proyecto y su propósito. La llave privada se guarda solo como secreto del repositorio y no queda ninguna copia local después de configurarla. Si un repositorio se compromete, se revoca su llave sin afectar a los demás proyectos del mismo servidor.
Sin rsync: empaquetar y reemplazar
La herramienta habitual para sincronizar archivos es rsync,
y ese hosting no la tiene. La alternativa resultó ser más simple de
razonar:
- El flujo compila el sitio en el runner de GitHub.
- Empaqueta la carpeta de salida en un solo archivo comprimido.
- Lo sube con
scp. - En el servidor, borra el contenido anterior y extrae el paquete.
Reemplazar todo tiene una ventaja sobre sincronizar: no se acumulan archivos viejos. Los frameworks modernos generan nombres con hash para cada versión de CSS y JavaScript, y sin limpieza la carpeta crece con restos de despliegues anteriores.
Cuidado con lo que se borra
El paso de borrar merece la mayor atención de todo el flujo. En un subdominio con su propia carpeta, se borra todo excepto lo que el hosting necesita. El dominio principal es distinto: su carpeta contiene también las carpetas de otros subdominios. Ahí el despliegue borra solo las rutas que el propio sitio genera, nunca la carpeta completa. Un error en esa línea podría borrar varios sistemas a la vez.
Verificar después de publicar
El último paso consulta el sistema recién desplegado y falla si no responde como se espera. En las aplicaciones con backend, llama al endpoint de salud, que verifica la base de datos. Un despliegue que termina en verde pero deja el sitio caído es peor que uno que falla con claridad, porque nadie mira.
Barreras antes de producción
Algunos proyectos generan archivos derivados de una fuente: audios de lectura a partir de preguntas, miniaturas, índices de búsqueda. Si alguien cambia la fuente y olvida regenerar el derivado, la función queda rota en silencio. Documentar "acuérdate de regenerar" no alcanza.
- Un script de verificación compara la huella de cada fuente con la registrada para su derivado.
- La integración continua ejecuta ese script en cada cambio.
- El despliegue se encadena a que la integración pase, en lugar de correr en paralelo.
Así, un cambio con un derivado desactualizado no puede llegar a producción, aunque alguien lo empuje a la rama principal.
Detalles que se olvidan
- Si el sitio es una PWA, subir la versión del service worker en cada despliegue que cambia algo visible; si no, quien ya lo visitó sigue viendo la versión anterior.
- Instalar dependencias con el archivo de bloqueo, no con resolución libre.
- Limitar el flujo a una sola ejecución a la vez: dos despliegues simultáneos extrayendo en la misma carpeta producen un sitio mezclado.
- Separar el despliegue del frontend y del backend cuando viven en carpetas distintas, y desplegar el backend primero cuando el frontend depende de un endpoint nuevo.