Artículo
Un despliegue estático verificable: TLS por fases, lock y rollback
Una retrospectiva de despliegue en VPS sobre orden de operaciones, exclusión mutua, validaciones y recuperación sin confundir automatización con seguridad total.
Este artículo documenta una etapa anterior del portafolio: un sitio estático construido en un VPS y servido por Nginx. No es un manual de la infraestructura actual ni una promesa de “seguridad total”. Es una revisión del orden que hizo el proceso repetible y de los fallos que todavía quedaban fuera.
El aprendizaje principal fue sencillo: un despliegue puede usar herramientas correctas y aun así ser frágil si no define precondiciones, exclusión mutua, validación y recuperación.
Límite. Un script reduce variabilidad conocida. No reemplaza el modelo de amenazas, la gestión de secretos, los respaldos, el monitoreo externo ni una revisión de la plataforma donde se ejecuta.
Empezar por el modelo de fallos
La primera versión del procedimiento era una lista de comandos: actualizar código, instalar dependencias, construir y recargar el servidor web. La lista describía el caso feliz, pero no respondía preguntas operativas:
- ¿qué pasa si dos despliegues comienzan al mismo tiempo?;
- ¿qué versión queda activa si el build falla?;
- ¿cómo se comprueba la configuración antes de recargar?;
- ¿qué evidencia queda para reconstruir la secuencia?;
- ¿quién detecta una caída completa del host?;
- ¿qué significa volver atrás para código y configuración?
El script empezó a ser útil cuando estas preguntas se convirtieron en puertas explícitas, no cuando acumuló más comandos.
TLS necesita una secuencia
El bootstrap de HTTPS tiene una dependencia circular aparente: Nginx necesita un certificado para servir la configuración TLS final, pero el cliente ACME necesita demostrar control del dominio antes de obtenerlo.
Para el desafío HTTP-01, Let’s Encrypt solicita un archivo bajo
/.well-known/acme-challenge/ y realiza la validación por el puerto 80. Su
documentación de tipos de desafío
también aclara que HTTP-01 no emite certificados wildcard y que, cuando no se
puede exponer ese puerto, deben evaluarse alternativas como DNS-01.
El procedimiento separó el cambio en fases:
- comprobar DNS, conectividad y la configuración HTTP;
- servir únicamente lo necesario para la validación ACME;
- emitir el certificado mediante un cliente configurado para ese webroot;
- instalar la configuración HTTPS que referencia archivos ya existentes;
- validar y recargar;
- comprobar HTTP, redirección y HTTPS desde fuera del proceso.
Esta secuencia no convierte una configuración TLS en segura por sí sola. Evita un fallo concreto: activar referencias a certificado y clave antes de que esos archivos existan.
Un build reproducible es una precondición
“Instalar y construir” no define un resultado reproducible. El procedimiento debe fijar la versión del runtime, conservar el lockfile y elegir deliberadamente la política para scripts de instalación.
En aquel repositorio, el despliegue usaba una instalación con lockfile congelado y habilitaba de forma explícita los pasos nativos que necesitaba el build. Esa política pertenecía a sus dependencias concretas; no debe copiarse sin revisar qué paquetes requieren scripts.
La comprobación importante ocurría antes de publicar:
versiones esperadas ↓lockfile sin cambios ↓instalación inmutable ↓pruebas y build ↓salida estática comprobableSi cualquiera de esas puertas fallaba, no había motivo para recargar el servidor web. Un build fallido debía terminar el despliegue antes de modificar la superficie pública.
Serializar para evitar estados competidores
El procedimiento añadió un lock de proceso. Su responsabilidad era limitada: impedir que dos ejecuciones del mismo despliegue modificaran simultáneamente el checkout y la salida.
Un lock no vuelve atómica toda la publicación. Tampoco protege contra otro proceso que ignore el mismo contrato. Sí transforma una carrera silenciosa en un fallo visible y permite registrar quién adquirió la exclusión y cuándo la liberó.
Las reglas eran:
- adquirir el lock antes de tocar el árbol de trabajo;
- abortar con un mensaje claro si ya existía una ejecución activa;
- liberar el lock también ante errores;
- escribir la secuencia y el resultado en un log fechado;
- no ocultar la salida de las verificaciones.
Esto redujo incertidumbre operacional sin presentar el mecanismo como un control de seguridad suficiente.
Validar antes y después de recargar
Nginx ofrece -t para comprobar la sintaxis e intentar abrir los archivos que
la configuración referencia, según su
documentación de parámetros. Esa
prueba debe ocurrir antes de enviar la señal de recarga.
La validación quedó dividida en tres niveles:
- artefacto: el directorio de salida contiene las rutas y recursos esperados;
- servidor: la configuración pasa su comprobación sin depender de que una recarga falle para descubrir el error;
- servicio: solicitudes HTTP verifican respuesta, redirección y contenido representativo.
Después de la recarga se repetían las comprobaciones de servicio. Validar solo antes confirma que una configuración parece aplicable; validar después confirma que el recorrido público sigue respondiendo.
Rollback significa restaurar un estado conocido
“Volver al commit anterior” era insuficiente porque el despliegue también podía modificar configuración y artefactos generados. La recuperación necesitaba identificar:
- la revisión de código anterior;
- la salida estática que había sido aceptada;
- la configuración del servidor web correspondiente;
- las comprobaciones que determinaban si la recuperación funcionó.
El rollback se documentó como otro despliegue: adquirir el lock, restaurar el estado elegido, validar la configuración, aplicar el cambio y ejecutar las pruebas de humo.
No se borraban datos persistentes porque el sitio no los necesitaba. En un sistema con migraciones o estado de usuario, esta estrategia sería incompleta y requeriría un diseño diferente.
El recorrido completo
- Comprobar precondiciones
- Adquirir el lock
- Instalar, probar y construir
- Validar la configuración
- Publicar y recargar
- Ejecutar pruebas externas
- Éxito
- Registrar el resultado y liberar el lock.
- Fallo
- Restaurar, verificar la recuperación y liberar el lock.
La secuencia hacía visible dónde detenerse. También evitaba que una verificación tardía sustituyera a las precondiciones: probar HTTPS al final no compensa haber construido con dependencias distintas o haber recargado una configuración inválida.
El límite del monitoreo local
El VPS ejecutaba una comprobación periódica útil para diagnóstico. Sin embargo, un proceso en el mismo host comparte varios modos de fallo con el servicio que vigila: pérdida de red, apagado, saturación o fallo del sistema.
Por eso el healthcheck local no debía describirse como observabilidad completa. Una señal externa es necesaria para detectar que el host entero dejó de responder. Además, disponibilidad no equivale a corrección: una respuesta 200 no demuestra que canonical, rutas o contenido crítico sean los esperados.
La combinación razonable separa:
- comprobaciones internas para contexto y diagnóstico;
- sondeos externos para disponibilidad;
- pruebas de humo sobre rutas y contenido;
- logs conservados fuera del ciclo inmediato del proceso.
Qué cambiaría hoy
El flujo anterior construía dentro de un checkout del VPS. Para una nueva implementación preferiría producir un artefacto inmutable en CI y promoverlo entre entornos, reduciendo el trabajo y las credenciales necesarias en el host de entrega.
También haría explícitos desde el inicio:
- la retención y prueba periódica de respaldos;
- la verificación externa con un canal de alerta;
- la política de rotación de credenciales;
- el despliegue de configuración como artefacto revisado;
- una estrategia de publicación que reduzca la ventana entre versiones.
Estas mejoras no invalidan la secuencia documentada. Marcan su alcance: fue una forma más verificable de operar un sitio estático en un VPS, no el punto final de una plataforma de entrega.
La decisión que conservaría
Un despliegue mantenible debe poder responder, con evidencia, cuatro preguntas:
- ¿qué condiciones comprobó antes de cambiar producción?;
- ¿qué versión y configuración intentó publicar?;
- ¿cómo comprobó el resultado desde el recorrido real?;
- ¿cómo restaura y vuelve a validar el último estado aceptado?
El lock, las fases de TLS y el rollback sirven porque ayudan a responderlas. Si se convierten en una colección de comandos que nadie revisa, vuelven a ser otra fuente de confianza implícita.
La arquitectura editorial que producía el artefacto se explica en De Markdown en runtime a contenido generado en build.