Actualización del blog

No es sólo un lavado de cara, es una puesta a punto del blog por completo. Migración de datos, cambios de estilo...

Actualización del blog
Photo by Matilda Alloway / Unsplash

Cuando empecé este blog, allá por mayo del 2020 (¡casi 4 años ya!), no sabía muy bien para qué lo utilizaría, cómo sería... así que decidí ir poco a poco evolucionando con él y ver qué ocurría. Durante este tiempo lo he ido utilizando para plasmar todo aquello que he ido haciendo en mi pasatiempo digital, con el fin de tener en algún lugar todo apuntado y, si además servía de ayuda a más gente, pues mucho mejor.

Decidí empezar con Ghost porque me pareció una plataforma ligera, sencilla y muy alineada con el propósito inicial. Es por eso que en su día elegí también utilizar SQLite como base de datos, pero con el tiempo y la cantidad de contenido que he ido generando, empezaba a quedarse pequeño.

También decidí utilizar un tema propio (basado en el antiguo Casper) y meterle mis propias modificaciones. Eso me ayudó a empezar a aprender a usar las Github
Actions
y evolucionar dicho tema de manera más fluida. Pero con el tiempo, ese mantenimiento empezó a requerir mucho más tiempo del que disponía para ello, y decidí que ya era hora de dejarlo atrás.

Por otro lado, el hecho de que Ghost dejara de soportar oficialmente SQLite hizo que un día, al actualizar el blog, me encontrara con la desagradable sorpresa de que éste no arrancaba, y me vi obligado a buscar la manera de solucionarlo, lo que desencadenó en aquella entrada. Desde aquel momento, empecé a plantearme que necesitaba darle cariño al blog y actualizarlo, pero lo fui posponiendo... hasta hoy 🤦‍♂️. Al fin y al cabo, esa solución funcionaba y me iba apañando.

Continúa usando SQLite con Ghost 5 y Docker
Si tienes tu blog en Ghost y no quieres migrar a MySQL, aquí tienes cómo seguir utilizando SQLite como base de datos

Continúa usando SQLite con Ghost 5 y Docker

Finalmente, decidí ponerme en serio con ello, ¡y aquí tenéis el resultado! He decidido mantener los colores y el logo inicial ya que creo que le dan ese toque distintivo al blog.

Cambios realizados

  • Migración de la imagen de Docker de Ghost 5 versión alpine a Ghost 5 (más robusta y estable, y teniendo ahora más recursos en el VPS me he dado "el capricho").
  • Cambio de SQLite a MySQL 8. Puesto que parece ser la única base de datos "oficial", decidí migrar por completo el blog y levantar una instancia de MySQL dedicada.
  • Nuevo tema. La experiencia de mantener y evolucionar tu propio estilo web fue muy útil y me sirvió de mucho, pero ya no hay tiempo para seguir evolucionándolo, así que he optado por un tema stock de los que ofrece Ghost de manera gratuita y lo he personalizado lo mínimo para no requerir mantenimiento.
  • Búsquedas. Ahora se incluye un cuadro de búsqueda en la página de inicio y un botón en la zona del menú que facilitan navegar por el blog. Con más de 60 entradas, empezaba a ser necesaria alguna forma de localizar lo que necesitaba de forma más efectiva que un simple scroll.
  • Color de acento. El esquema de colores, si bien se ha mantenido en lo básico, ha sido modificado para incluir un color de acento más alineado con el resto (en lugar de aquel rojo vino que tenía antes... los colores no son lo mío, pero lo intento arreglar en la medida que puedo 🥸).
  • Gestión de la membresía. Si te suscribes, ahora puedes elegir si quieres recibir las nuevas publicaciones en el correo o no, así como las notificaciones de comentarios.
  • Login y registro. Para entrar al sitio, ahora envío un correo con un magic link que te sirve para iniciar sesión. No hacen falta contraseñas de ningún tipo (más fácil de mantener y evito almacenar información extra). Los nuevos registros tan sólo requieren ahora de un correo electrónico en el que recibir dicho enlace.
  • Nueva ubicación de los enlaces externos. Los enlaces al repositorio de Git, así como a las redes sociales y el RSS ahora se encuentran en la parte inferior de la página, y reemplacé los iconos por el nombre directamente.
  • No más scroll infinito. La web ahora muestra las últimas publicaciones, y si se quieren ver todas, se deberá pulsar sobre See all (aún no lo traduce automáticamente Ghost, en eso aún estoy trabajando). Al meter el buscador, ya no es necesario muchas veces hacer scroll infinito hasta dar con la entrada que se buscaba.
  • Entradas destacadas. Utilizaré esta opción del blog para marcar las entradas que más visitas o búsquedas están teniendo, a fin de identificar de manera pública qué es lo que más interesa de lo que he publicado (gracias a Offen y Matomo, me he llevado gratas sorpresas viendo que hay contenido que está siendo útil para mucha gente 😃).
  • Disqus fuera. Soy sincero, aquí no comenta mucha gente 🤐. Así que he preferido eliminar la integración de Disqus, que sobrecargaba la página al cargar las entradas, y he dejado el cajón por defecto, de tal forma que ahora, si quieres comentar, deberás registrarte (es gratis y lo seguirá siendo, lo prometo). También mantengo el formulario de contacto por si quieres enviarme alguna duda, sugerencia...

¿Cómo lo he hecho?

Una vez explicado qué ha cambiado, voy a contaros cómo lo he hecho, por si alguien se lo está planteando también, que tenga una guía rápida y concreta.

Primer paso: copias de seguridad

Lo primero que he hecho ha sido realizar una copia de seguridad del blog. Para esto, he seguido 3 pasos principales:

  • Exportar el contenido. Casi todo Ghost se puede exportar en un simple clic. Para ello, basta con ir a Settings -> Import/Export y en la opción de Migration tools seleccionar Export y hacer clic en Export content. Esto nos bajará un fichero JSON con las entradas de nuestro blog y las configuraciones.
Opción de exportar contenido en los ajustes de Ghost
Opción de exportar contenido en los ajustes de Ghost
  • Exportar rutas y redirecciones. En la opción de Labs descargué tanto las rutas personalizadas que tengo, como las redirecciones que he creado.
Opción para exportar redirecciones y rutas dentro de Labs
Opción para exportar redirecciones y rutas dentro de Labs
  • Exportar miembros registrados. Fuera de los ajustes, en la sección de Miembros, tenemos la opción de exportar un CSV con los usuarios que estén registrados. Lo bajamos también.
Opción para exportar los miembros a un fichero CSV
Opción para exportar los miembros a un fichero CSV
  • Copia de seguridad de las imágenes. Dentro de los directorios de Ghost, copié el contenido entero de la carpeta images, que contiene tanto las imágenes de cabecera que he usado, como las que componen las entradas, y no se almacenan en la base de datos (sólo sus referencias).

Segundo paso: Preparar el nuevo docker compose

Una vez tengo todo respaldado, podemos empezar a preparar el nuevo servicio. Para ello, partí del fichero docker-compose.yml que proporciona el propio Ghost y lo personalicé para que usara los ficheros de entorno con las credenciales y configuraciones sensibles, y para que Traefik lo reconociera y expusiera correctamente. El contenido es el siguiente:

version: '3.1'

services:

  ghost:
    image: ghost:5
    container_name: ghost
    restart: always
    env_file:
      - .env_ghost
    environment:
      url: https://blog.midomin.io
    volumes:
      - ./data:/var/lib/ghost/content
    depends_on:
      - db
    networks:
      - public
      - internal
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=public"
      - "traefik.http.services.ghost-secure.loadbalancer.server.port=2368"
      - "traefik.http.routers.ghost-secure.entrypoints=websecure"
      - "traefik.http.routers.ghost-secure.rule=Host(`blog.midomin.io`)"
      - "traefik.http.routers.ghost-secure.tls=true"
      - "traefik.http.routers.ghost-secure.tls.certresolver=certlocal"
      - "com.centurylinklabs.watchtower.monitor-only=true"

  db:
    image: mysql:8.0
    container_name: ghost-db
    restart: always
    env_file:
      - .env_db
    volumes:
      - ./db:/var/lib/mysql
    networks:
      - internal

networks:
  public:
    external: true
  internal:
    external: false

Fichero docker-compose.yml

Como veis, integra su propia instancia de MySQL. Lo decidí así para tener lo más aislado posible el blog del resto de servicios, dado que está más expuesto al exterior y que quiero mantenerlo separado del resto de servicios.

En cuanto a los ficheros de variables de entorno, utilicé el siguiente para MySQL, donde tan sólo le he especificado la contraseña de root que debe usar:

MYSQL_ROOT_PASSWORD=SuperSecretPassword

Fichero .env_db

Para el contenedor en sí, utilicé el fichero siguiente y le metí la configuración relativa a la gestión de correos mediante Mailgun, la conexión a la base de datos y un par más propias del blog:

database__client=mysql
database__connection__host=db
database__connection__user=root
database__connection__password=SuperSecretPassword
database__connection__database=ghost
mail__transport=SMTP
mail__options__service=Mailgun
mail__options__host=smtp.eu.mailgun.org
mail__options__port=465
mail__options__secure=true
mail__options__auth__user=user@midomin.io
mail__options__auth__pass=passwordToken
mail__from=noreply@midomin.io
NODE_ENV=production

Fichero .env_ghost

Con esto, y tras un docker compose up -d, comprobé que el blog estaba levantado y, al acceder a la URL de gestión, pude registrar mi usuario administrador con el que poder entrar y empezar a reconstruirlo.

Tercer paso: Importar todas las copias de seguridad

Una vez creada mi cuenta de administrador y comprobar que el blog estaba accesible, lo primero que hice fue copiar toda la carpeta images que había respaldado en esta nueva, sin reemplazar ningún fichero. Tras ello, comencé a re-importar todos los ficheros que descargué, pero en el orden inverso: Primero restauré los miembros, importando el CSV. Después, las rutas y redirecciones y, por último, desde la Migration tool importé el fichero JSON mediante la opción Universal Import. Tras esto y una pequeña espera (tampoco había tanto contenido para lo que este blog puede soportar), tenía todo en su sitio otra vez. Comprobé que las imágenes estaban accesibles, que las entradas seguían ahí y que, en general, el blog funcionaba.

Ventana de importación dentro de las herramientas de migración
Ventana de importación dentro de las herramientas de migración

Cuarto paso: Personalizar la nueva apariencia

Con todo ya aparentemente disponible, tan sólo quedaba lo más sencillo, y a la vez, lo que más vueltas le he dado, pues es lo que más se va a ver... Así que empecé a navegar por los ajustes del tema, probando estilos, cambiando iconos, layouts, la ventana de las cookies 🍪... y también probando las búsquedas y las opciones de registro, inicio de sesión, etc. Además añadí un banner indicando que estaba haciendo cambios, por si alguien entraba y veía algo raro (al final, para lo que es, un cambio en producción directamente es más rápido y en mi caso no afecta a los usuarios de manera masiva...). Este banner lo mantendré aún un par de días más mientras veo cómo rinde todo, y entonces lo quitaré.

Próximos pasos

Aún hay cosillas por pulir, como revisar por qué algunas traducciones no se están teniendo en cuenta, pero eso son cosillas menores que no me preocupan de momento. De todas formas, si veis algo raro, que esté mal o dudas que podáis tener, no dudéis en usar cualquier medio de contacto de los que tengo puestos para hacérmelo llegar, y os contestaré lo más pronto que pueda, ¡lo prometo! 🤞 (en verdad, suelo contestar rápido, aunque sea para decir si tengo tiempo de mirarlo o no, pero no dejaros ahí en visto).

🎉
¡Espero que os guste este nuevo estilo!

Si te ha gustado la entrada, o te ha sido útil y quieres ayudarme a pagar los gastos que conlleva el servidor y mantener así el blog libre completamente de anuncios, puedes hacer una donación en Bitcoin en la siguiente dirección: