Github Actions
Dec 17, 2025 - ⧖ 6.0 minPues a pesar de que he mantenido las fechas originales de los posts en realidad este blog lo he echado andar recientemente. Para ser exactos en este mes de diciembre. Las razones fundamentalmente han sido que la versión anterior aunque estaba bien y era minimalista bastante, tenía dos problemas para mí:
- Requería desplegar un container (con base de datos y tal): Yo en general todo lo que tengo autoalojado lo mantengo en máquinas pequeñas con poca RAM y menos CPU, así que "levantar un container" no es moco de pavo. Además, es simplemente un blog... estático... ¿de verdad que no me llega con un simple servidor web? ☹️
- El editor estaba embebido en el blog: No es un gran problema y en general puede suponer una ventaja. Pero me gusta poder hacer las cosas offline, luego subirlo y listo, me gusta usar el editor que me de la gana, incluso cambiar de editor en cada post.
Como alternativa me estaba planteando buscar un sistema tipo pandoc y construir algo complejo con pipelines y demás para de un repositorio con Markdowns llegar a construir una web, pero me he encontrado esta alternativa que me parece que alcanza un buen equilibrio entre una cosa y la otra.
La verdad que a pesar de su sencillez el blog con Marmite tiene muchas posibilidades y aún estoy acabando de poner cosas en marcha, pero bueno, poco a poco. Lo importante y es el objetivo del post es lo que he hecho para que se genere la página web estática de forma manual y se suba a mi servidor autoalojado. Y para ello he usado Github Actions y configurado las credenciales de acceso en los secretos de Github. La verdad es que tampoco hay mucho más que contar, pero bueno voy a dejar el paso a paso y así lo podré reproducir en caso de que me encuentre en las mismas en el futuro.
Al final para poner en marcha los workflows de Github Actions solo hay que crear un fichero bajo la carpeta .github/workflows, en concreto un yml. Creo que el nombre da un poco igual. En este caso el fichero se llama deploy.yml y lo que hace es que cuando se sube un commit a la rama main se ejecuta el workflow. El workflow es un poco complejo pero lo ha generado la IA así que estará bien 😜.
name : Deploy Blog
on :
push :
branches : [ main ]
pull_request :
branches : [ main ]
workflow_dispatch : # Allows manual triggering
jobs :
deploy :
runs-on : ubuntu-latest
steps :
- name : Checkout repository
uses : actions/checkout@v4
- name : Create site directory
run : mkdir -p site
- name : Build site with Marmite
run : |
echo "Building site with Marmite..."
docker run --rm -v "$(pwd)":/workspace -w /workspace ghcr.io/rochacbruno/marmite:latest
- name : Setup SSH key
if : github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
run : |
mkdir -p ~/.ssh
echo "${{ secrets.DEPLOY_SSH_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
# Extract hostname and port from DEPLOY_HOST (format: hostname:port)
HOST_ONLY=$(echo "${{ vars.DEPLOY_HOST }}" | cut -d: -f1)
PORT=$(echo "${{ vars.DEPLOY_HOST }}" | cut -d: -f2)
ssh-keyscan -p $PORT -H $HOST_ONLY >> ~/.ssh/known_hosts
- name : Deploy to server
if : github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
run : |
echo "Deploying to server..."
# Extract hostname and port for rsync
HOST_ONLY=$(echo "${{ vars.DEPLOY_HOST }}" | cut -d: -f1)
PORT=$(echo "${{ vars.DEPLOY_HOST }}" | cut -d: -f2)
rsync -avz --delete -e "ssh -i ~/.ssh/id_rsa -p $PORT -o StrictHostKeyChecking=no" \
site/ ${{ vars.DEPLOY_USER }}@$HOST_ONLY:${{ vars.DEPLOY_PATH }}/
- name : Verify deployment
if : github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
run : |
echo "Checking site availability..."
sleep 10 # Give server time to process files
if curl -s --head ${{ vars.SITE_URL }} | head -n 1 | grep -q "200 OK"; then
echo "✅ Site is up!"
echo "🌐 Visit: ${{ vars.SITE_URL }}"
else
echo "⚠️ Site is not accessible. Check: ${{ vars.SITE_URL }}"
exit 1
fi
La primera parte del workflow son los triggers (lo que provoca que se lance). Luego en cada step se controla si se ejecuta o no con los ifs que hay debajo de cada name. La gracia es que el deploy como tal solo se ejecuta cuando realment el cambio llega a main, por lo que cada vez que meta contenido y lo mantenga en un PR solo se está ejecutando la parte que genera la página web (para ver que no hay errores de generación).
Es interesante ver que he mezclado secrets secrets.DEPLOY_SSH_KEY y variables vars.DEPLOY_HOST para que se pueda usar una variable de entorno. Las variables
se ven en los logs mientras que los seecrets aparecen securizados. Mola que parece todo bastante seguro pero muy simple de configurar.
Por cierto, las variables y los secrets se pueden configurar en el repositorio en Settings > Secrets and variables > Actions > New repository secret
o en la pestaña Variables > New repository variable.
Para terminar dejo un pequeño script que he puesto en marcha para testear los cambios antes de subirlos:
#!/bin/bash
echo "Starting local development server as daemon..."
echo "🚀 Server will watch for changes and rebuild automatically"
echo "📝 Edit files in the 'content' directory to see live updates"
echo "🌐 Visit: http://localhost:8000"
echo ""
# Start the marmite server with watch mode as daemon
CONTAINER_ID =$( podman run --rm -d -v " $( pwd ) " :/workspace -w /workspace -p 8000:8000 --name marmite ghcr.io/rochacbruno/marmite:latest -w --serve )
echo "✅ Server started as daemon with container ID: $ CONTAINER_ID "
echo ""
echo "🛑 To stop the server, run one of these commands:"
echo " podman stop marmite"
Me quedan probar muchos casos aún pero parece que lo básico va...