La arquitectura de la sustracción: por que mate a mi pipeline de Jenkins
Cuatro anos intentando publicar desde Obsidian (Django, Hugo, Jenkins) hasta encontrar la pieza que encajo: menos friccion, mas publicaciones.
Esta semana he migrado de portátil de trabajo. Lo típico: cables, backups, claves, "por qué esto no arranca", "dónde estaba ese fichero". Y, en medio de ese ruido, me volvió una idea que me persigue desde 2022: cuántas veces he confundido avanzar con mover piezas.
No con "montar por montar". Cada pieza suele tener un motivo real: investigar una tecnología, encajar con el stack que ya tienes, reducir un riesgo, ahorrar un paso manual. El problema es otro: cuando el objetivo y el presupuesto (tiempo o dinero) no están claros, los motivos se vuelven infinitos. Y entonces el sistema crece, no porque sea mejor, sino porque es lo que sabes hacer para sentir que no estas parado.
A eso, en mi caso, le puse nombre: arquitectura de la sustracción. No es minimalismo estético. No es "quitar cosas" como religión. Es una pregunta operativa: qué sobra para el objetivo que persigo con el presupuesto que tengo, y qué puedo eliminar para que el sistema deje de robarme energía mental.
La pregunta real nunca fue "mantener un sistema o publicar". Fue: cómo publico desde Obsidian a la web con la mínima fricción posible.
Porque yo siempre quise publicar. Lo que pasó es que nunca encontré la herramienta concreta que encajase con mis restricciones, y en cada etapa fui por el camino de menor resistencia que conocía.
1. 2022-2024: quería publicar, no quería WordPress, y no encontré nada que encajara
Todo empieza con una idea sencilla: "quiero abrir un blog". La opción razonable era usar algo ya hecho. El problema es que WordPress, en aquel momento, no me encajaba ni por seguridad ni por mantenimiento. Lo veía como una maquina de tener que estar pendiente: actualizaciones, hardening, y una sensación constante de que para cada cosa necesitabas un plugin mas. Y para un blog personal, yo quería justo lo contrario: escribir y olvidarme.
Así que busqué alternativas. Y aquí viene la parte menos romántica: muchas opciones que encontraba eran cerradas (Blogspot, Blogger y similares), o no eran autoalojables, o venían con un "sí, puedes publicar, pero dentro de nuestra caja". Yo quería poder self-hostearlo y tener el control del canal, aunque sólo fuera por tranquilidad y por estilo de trabajo.
Cuando nada encajaba, tomé el camino que conocía: Django. No porque pensara que iba a construir el mejor CMS del mundo, sino porque era la vía que menos resistencia me ofrecían mis propias habilidades. Python lo manejaba. Django lo conocía. Y, con eso, parecía razonable montar un CMS simple y publicar.
Spoiler: publicar no ocurrió.
El primer mes no salio una sola linea de contenido "real". Salio armazón. Modelos, autenticación, base de datos, despliegues. Todo técnicamente correcto. Y, al mismo tiempo, perfectamente irrelevante para el objetivo de fondo. Lo que yo necesitaba no era un producto. Era un canal.
Entre 2022 y 2024 el proyecto se reinició cinco veces. No por falta de ganas, sino por fricción estructural: poco tiempo, cambios de versiones, y esa ecuación desagradable en la que adaptar lo viejo a la versión nueva te costaba mas que rehacerlo. Cada vez que lo retomaba, la versión había cambiado, el código había envejecido, y el cerebro elegía el atajo: "lo rehago, tardo menos". Y ahí se te va otro trimestre.
La vez que mas cerca estuve de tenerlo presentable, me bloquee con algo que, visto en frío, era un anticipo de todo lo que vendría después: la analítica. En 2024 no quería meter Google Analytics. No quería banners de cookies. No quería convertir un blog personal en otra web que rastrea. Y en vez de aceptar una solución simple, me fui al extremo: escribir mi propio motor de analítica server-side.
El código quedo bonito. Bastante bonito. Y el blog seguía sin estar online.
Ahí entendí una verdad incomoda: no me estaba faltando tecnología. Me estaba faltando encaje. Estaba intentando fabricar una solución a medida con un presupuesto de tiempo que no existía.
2. 2025: Obsidian, Hugo y la cadena de cristal (cuando publicar parece un ticket)
En 2025 cambie la estrategia. Si el problema era fabricar un CMS entero, la salida era obvia: generar una web estática desde Markdown. Y aquí entra Obsidian. Para mi, Obsidian ya era el motor central: mis notas, mis borradores, mis ideas, mis enlaces. Yo no quería escribir en un editor aparte y luego "pasar" el contenido. Quería escribir donde ya vivía mi conocimiento y que el camino a la web fuese corto.
Hugo parecía el siguiente paso lógico: Markdown in, web out. La teoría era perfecta. La practica, no.
No llegue a tener una web completamente funcional y publica. Lo que tuve fue un laboratorio de validación: intentos, builds locales, ajustes, y una fricción constante entre "lo que escribo" y "lo que veo renderizado". Y ahí apareció el primer golpe serio.
2.1 El día del publishDir (cuando me borre el vault entero)
Esto no fue un susto. Fue un incendio.
En una prueba local, tocando configuración (publishDir y una limpieza agresiva), una ruta mal puesta hizo que la limpieza subiera un nivel. Y el nivel de arriba no era un directorio temporal. Era mi vault de Obsidian.
Me borre todo el vault. Todo.
Por suerte, lo recupere desde una copia de seguridad. Pero ese momento te cambia la relación con tu propio sistema. De repente, tu problema ya no es "cómo publico". Tu problema es "cómo no me destruyo mi propio trabajo". Y cuando estas escribiendo, esa clase de miedo se queda en el cuerpo.
Ese fue el motivo real de meter guardrails. En ese momento no había repo git. El repo git nació para evitar volver a perder la información local. Metí el contenido en versionado dentro de una subcarpeta de Obsidian, no por postureo, sino por supervivencia.
2.2 La humillación del webhook ignorado
Con el repo en su sitio, el siguiente objetivo era quitar pasos manuales. Porque el motivo por el que Hugo me atraía era ese: reducir fricción entre escribir y ver el post publicado.
Acabe montando un flujo de validación: escribía en Obsidian, comiteaba en local, pusheaba a un repo privado remoto, un webhook invocaba Jenkins, Jenkins construía, y yo me descargaba la imagen para probar en local. Era mi forma de decir: "vale, si esto funciona, ya tengo el canal".
Y entonces llego la escena que resume 2025: días en los que el webhook se enviaba y Jenkins no respondía. No pasaba siempre. Solo lo suficiente para sembrar desconfianza.
La película se repetía: push, espera, té, nada. Abrir Jenkins. Esperar a que cargue. Entrar al job. Pulsar Build Now.
Yo había montado automatización para eliminar pasos manuales. Y termine haciendo de operador de mi propia automatización.
Lo peor no era el minuto perdido. Era el ruido mental: si para publicar primero tengo que comprobar si el pipeline esta despierto, ya no estoy publicando. Estoy abriendo un incidente domestico.
2.3 El despliegue fantasma (verde en Jenkins, nada cambia)
La siguiente frustración fue mas sutil y mas cruel: el pipeline "funcionaba" y aun así el resultado no aparecía.
Jenkins compilaba Hugo y generaba la imagen. Todo en verde. Pero a la hora de probarlo, a veces la versión que yo veía seguía siendo la anterior. Unas veces por etiquetados, otras por como estaba montado el despliegue local, otras por mi propio método de prueba. La conclusión era siempre la misma: tiempo perseguido en caches, variables y detalles que no aportaban nada al objetivo.
Ese fue el motivo por el que nunca salió a producción. No porque no se pudiera, sino porque yo no conseguí que fuese estable. A veces por Jenkins, a veces por mi despliegue. Ambas reales. Y mientras tanto, el blog seguía sin ser publico.
Nada era dramático por separado; junto, sí. Y aquí esta el punto importante: el blog ni siquiera era publico. Era fase de pruebas. Pero la fricción era real igual, porque la fricción no depende del tráfico: depende del coste mental que te cobra el sistema antes de dejarte publicar.
Cuando el paso de "he terminado un post" a "lo veo en la web" parece un ticket, dejas de escribir. No porque no quieras publicar. Porque sabes que publicar te va a robar la tarde.
3. 2026: Ghost encaja (la pieza del puzzle que faltaba)
Y entonces llego Ghost. Un amigo lo menciono, lo mire con curiosidad, y ahí si hubo revelación. No por marketing. Por encaje.
Mi necesidad era muy concreta: escribir en Markdown (idealmente desde Obsidian) y publicar en un CMS que pase de Markdown a web sin fricción. Sin tener que construir un producto. Sin tener que validar un pipeline que se rompe con una ruta. Sin convertir cada publicación en un mini despliegue corporativo.
Ghost era esa pieza.
El hecho de poder autoalojarlo encajaba con como trabajo, si. Me gusta operar mis servicios y tener mis datos. Pero eso era secundario. Lo principal era que el camino sea corto de verdad.
La puesta en marcha me llevo unas tres horas: docker-compose con Ghost y MySQL, Plausible self-hosted para analítica sin cookies, Nginx y certificados. Nada heroico. Lo heroico, si acaso, fue lo contrario: que por primera vez el problema volvía a ser escribir.
Con Ghost aparecieron las publicaciones reales. Antes había borradores, pruebas, intentos. Con Ghost, el blog por fin fue publico. Y cuando el canal deja de doler, el contenido deja de ser una deuda.
4. Lo que en realidad va de esto: fricción, contexto y presupuesto
Si este post suena a "yo era un tonto por complicarlo todo", no es el mensaje. Yo no monte cosas "por si acaso". Monte cosas porque en ese momento me hacían falta: para tener un canal self-hosted sin WordPress, para intentar un flujo Obsidian->web, para quitar pasos manuales, para poner guardrails después de haberme borrado el vault entero.
El error no fue técnico. Fue de enfoque y de contexto.
La sobreingeniería no es un vicio moral. Es una consecuencia casi automática cuando el alcance esta difuso y el presupuesto no se explicita. Si no dices "esto es un blog personal con X horas a la semana", tu cerebro rellena el hueco con "y si". Y ese "y si" es infinito. La mayoría de la gente cae ahí. Yo también. Y seguiré cayendo en otros proyectos, porque esto no es una iluminación permanente.
La madurez técnica, para mi, no es "quitar cosas". Es saber identificar qué sobra para el objetivo que persigues y para el presupuesto que tienes. A veces sobrarán capas. A veces sobrará automatización. A veces sobrará control. Y a veces, al revés, la sobreingeniería sera literalmente lo correcto porque el contexto lo exige.
Pero en este caso, el enemigo no era la complejidad. Era la fricción. El impuesto mental.
Y esto no es solo un problema de blogs. Es el mismo patrón en cualquier sistema: si tu infraestructura consume tu "tiempo mental", si te obliga a estar pendiente, si te convierte en el operador nervioso que vigila que nada falle, estas gastando energía donde no aportas valor. Ya sea escribiendo un post o sosteniendo un sistema empresarial: tu objetivo no es tocar el teclado sin parar. Tu objetivo es que el sistema sea lo bastante estable como para que puedas dedicar la cabeza a lo que importa.
Por eso la arquitectura de la sustracción, tal y como la entiendo ahora, no es quitar por quitar. Es recortar lo que no aporta al propósito, dado el contexto. Es diseñar un camino que no te obligue a pelear cada vez. Es hacer que publicar sea aburrido. Y cuando publicar es aburrido, escribes mas. Punto.
5. Conclusiones
He tardado cuatro años en sacar el blog no por falta de ganas de publicar, sino por falta de encaje y por fricción acumulada. Django fue el camino de menor resistencia en 2022. Hugo con pipeline lo fue en 2025. Ghost lo fue en 2026, pero con una diferencia clave: era el camino de menor resistencia que, ademas, llegaba al final.
No maté al constructor. No renuncie a nada. Encontré la pieza del puzzle que faltaba y dejé de usar el blog como laboratorio permanente. El orgullo de "esto lo he montado yo" no desapareció. Simplemente dejé de exigirle al blog que se ganara ese orgullo a base de sufrimiento.
Ahora el canal no me roba energía. Y cuando el canal no roba energía, por fin haces el trabajo que querías hacer desde el principio: publicar.
Nos leemos en el siguiente post.