Desde el año pasado tengo el blog funcionando con Hugo, con despliegue automático y todo bastante prolijo, y estoy contento con ello. Pero una limitante de esta configuración hasta el momento es que dependía de la computadora para publicar. Y si bien no es un gran problema pues siempre prefiero escribir y publicar desde allí, en estos dias de viaje me empezó a surgir la idea de publicar desde el teléfono que es el dispositivo que tengo conmigo todo el tiempo.
Así que decidí ponerme manos a la obra con eso, usando la terminal de Termux para gestionar todo, y opcionalmente Markor para editar texto un poco más cómodo. A continuación comparto apuntes de cómo configuré todo.
Este es el stack que estoy usando:
- Hugo como generador estático.
- GitLab como repositorio y CI/CD.
- Cloudflare Pages para servir el sitio.
- Termux como entorno Linux en Android.
- Markor para editar los archivos Markdown.
- SSH para autenticación.
- Scripts propios para automatizar todo.
Preparar Termux
Primero instalé lo necesario:
pkg update
pkg upgrade
pkg install git openssh hugo iconv
Git y OpenSSH para trabajar con el repositorio en GitLab, Hugo para verificar que el sitio se genere correctamente, e ‘iconv’ porque lo uso para generar slugs limpios desde los títulos.
Después configuré mi identidad en Git:
git config --global user.name "Damián Muraña"
git config --global user.email "damian@..."
Y configuré SSH, primero creando un nuevo par de claves:
ssh-keygen -t ed25519
Subí la clave pública a GitLab y agregué esto en ~/.bashrc para que el ssh-agent se inicie automáticamente en importe la clave:
if ! pgrep -u "$USER" ssh-agent > /dev/null; then
eval "$(ssh-agent -s)" > /dev/null
fi
if ! ssh-add -l > /dev/null 2>&1; then
ssh-add ~/.ssh/id_ed25519 > /dev/null 2>&1
fi
Así no tengo que ejecutar ssh-add cada vez que abro Termux.
El repositorio
El repositorio lo cloné en:
~/storage/shared/Documents/damianmuranauy
Como está en almacenamiento compartido de Android (así puedo editar desde Markor de forma simple), Git se quejó con el famoso error de “dubious ownership”. Lo solucioné agregándolo como directorio seguro:
git config --global --add safe.directory /storage/emulated/0/Documents/damianmuranauy
Después de eso funcionó todo normal.
Scripts personalizados
Para no estar escribiendo comandos largos cada vez que voy a crear y publicar algo, creé tres comandos propios:
- blog-update
- blog-new
- blog-publish
Los guardé en $PREFIX/bin para que funcionen globalmente.
blog-update
Sincroniza el repositorio local con el remoto:
#!/data/data/com.termux/files/usr/bin/bash
REPO="$HOME/storage/shared/Documents/damianmuranauy"
cd "$REPO" || exit 1
echo "Rama actual:"
git branch --show-current
echo
echo "Sincronizando..."
git pull
blog-new
Crea un nuevo post con front matter listo y genera el slug automáticamente.
#!/data/data/com.termux/files/usr/bin/bash
REPO="$HOME/storage/shared/Documents/damianmuranauy"
POST_DIR="$REPO/content/posts"
if [ -z "$1" ]; then
echo 'Usá: blog-new "Título del post"'
exit 1
fi
TITLE="$*"
SLUG=$(echo "$TITLE" \
| tr '[:upper:]' '[:lower:]' \
| iconv -t ascii//TRANSLIT \
| sed -E 's/[^a-z0-9]+/-/g' \
| sed -E 's/^-+|-+$//g')
if [ -z "$SLUG" ]; then
echo "No se pudo generar slug válido."
exit 1
fi
DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
FILENAME="$POST_DIR/$SLUG.md"
cat > "$FILENAME" <<EOF
+++
title = "$TITLE"
date = $DATE
draft = false
featured_image = ""
categories = []
tags = []
+++
EOF
echo "Post creado en $FILENAME"
Después lo abro con Markor, ajusto el front matter y escribo el contenido.
blog-publish
Este es el que se encarga de hacer commit, pero antes verifica que el sitio compile correctamente con Hugo.
#!/data/data/com.termux/files/usr/bin/bash
REPO="$HOME/storage/shared/Documents/damianmuranauy"
cd "$REPO" || exit 1
if [ -z "$1" ]; then
echo 'Usá: blog-publish "Mensaje del commit"'
exit 1
fi
echo "Verificando compilación con Hugo..."
if ! hugo --gc --minify --noBuildLock> /dev/null 2>&1; then
echo "Hugo falló. No se publicará nada."
exit 1
fi
echo "Compilación exitosa."
git add .
if git diff --cached --quiet; then
echo "No hay cambios."
exit 0
fi
git commit -m "$*"
if git push; then
echo "Publicado correctamente."
else
echo "Push falló. El commit quedó local."
fi
Si Hugo no compila, no hace el commit. Si Hugo compila, verifica que existan cambios y hace el commit y el push para que luego GitLab y Cloudflare Pages generen la versión actualizada del sitio.
El flujo de publicación
Desde el celular tengo que abrir Termux y ejecutar:
blog-update
blog-new "Título del post"
Luego abro Markor, la carpeta posts la tengo en favoritos así que voy allí y edito el archivo .md del nuevo post. Cuando termino de escribir lo guardo y vuelvo a Termux.
Allí ejecuto:
blog-publish "Nuevo post sobre alguna cosa"
Y si todo sale bien el nuevo post se sube al repositorio y GitLab hace el despliegue automático.
Todo desde el teléfono, sin navegador web o CMS, y sin depender de la computadora.

¿Por qué hacer esto?
Por si alguien se lo pregunta: por reducir la fricción para escribir. Si publicar depende de abrir una computadora, esperar que arranque, conectarme a una red y sobre todo de tener un lugar adecuado donde hacer esto, voy a escribir menos.
Por supuesto, como dije antes, todavía prefiero escribir desde la computadora y con un teclado físico en condiciones. Pero de este modo si tengo una idea en una plaza mientras tomo café puedo desarrollarla y publicarla en minutos.
Y así, este post explicativo es el primero publicado con esta configuración.