TPTito Pinardo Gutiérrez
← Volver al rack
English
1U · IACTerraform · Ansible · Git En producción

Posición 18 de 25 en el rack · En producción

Unidad 1U · Infraestructura como código

El homelab como código

Reconstruir un servicio: un comando

Los servicios de casa se habían montado a mano durante años y nadie, ni yo, sabía reconstruir uno. Ahora Terraform crea cada contenedor en Proxmox y un rol de Ansible lo configura; los secretos van cifrados, cada cambio se revisa antes de aplicarse y todo queda en Git con una copia automática.

Cómo trabajo
Desde un contenedor de control en el propio servidor, con los agentes de IA con los que trabajo en terminales que puedo abrir desde el portátil o el navegador.
La regla
Nada se aplica sin ver antes qué va a cambiar: «terraform plan» o «--check --diff». Y versiones fijadas: volver a ejecutar un playbook no actualiza nada por sorpresa.
Lo público
Una copia saneada del repositorio en GitHub, generada y comprobada sola en cada cambio y publicada cuando la apruebo: estructura y roles, sin IPs reales, secretos ni reglas de cortafuegos.
  • 1fichero de Terraform por contenedor o VM
  • 1rol de Ansible por servicio
  • 4 → 0contenedores que un plan iba a destruir y no se aplicó
  • 2copias del repositorio en cada commit

Su código, en abierto Versión pública del repositorio: sin IPs ni secretos.

El nodo de control por dentro

Desde aquí se crea, se configura y se actualiza todo lo demás. Elige un recorrido para ver cómo nace un servicio y qué lo frena antes de romper algo.

Hermesde visita en la unidad

Pulsa una pieza o elige un recorrido. Si vienes de una habilidad, ya están encendidas las piezas donde la uso.

      Nace un servicio
      1. Mi portátil — Desde el portátil abro el panel de terminales.
      2. Panel de terminales — Llego a la sesión del nodo de control.
      3. Agentes de IA — Con un agente, escribo el fichero de Terraform del contenedor nuevo.
      4. Terraform — Terraform calcula el cambio.
      5. terraform plan — El plan dice: 1 para crear, 0 para destruir.
      6. Revisión — Lo leo. Si sale algo que no esperaba, no sigo.
      7. Terraform — Terraform aplica.
      8. API de Proxmox — Por la API de Proxmox.
      9. Contenedores LXC — Y el contenedor existe.
      10. Roles — Escribo el rol del servicio.
      11. Secretos — Sus secretos, a OpenBao; en el repositorio, solo sus nombres.
      12. Ensayo con diferencias — Ensayo: qué ficheros cambiarían.
      13. Revisión — Lo reviso.
      14. Roles — Aplico el rol.
      15. Rol de endurecimiento — Endurecimiento y monitorización, iguales que en el resto.
      16. Lista de servicios — Añado el servicio a la lista común.
      17. DNS de Cloudflare — Y su DNS se crea solo si es público.
      18. Hook de Git — Commit.
      19. Repositorio en Forgejo — A Forgejo, donde pasa el CI.
      20. Repositorio de respaldo — Y al de respaldo, en segundo plano.
      Actualizo la flota
      1. Panel de terminales — Cada miércoles de madrugada se actualizan solos los paquetes; para el resto, un botón en Forgejo: qué (paquetes, contenedores o todo) y en qué equipos.
      2. Actualizaciones — Primero, una simulación por equipo.
      3. Ensayo con diferencias — Se rechazan cambios de kernel, drivers o servicios críticos.
      4. Actualizaciones — Se aplica equipo a equipo.
      5. Contenedores LXC — Cada contenedor tiene que volver sano antes de pasar al siguiente.
      6. Rol de endurecimiento — Los agentes de monitorización confirman, y el resumen llega al móvil: qué cambió y qué equipos piden reiniciar. Eso lo decido yo.
      Un plan que habría borrado datos
      1. Terraform — Centralizo las claves de SSH en una sola lista para todos los contenedores.
      2. terraform plan — El plan sale: 4 para crear, 4 para destruir.
      3. Cambios que recrean — Ese campo no se puede cambiar en sitio: recrearía los contenedores.
      4. Revisión — Entre ellos, la mensajería con toda su base de datos y la puerta pública.
      5. Contenedores LXC — No se aplica. Las claves se añaden a mano a los que ya existen y la lista vale para los nuevos.
      La copia pública, sola pero revisada
      1. Repositorio en Forgejo — Cada fusión genera la copia: solo los ficheros de una lista blanca; IPs, dominios, correos y claves cambiados por ejemplos; los secretos, por sus nombres sin valor; las funciones, reducidas a su firma y su descripción.
      2. Revisión — Un control de fugas la recorre entera y para cualquier dato real; también en el CI de cada PR. Si pasa, me llega el enlace a lo que cambiaría y lo reviso.
      3. Copia pública saneada — Con mi aprobación se publica en GitHub, solo si es exactamente lo que revisé y sin reescribir su historia.
      Reconstruir un servicio
      1. Terraform — Un contenedor se rompe sin arreglo.
      2. API de Proxmox — Terraform lo vuelve a crear.
      3. Contenedores LXC — Igual que estaba.
      4. Datos aparte — Se monta su almacenamiento con los datos.
      5. Roles — El rol lo configura.
      6. Contenedores LXC — Y el servicio vuelve. Antes era una tarde de prueba y error.
      1. Mi portátil

        Desde casa o la VPN, abro el panel de terminales.

      2. Repositorio en Forgejo

        Toda la infraestructura: Terraform, inventario, roles, playbooks, scripts y documentación. Los cambios entran por PR con CI y su plan a la vista. Tiene su propia unidad.

        • Git
        • Forgejo · Actions
      3. Repositorio de respaldo

        Un hook empuja cada commit a un segundo repositorio dentro de casa. Tiene su propia unidad.

        • Git
      4. Copia pública saneada

        La versión que enseño, generada sola en cada fusión: una lista blanca de ficheros, IPs de documentación, dominios de ejemplo y funciones reducidas a su descripción. Solo se publica si la apruebo.

        • Git
        • Linux / SSH hardening
      5. API de Proxmox

        Terraform habla con ella con un token de permisos justos.

        • Proxmox VE
      6. DNS de Cloudflare

        Los registros públicos se crean y se borran desde la misma lista de servicios.

        • Technitium DNS
      7. Panel de terminales

        Las sesiones reales de cada agente, en tmux, visibles desde el navegador detrás de la puerta interna.

        • Linux (Debian, Alpine, Arch)
      8. Agentes de IA

        Con los que trabajo: proponen y ejecutan, y yo reviso. Con suscripción, nunca con claves de API sueltas.

      9. Hook de Git

        Tras cada commit, empuja a los dos remotos en segundo plano.

        • Git
      10. Revisión

        El paso que no se salta: leer el plan o el diff antes de aplicar.

      11. Terraform

        Contenedores y VMs, su CPU, memoria, discos, red y cortafuegos.

        • Terraform
      12. terraform plan

        Qué se crearía, cambiaría o destruiría. Si dice «destroy» en algo que tiene datos, se para.

        • Terraform
      13. Estado de Terraform

        Lo que Terraform cree que existe. Se migró de máquina comprobando que el plan salía idéntico en las dos.

        • Terraform
      14. Cambios que recrean

        Algunos campos no se pueden cambiar en sitio: cambiarlos destruye y vuelve a crear el recurso.

        • Terraform
      15. Roles

        Uno por servicio, reutilizables: paquetes, configuración, servicio y comprobación final.

        • Ansible
      16. Secretos

        Ya no hay ficheros de secretos: cada grupo lee los suyos de OpenBao, en tokens de 15 minutos, y en el repositorio solo están sus nombres. En el público, ni eso: ejemplos.

        • Ansible
        • Linux / SSH hardening
      17. Ensayo con diferencias

        Qué ficheros cambiarían y cómo, sin cambiar nada.

        • Ansible
      18. Lista de servicios

        Una sola lista para rutas de Traefik, DNS de Cloudflare y panel de inicio.

        • Ansible
        • Traefik
      19. Contenedores LXC

        Un contenedor por servicio, casi todos sin privilegios.

        • LXC
        • Linux (Debian, Alpine, Arch)
      20. Rol de endurecimiento

        SSH solo con clave y desde orígenes concretos, servicios sobrantes fuera y agentes de monitorización instalados.

        • Linux / SSH hardening
        • Ansible
      21. Actualizaciones

        Los paquetes de toda la flota, solos cada miércoles de madrugada; las imágenes Docker y lo demás, con un botón en Forgejo. Ninguno se reinicia solo.

        • Ansible
        • Linux (Debian, Alpine, Arch)
      22. Datos aparte

        Los datos viven en ZFS y se montan en el contenedor. Los roles gestionan la configuración, no los datos.

        • ZFS

      Lo que uso de mi árbol

      Pulsa una habilidad: se encienden en el mapa las piezas donde la uso y te cuento para qué.

      Terraform
      Un fichero por contenedor o VM con el proveedor de Proxmox, plan antes de cada aplicación y cuidado con los campos que recrean.
      Ansible
      Un rol por servicio, secretos leídos de OpenBao, ensayo con --check --diff y actualizaciones de la flota equipo a equipo.
      Proxmox VE
      Terraform habla con su API con un token de permisos justos; el nodo de control vive en un contenedor del propio servidor.
      LXC
      Un contenedor por servicio, casi todos sin privilegios.
      ZFS
      Los datos de cada servicio viven en ZFS y se montan; los roles no los tocan.
      Git
      Todo versionado, con hook que empuja a dos remotos y una copia pública saneada.
      Forgejo · Actions
      El origen del repositorio: rama principal protegida, CI sin secretos, plan del PR y despliegue con un clic.
      Renovate
      Un PR por cada versión fijada que tiene versión nueva, con su suma oficial; se aplica con el mismo plan y el mismo clic.
      Linux (Debian, Alpine, Arch)
      Contenedores Debian, Ubuntu y Alpine configurados de forma uniforme.
      Traefik
      Sus rutas se generan desde la lista común de servicios.
      Technitium DNS
      Los registros de Cloudflare se crean y se borran desde la misma lista; el DNS de casa, también configurado desde aquí.
      Linux / SSH hardening
      Rol común: SSH solo con clave y desde orígenes concretos, servicios sobrantes fuera y monitorización en todos.
      OpenBao · Vault
      Todos los secretos y las credenciales de Terraform salen de OpenBao, no del repositorio ni del disco del nodo de control.
      CrowdSec
      Su rol instala el motor, sus fuentes y el resumen diario; la IP real detrás de Cloudflare y el plugin, en el de Traefik.
      Proxmox Backup Server
      El servidor de copias, su almacén, la tarea nocturna y la copia aparte de los mundos de los juegos, todo desde código.

      Bitácora de incidencias

      Averías reales. Lee el síntoma, elige la causa que creas y mira cómo se arregló.

      1. #1

        Un cambio inocente que destruía cuatro contenedores

        16-09-2026 · Terraform

        Quería añadir la clave de SSH del portátil a todos los contenedores desde una lista común. El plan dijo «4 to add, 4 to destroy».

        ¿Qué crees que pasaba?

        Ver la solución
        Causa
        En el proveedor de Proxmox, las claves de la cuenta del contenedor no se pueden cambiar en sitio: cualquier cambio destruye y crea de nuevo. Habría borrado la base de datos de la mensajería y tumbado la puerta pública.
        Solución
        No aplicar ese plan. Añadir las claves a mano en los contenedores existentes; la lista común queda para los que se creen desde ahora.
        Lección
        El plan es el freno. Un «destroy» en algo con datos se lee dos veces, aunque el cambio parezca inocente.
      2. #2

        Renombrar un recurso

        Septiembre de 2026 · Terraform

        Al poner un nombre más claro a un recurso en el código, el plan quiso destruir el contenedor y crear otro igual.

        ¿Qué crees que pasaba?

        Ver la solución
        Causa
        Terraform identifica cada recurso por su dirección en el código. Si cambia, cree que el viejo sobra y que falta uno nuevo.
        Solución
        Mover el recurso en el estado a su nombre nuevo antes de aplicar. El plan pasa a no tener cambios.
        Lección
        En Terraform, renombrar no es cosmético. Primero se mueve en el estado, después se comprueba que el plan está vacío.
      3. #3

        Comillas que se rompían por el camino

        16-09-2026 · scripts

        Un script que registra contenedores en la monitorización fallaba de formas distintas cada vez: comillas cortadas, saltos de línea perdidos.

        ¿Qué crees que pasaba?

        Ver la solución
        Causa
        Para llegar al contenedor el código viajaba por tres capas de shell, y cada una reinterpretaba comillas y saltos de línea.
        Solución
        Mandar el código siempre en base64 y decodificarlo al otro lado antes de ejecutarlo. El problema desaparece de raíz.
        Lección
        Cuando se parchea caso por caso y sigue fallando, hay que cambiar el transporte, no seguir escapando.
      4. #4

        Los respaldos dejaron de recibir commits

        09-10-2026 · Git

        Los commits se hacían bien, pero los dos remotos llevaban un rato sin recibir nada. Ningún error a la vista.

        ¿Qué crees que pasaba?

        Ver la solución
        Causa
        El hook empuja en segundo plano, así que sus errores no se ven. Tras corregir un commit que ya estaba en los remotos, las historias divergieron y cada push posterior se rechazaba.
        Solución
        Comprobar qué tenía cada remoto y forzar con protección (solo si nadie ha empujado otra cosa entretanto).
        Lección
        Lo que corre en segundo plano necesita una comprobación visible. Tras reescribir historia, mirar los remotos.

      Cómo se construyó

      1. Septiembre de 2026

        Primeros recursos

        • Token de Proxmox con permisos justos y un contenedor de prueba que luego se retiró.
        • La puerta pública, primero clonada y probada, después migrada.
        • Mensajería, panel de inicio y DNS de Cloudflare desde la misma lista.
      2. Septiembre de 2026

        Toda la flota

        • Plex, automatizaciones, documentos y monitorización migrados a código, siempre con el original parado como red.
        • Rol de endurecimiento común y registro de monitorización en un comando.
      3. 22-09-2026

        Control desde el servidor

        • El nodo de control pasa de mi PC a un contenedor del servidor, con el plan idéntico en ambos.
        • Panel de terminales con los agentes de IA, detrás de la puerta interna.
        • Copia pública saneada en GitHub.

      Decisiones (y por qué)

      • Qué hace cada herramienta

        Terraform crea, Ansible configura

        Terraform sabe qué existe y lo compara con el código; Ansible sabe dejar una máquina en un estado. Mezclarlos hace que ninguno sepa del todo qué pasa.

      • Versiones

        Fijadas

        Volver a ejecutar un playbook no debe actualizar nada por sorpresa. Actualizar es un cambio explícito, con su commit.

      • Los datos

        Aparte de los roles

        Un rol que toca datos es un rol que puede borrarlos. Los datos viven en almacenamiento montado y se restauran por su lado.

      • Migrar sin riesgo

        El original parado, no destruido

        Cada migración deja el contenedor antiguo apagado como vuelta atrás hasta que el nuevo lleva días funcionando.

      Lo que aprendí

      • El plan es el freno de mano: un «destroy» inesperado se lee antes de seguir.
      • Separar lo que existe (Terraform), cómo está (Ansible) y los datos.
      • Migrar con el original parado al lado.

      Lo siguiente

      • Pasar a código lo que queda a mano: el gestor de stacks Docker con todos sus servicios.
      • Llevar también la configuración del router a código.

      ¿Hablamos?

      Puedo contar cualquiera de estas decisiones en detalle en una entrevista.

      Descargar CV Contactar ← Volver al rack

      Hay una copia pública y saneada del repositorio en mi GitHub. Aquí no aparecen direcciones, tokens ni reglas de cortafuegos.