Un homelab como código: Proxmox, dos Kubernetes y GitOps en un miniPC

MiniPC doméstico con un monitor que muestra un esquema de máquinas virtuales y clústeres

Un único miniPC de segunda mano con Proxmox VE basta para mantener dos clústeres Kubernetes, un almacén de secretos, un servidor NFS y varios servicios de red doméstica, todo descrito como código en un repositorio público. Es el planteamiento del proyecto homelab de Maxym Gryn, que reparte el trabajo entre Terraform, Ansible y ArgoCD y documenta tanto lo que funciona como lo que se rompió por el camino. Su objetivo declarado es que, si el disco muere, el entorno pueda reconstruirse desde Git y una lista corta de cosas que Git no guarda.

Las claves del homelab como código con Proxmox y Kubernetes en 30 segundos

  • Un Dell OptiPlex 3090 Micro con 32 GB de RAM y Proxmox aloja dos clústeres Kubernetes: kubeadm para desarrollo y Talos para producción.
  • Terraform crea las máquinas virtuales y los contenedores LXC, Ansible los configura y ArgoCD despliega las aplicaciones desde la rama main.
  • Los secretos viven en HashiCorp Vault y los certificados salen de Let’s Encrypt con validación DNS-01.
  • El autor reconoce que un solo host y copias en el mismo SSD no protegen frente a un disco muerto.

El autor explica que quería alojar algunos proyectos web sin recurrir a la nube y probar un entorno propio. Descartó un servidor usado por el ruido, el consumo y el espacio, y se quedó con un Dell OptiPlex 3090 Micro comprado de segunda mano: procesador Intel Core i5-10500T, 32 GB de DDR4 y un SSD NVMe de 1 TB, con un consumo en reposo de entre 8 y 12 W según sus mediciones. La pregunta difícil, escribe, no era el hardware sino cómo gestionar lo que corre encima sin acabar con una máquina llena de cambios manuales imposibles de reproducir.

Qué corre en un solo Proxmox

El host Proxmox, con un único SSD, se divide en tres grupos de máquinas, cada uno con su propia raíz de Terraform:

  • Desarrollo: un clúster Kubernetes montado con kubeadm (un nodo de control y un worker) y una máquina virtual donde el autor ejecuta Claude Code.
  • Producción: un clúster con Talos Linux, el sistema operativo inmutable pensado solo para Kubernetes, con un nodo de control y dos workers.
  • Compartido: una máquina virtual con HashiCorp Vault, un servidor NFS y contenedores LXC para la red de casa: Pi-hole (DNS y bloqueo de publicidad), Traefik (proxy inverso), Glance (panel), Gatus (comprobaciones de disponibilidad con avisos por Telegram) y Orangutan (descubrimiento de dispositivos).

El propio autor bromea con que desarrollo y producción están completamente separados, salvo por la máquina, el almacenamiento, la fuente de alimentación y todo lo demás que puede arruinar una tarde. La separación sirve para experimentar en un clúster sin tocar el otro, pero no elimina el host compartido como punto único de fallo.

El almacenamiento persistente lo da el servidor NFS, que exporta un recurso para desarrollo (la clase de almacenamiento predeterminada) y otro solo para los workers de producción. Todas las máquinas tienen dirección IP estática fuera del rango DHCP del router.

Tres herramientas, tres trabajos distintos

La automatización está separada en capas. Terraform crea las máquinas virtuales y los contenedores LXC en Proxmox. Ansible configura lo que hay dentro: el clúster kubeadm, el runtime containerd, el NFS, Vault y los servicios de la red local. ArgoCD entrega las aplicaciones de Kubernetes desde Git. El autor justifica la división porque aprovisionar, configurar el sistema operativo y desplegar aplicaciones son problemas diferentes, cada uno con sus propias formas de fallar, y mezclarlos complica la depuración.

La regla de la capa Kubernetes es estricta: ArgoCD sincroniza la rama main de GitHub, no la copia de trabajo local. Un commit no es un despliegue, una rama subida tampoco y una pull request abierta tampoco. Solo fusionar en main despliega, así que el autor abre la PR, la revisa y la fusiona él mismo cuando está listo para vigilar cómo se aplica.

El clúster Talos de producción hace además de centro del GitOps. Su ArgoCD, instalado con un playbook de Ansible, usa una aplicación raíz (el patrón app of apps) y un ApplicationSet que genera las aplicaciones de producción a partir de un archivo de configuración por aplicación, y también gestiona los despliegues en el clúster de desarrollo. La entrada HTTP corre con ingress-nginx como DaemonSet en los puertos 80 y 443. Detrás hay una carga real: una aplicación de ofertas de empleo del autor con PostgreSQL, en producción en Talos y con desarrollo como entorno de pruebas. Su código está en un repositorio privado; el público solo contiene la configuración de despliegue y la imagen publicada.

Tener dos clústeres con herramientas distintas es intencionado. Con kubeadm, configurado por Ansible junto a containerd, y con Talos, gestionado por su propio módulo de Terraform, el laboratorio ofrece dos modelos de operación de Kubernetes en lugar de dos copias del mismo. Para quien quiera practicar con un enfoque similar, en este medio ya explicamos cómo gestionar Proxmox VE con Terraform.

Secretos, certificados y monitorización como parte de la plataforma

Ningún secreto se guarda en claro en los manifiestos. Estos llevan marcadores del tipo <path:kv-prod/data/…#CAMPO> y el complemento ArgoCD Vault Plugin los sustituye por el valor real en el momento de sincronizar. Desarrollo y producción leen rutas distintas de Vault.

Los certificados HTTPS siguen dos caminos. Los servicios de Kubernetes usan cert-manager y los servicios de la red local que están detrás de Traefik usan la automatización de certificados del propio Traefik. Ambos piden certificados a Let’s Encrypt con validación DNS-01 a través de la API de Cloudflare, pero con tokens distintos, para poder revocar uno sin tocar el otro. Los nombres públicos son registros de Cloudflare sin proxy que apuntan a direcciones privadas, de modo que cualquier equipo de la red local los resuelve sin tocar el archivo hosts. El repositorio advierte de que algunos routers bloquean esas respuestas como protección contra ataques de DNS rebinding.

La monitorización vive en producción con kube-prometheus-stack (Prometheus, Grafana y Alertmanager). Desarrollo ejecuta un agente de Prometheus que envía métricas al centro, y un exportador recoge también las de Proxmox. Las alertas llegan por Telegram. Los paneles de Grafana se escriben en Jsonnet y se generan como JSON que también se guarda en el repositorio, para que la monitorización no sea otro conjunto de cambios manuales que reconstruir.

Lo que se rompió y las reglas que dejó

La parte más útil del proyecto para cualquier administrador son los fallos, que el autor ha convertido en instrucciones del repositorio y en registros de decisiones de arquitectura (ADR):

  • Renombrar un módulo de Terraform destruyó el clúster de desarrollo. Terraform identifica los recursos por su dirección, así que un nombre nuevo equivale a borrar lo viejo y crear lo nuevo. Un cambio de una línea reconstruyó las tres máquinas desde una plantilla vacía y hubo que restaurar la base de datos. Desde entonces, todo cambio de nombre lleva un bloque moved.
  • Una aplicación «Healthy» que nadie podía abrir. Grafana apareció como sana en ArgoCD durante horas sin ser accesible porque no existía ningún controlador de ingress. Que algo esté sincronizado solo significa que Kubernetes ha aceptado los manifiestos, no que sirva tráfico. Ahora el autor comprueba el servicio con curl y kubectl get pods.
  • Vault sellado falla en silencio. Tras un reinicio, Vault arranca sellado, el complemento no rellena nada, las aplicaciones pasan a estado de sincronización desconocido y ArgoCD sigue mostrando salud correcta. Lo primero que revisa cuando una aplicación deja de sincronizar es vault status.
  • El orden importa. La primera configuración del complemento de Vault montaba un ConfigMap que todavía no existía y dejó el servidor de repositorios de ArgoCD atascado en Init durante seis horas. La solución fue crear las dependencias antes de lanzar el despliegue con Helm.

El repositorio valida cada cambio antes de que llegue al laboratorio. Los ganchos locales de pre-commit revisan formato, YAML, claves privadas y secretos con gitleaks, scripts con shellcheck, Ansible con ansible-lint en perfil de producción y el formato de Terraform y Jsonnet. En GitHub Actions, siete trabajos en paralelo repiten esos controles y añaden validación de Terraform, renderizado y comprobación de los manifiestos con kustomize y kubeconform, la expansión del ApplicationSet y la coincidencia de los paneles con sus fuentes. La integración continua es de solo lectura a propósito: no toca Proxmox, ni los clústeres, ni ningún secreto. Las dependencias se actualizan con Renovate.

Git no es todo el plan de recuperación

Uno de los archivos más importantes del proyecto es docs/rebuild.md, la guía para reconstruir tras cambiar el disco o perderlo todo. Lo relevante es que enumera lo que el repositorio no contiene: el propio Proxmox, el archivo de contraseñas secret.yaml cifrado con ansible-vault, los *.tfvars excluidos de Git y los certificados de Talos guardados en el estado de Terraform. El autor resume la lección en que tener la configuración en Git no equivale a tener todo lo necesario para recuperarse.

También es explícito con los límites. Un solo host físico significa que no hay conmutación por error, y las copias de seguridad están en el mismo SSD que protegen: sirven ante una actualización fallida o un secreto borrado, no ante un disco muerto. Por eso considera que todo lo que describe es una afirmación hasta probarlo desde cero. Su siguiente paso es sacar las copias de la máquina, borrar Proxmox y reconstruir siguiendo solo lo que está escrito, corrigiendo la guía en cada punto en el que tenga que improvisar.

De su experiencia saca cuatro consejos aplicables fuera de un homelab: escribir el registro de decisión después del primer fallo, comprobar el servicio en sí y no solo la pantalla de estado de una herramienta, apuntar qué no guarda Git antes de necesitarlo y mantener la integración continua sin acceso a producción. La idea de fondo es la distancia entre «configurado» y «funcionando», que según el autor fue el origen de casi todo lo que salió mal.

Preguntas frecuentes

¿Qué hardware usa este homelab?

Un Dell OptiPlex 3090 Micro de segunda mano con Intel Core i5-10500T, 32 GB de DDR4 y un SSD NVMe de 1 TB, que según su autor consume entre 8 y 12 W en reposo.

¿Por qué usa dos clústeres Kubernetes distintos?

Para tener dos modelos de operación: kubeadm configurado con Ansible en desarrollo y Talos Linux gestionado con Terraform en producción, en lugar de dos copias iguales.

¿Cómo gestiona los secretos?

Con HashiCorp Vault. Los manifiestos llevan marcadores y ArgoCD Vault Plugin los sustituye por los valores reales al sincronizar, con rutas separadas para desarrollo y producción.

¿Basta con tener la infraestructura en Git para recuperarla?

No. El proyecto mantiene una guía de reconstrucción que lista lo que Git no guarda, como contraseñas, variables de Terraform y certificados, y el autor reconoce que sus copias en el mismo disco no cubren una avería del SSD.

Fuentes:

Suscríbete al boletín SysAdmin

Este es tu recurso para las últimas noticias y consejos sobre administración de sistemas, Linux, Windows, cloud computing, seguridad de la nube, etc. Lo enviamos 2 días a la semana. Recuerda revisar tu email para confirmar la suscripción.

Scroll al inicio
×