Problema
En entornos homelab con varios orquestadores (Docker, Kubernetes, LXC/VM en Proxmox) y servicios de red distribuidos, cada nueva aplicación exige una cadena de pasos repetitivos: reserva DHCP, registros DNS internos y externos, configuración de Traefik, reglas de Authelia, usuarios de bases de datos, documentación en Netbox y wikis, entre otros. Cuando el número de apps supera unas cuantas decenas, la lista se vuelve una carga operativa que ralentiza la entrega y aumenta la probabilidad de errores manuales. El patrón que se repite es la fragmentación de la configuración: cada componente tiene su propio fichero o UI y no existe una fuente única de verdad que pueda ser consumida por los distintos sistemas de automatización.
Causa
- Ausencia de modelo de datos centralizado – Sin un esquema que describa de forma estructurada todos los recursos que una aplicación necesita, cada herramienta (Ansible, Terraform, OpenTofu, etc.) requiere su propio set de variables.
- Dependencias implícitas – La creación de una IP en Netbox, por ejemplo, está vinculada a la generación de un registro A en la zona
.homelab. Cuando esas dependencias no están declaradas explícitamente, los pipelines pueden ejecutar pasos en orden incorrecto. - Herramientas aisladas – Usar Docker‑Compose, Helm, y scripts de Proxmox por separado obliga a mantener tres fuentes de configuración paralelas.
- Falta de validación temprana – Los errores de sintaxis o de lógica en la definición de la aplicación solo se detectan al final del proceso, cuando ya se han creado recursos parciales.
Solución
Adoptar un archivo de metadata único que actúe como contrato entre la aplicación y todos los sistemas de infraestructura. El archivo, escrito en YAML, contiene secciones estandarizadas: network, dns, traefik, authelia, guest_deploy, monitoring, databases, etc. Cada sección sigue un esquema predefinido y es validada por un linter antes de que el CI continúe.
Paso a paso reutilizable
- Definir el esquema – Usa JSON‑Schema o una herramienta como
yamalepara describir los campos obligatorios y sus tipos. Incluye reglas de dependencia (p.ej., sidnsestá presente,networkdebe existir). - Detectar cambios – En el pipeline CI, compara la lista de archivos
metadata/*.ymlcontra la rama base. Si más de un archivo cambia, aborta o solicita revisión manual. - Validar – Ejecuta el linter contra el esquema. Cualquier violación detiene el pipeline.
- Reservar recursos – Un script consulta Netbox para obtener una IP libre en la VLAN indicada y actualiza el bloque
network. De forma similar, asigna una base de datos PostgreSQL o una instancia Redis, guardando la referencia en Netbox como campo personalizado. - Generar artefactos – A partir del metadata se generan:
- Manifiestos Terraform/OpenTofu (
*.tfvars) para DNS (Knot, Cloudflare). - Configuración de Traefik (ExternalName services, IngressRoutes).
- ACLs y clientes OIDC para Authelia.
- Archivos
docker‑compose.ymlo Helm values según la plataforma. - Inventario Ansible para Proxmox.
- Configuración de Gatus y Prometheus.
- Manifiestos Terraform/OpenTofu (
- Commit automático – Los archivos generados se añaden al PR con
[skip ci]para evitar bucles. - Despliegue post‑merge – OpenTofu aplica la infraestructura, Ansible despliega contenedores o máquinas, y los wikis se actualizan mediante rsync.
Este flujo desacopla la lógica de negocio (qué necesita la app) de la implementación (cómo se crea). Cada nuevo servicio solo requiere añadir o actualizar su bloque metadata; el resto del pipeline se encarga del resto.
Alternativas prácticas
- Usar Helm charts genéricos que consuman valores desde el metadata y deleguen la generación de recursos a Helm.
- Integrar con Pulumi si prefieres código en vez de HCL/TF.
- Persistir el metadata en GitOps (ArgoCD, Flux) para que cualquier cambio sea versionado y auditado automáticamente.
Cuándo aplicar esta solución
- Entornos con múltiples orquestadores (Docker, K8s, LXC/VM) donde cada aplicación necesita recursos de red, DNS y bases de datos.
- Equipos pequeños que gestionan manualmente la mayor parte de la infraestructura y buscan reducir la carga operativa.
- Repositorios de configuración donde la trazabilidad y la reproducibilidad son críticas (por ejemplo, auditorías de seguridad).
No es recomendable cuando la infraestructura es estática y solo se despliegan unas pocas aplicaciones; el coste de mantener el esquema puede superar los beneficios.
Código
# Detectar apps modificados y abortar si son más de una
git diff --name-only origin/main...HEAD | grep '^metadata/.*\.yml$' | \
awk -F'/' '{print $2}' | sort -u > /tmp/changed_apps.txt
if [ $(wc -l < /tmp/changed_apps.txt) -gt 1 ]; then
echo "Error: más de una aplicación modificada en el MR"
exit 1
fi
# Validar con yamale (asume schema.yml en la raíz)
while read app; do
yamale -s schema.yml metadata/$app.yml || exit 1
done < /tmp/changed_apps.txt
Verificación
- Revisión del PR – Verifica que el archivo
metadata/*.ymly los artefactos generados aparecen en el diff. - Estado de Netbox – Comprueba que la VM y sus interfaces aparecen con la IP asignada y, si corresponde, con el campo Redis enlazado.
- DNS – Usa
digonslookuppara confirmar que los registros A/CNAME están presentes tanto en la zona interna como en Cloudflare. - Traefik – Accede a la UI de Traefik y verifica que el router y el servicio aparecen con el backend correcto.
- Authelia – Prueba el flujo de login OIDC; la regla de ACL debe aplicarse según lo definido en
metadata. - Monitorización – Asegúrate de que Gatus y Prometheus scrapean la nueva URL sin errores.
Notas adicionales
- Idempotencia: los scripts que reservan IP o bases de datos deben ser idempotentes; si el recurso ya está asignado, simplemente lo devuelven sin crear duplicados.
- Gestión de secretos: genera contraseñas con
openssl rand -base64 16y almacénalas en unsecrets.ymlcifrado (sops, age). Nunca committees valores en claro. - Orden de despliegue: la mayoría de los pipelines fallan cuando intentan crear un registro DNS antes de que la IP exista en Netbox. Mantén la dependencia explícita en el esquema.
- Escalado: para homelabs que crecen a cientos de apps, considera particionar el metadata por dominio (p.ej.,
metadata/docker/,metadata/k8s/) y usar un script de descubrimiento que recorra todos los sub‑directorios. - Rollback sencillo: al mantener el metadata bajo control de versiones, revertir un despliegue equivocado es tan fácil como volver al commit anterior y ejecutar el pipeline de nuevo.
Con un archivo de metadata bien estructurado y un pipeline que lo consuma, la mayor parte del trabajo manual desaparece. El resultado es un proceso de despliegue predecible, auditado y reproducible, ideal para cualquier homelab que combine Docker, Kubernetes, LXC y VMs bajo una misma estrategia de DevOps.