- Historia
- Objetivo
- Introducción
- Infraestructura
- Git Hooks
- Configuración servidor
- Configuración cliente
- Conclusiones
Historia
Hace unas semanas este blog se vió afectado por el incendio en los servidores de ovh que dejó el sitio web caído por unos días.
Afortunadamente toda la web se encuentra en un repositorio en github y no perdí nada importante. Me da pena haber perdido un fichero con 2G de usuarios y contraseñas que había capturado con un ssh-honeypot.
Cuando empecé este blog no había nada automatizado. No había certificados ssl, el servidor web estaba instalado en el sistema y copiaba por scp el html compilado en mi máquina. Por suerte, había avanzado en la automatización del despliegue de esta web para ser más independiente del proveedor de vps de turno.
Objetivo
El objetivo es desplegar en el servidor los cambios que hagamos en local, con solo hacer solo git push al repositorio del vps.
Introducción
Este blog es un sitio web estático generado por jekyll. Sin entrar en particularidades de jekyll, la manera de generar esta blog consiste en escribir los posts en markdown y compilar para generar los ficheros html.
Infraestructura
Toda la infraestructura, el servidor web y el sistema de comentarios, está dockerizado. Puedo versionar mi infraestructura con git, ampliarla y modificarla sin tener que instalar a mano cada software en el vps. Esto permite que la web sea autocontenida, todo lo que necesito está en un repositorio.
Con docker-compose levanto todos los contenedores de un solo comando.
Git Hooks
Git ofrece una manera de lanzar scripts cada vez que ocurren eventos en el repositorio. En el argot de git se le conoce como git hooks.
Se pueden disparar scripts tanto en eventos del cliente (commit, merge) como en el lado del servidor (pre-receive, post-receive).
Configuración servidor
Tenemos que crear un repositorio de git bare
mkdir hardfloat-blog.git
cd hardfloat-blog.git
git init --bare
Creamos el hook que se va a ejecutar en el servidor después de recibir cada push.
vim hooks/post-receive
Con el seguiente contenido:
#!/bin/bash
GIT_DIR=/home/debian/hardfloat-blog.git
GIT_WORK_TREE=/home/debian/hardfloat-blog
if [ ! -d $GIT_WORK_TREE ]; then
mkdir $GIT_WORK_TREE
fi
git --git-dir=$GIT_DIR --work-tree=$GIT_WORK_TREE checkout -f master
cd $GIT_WORK_TREE
git --git-dir=$GIT_DIR --work-tree=$GIT_WORK_TREE submodule update --init --recursive
docker-compose -f docker-compose-prod.yml down &&
docker-compose -f docker-compose-prod.yml up -d
Y damos los permisos de ejecución al script:
chmod +x hooks/post-receive
Con el repositorio clonado, docker-compose se encargará de construir los contenedores y levantar los contenedores de forma automática.
Configuración cliente
Esto es lo más fácil, tan solo tenemos que agregar un remoto a git desde el que hacer push.
La plantilla es la siguiente:
git remote add prod ssh://[username]@host:[port]/home/andres/hardfloat-blog.git
Ahora solo tenemos que hacer un git push a producción y el hook se encargará de reiniciar todos los contenedores y generar los ficheros html al momento
git push origin prod
Conclusiones
Aún me quedan cosas por automatizar como la generación y renovación de los certificados y algunos permisos en directorios a la hora de levantar los contenedores. El tema de los certificados se puede automatizar desde el sistema con certbot, aunque también me gustaría hacerlo en docker.
Los hooks de git son un buen punto de entrada para realizar tareas en cada push. Por ejemplo, podríamos enviarnos un mail cuando se desplieguen los cambios, desplegar solo si pasan todos los test, en caso contrario descartamos el despliegue.
Desplegar con un solo comando es una auténtica gozada. Elimina la fricción de sentarse a escribir y enviar los cambios al servidor.