Proyectos
CI/CD · Infraestructura

Despliegue continuo
sin exponer SSH

El reto: que un cambio publicado en GitHub llegue a producción de forma automática y verificable, sin abrir ningún canal entrante de administración. Es el servidor quien inicia las conexiones salientes. Nunca al revés.

El flujo, de un extremo a otro
git push rama main Actions build imagen GHCR registro webhook · HMAC INTERNET 4LABSSERVER n8n verifica firma escribe /deploy/trigger systemd.path detecta · despliega docker up web en producción

El único punto de contacto entre n8n y el sistema es un fichero. n8n no toca Docker, no abre puertos, no ejecuta comandos. Si se comprometiera, lo máximo que lograría es forzar un redespliegue de la propia imagen del proyecto.

Las decisiones, y su porqué
01
No montar el socket de Docker en n8n
Probleman8n necesita ordenar el despliegue en el servidor, y es un contenedor que ejecuta lógica disparada por webhooks públicos.
AlternativasLa vía cómoda es montar /var/run/docker.sock en el contenedor.
DecisiónDescartada. El socket de Docker equivale a acceso root en el anfitrión: con él se puede arrancar un contenedor privilegiado que monte todo el sistema de ficheros. Concedérselo a un servicio expuesto a Internet anularía todo el endurecimiento previo del servidor.
02
Fichero-señal en vez de un receptor HTTP
ProblemaDescartado el socket, ¿cómo comunica n8n la orden de desplegar al anfitrión?
AlternativasOpción A: un receptor HTTP en el host con un token. Opción B: n8n escribe un fichero que un servicio del sistema vigila.
DecisiónFichero-señal. El criterio no es qué protege mejor el canal, sino cuál elimina el problema: la solución sin red no tiene puerto ni token que defender. n8n pierde toda capacidad de ejecutar comandos; su único poder sobre el sistema es crear un fichero vacío en una ruta concreta. Una unidad systemd de tipo path lo detecta por inotify y dispara el despliegue.
03
Firma HMAC en vez de un token en cabecera
ProblemaEl webhook que dispara el despliegue debe ser auténtico: cualquiera que conozca la URL no debería poder forzar un despliegue.
AlternativasUn token fijo en una cabecera funciona, pero viaja en cada petición: si se filtra un log, se filtra el token.
DecisiónHMAC-SHA256, el mecanismo estándar de GitHub. El emisor firma el cuerpo con un secreto compartido; el receptor recalcula la firma y compara. El secreto nunca viaja por la red. Una petición interceptada revela la firma, pero no permite deducir el secreto ni falsificar otra. La comparación se hace en tiempo constante.
04
Imagen inmutable en vez de copiar ficheros
ProblemaLa web podía desplegarse copiando los ficheros estáticos al servidor y recargando Nginx.
AlternativasCopiar artefactos es más simple, pero no deja un punto de reversión limpio ni un registro de qué está desplegado.
DecisiónCada despliegue es una imagen Docker versionada, identificada por su digest, publicada en el registro. Revertir es descargar el digest anterior, no restaurar una copia. Es además la base sobre la que se apoyarán los futuros servicios de la plataforma.
El resultado

Un git push construye la imagen, la publica, notifica al servidor con una petición firmada, este verifica la firma y despliega la nueva versión — sin intervención manual y sin exponer SSH. La prueba definitiva fue una publicación real: el digest de la imagen desplegada difería del de las pruebas manuales, confirmando que se sirvió el artefacto recién construido.

GitHub ActionsGHCRDockern8nsystemdNginxAstroHMAC-SHA256
Connect → Automate → Augment → Deploy.
Este pipeline es el método 4Labs aplicado a la propia plataforma.