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.

Publicar en Hugo desde Termux

¿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.