Mi Homelab 2026 Stack Self-Hosted SRE

Published on June 20, 2026

Mi Homelab 2026: Stack Completo de un Self-Hosted SRE

Siempre me ha gustado tener mi propio laboratorio: pequeño, intencional y reproducible. Este post documenta la arquitectura que tengo corriendo hoy, por que decidi cada pieza asi, y como se conectan los componentes entre si. Si estas empezando tu propio homelab o simplemente sientes curiosidad, espero que te sirva de mapa mental.

Nota sobre seguridad: Las direcciones IP de mi red interna fueron ofuscadas. La topología, los roles y los servicios son reales; los numeros exactos, no. Si quieres replicar algo parecido, los rangos privados 192.168.x.0/24 o 10.x.0.0/16 te sirven igual.

Visión general en una sola imagen mental

Internet
   │
   ▼
[pfSense]  ◄── OpenVPN (mi unica puerta de entrada)
   │
   ▼
LAN 192.168.x.0/24
   │
   ├── [services]      PostgreSQL 16 + NFS
   ├── [ia-server]     Hermes Agent (mi casa)
   └── [Proxmox VE]
         └── 3 VMs Kubernetes v1.34.1
              ├── k8svmm1  control-plane
              ├── k8svmn1  worker
              └── k8svmn2  worker (con VIP MetalLB)
                    ▲
                    └── [MetalLB] ──► [NGINX Gateway] (puerto 443)
                                              │
                                              ▼
                                       Apps vía ArgoCD
                                  (portfolio, crafthost, ...)

Vamos capa por capa.


1. pfSense: el portero del homelab

Toda la red cuelga de un pfSense que hace de firewall, router y servidor OpenVPN. Decisiones clave:

  • Es la unica pieza con salida directa a Internet. Ningun servidor de mi LAN puede hablar hacia afuera por si mismo; el trafico saliente pasa por NAT en pfSense y queda logueado.
  • OpenVPN es como entro a administrar todo desde fuera. Sin VPN, no hay SSH. Sin SSH, no hay nada. Esto reduce drasticamente la superficie de ataque: aunque alguien encontrara mi IP publica, no tiene credenciales validas ni puertos relevantes expuestos.
  • DNS: 8.8.8.8 directo. No tengo DNS local. Es una decision deliberada: cualquier resolución de nombre es trivial de auditar en pfSense, y no quiero un punto mas donde meter reglas de firewall.
  • Hardware dedicado. pfSense corre en una maquina fisica propia, no en una VM dentro de Proxmox. Si el hipervisor se cae, sigo pudiendo entrar a la red por VPN para arreglarlo. Es la unica "dependencia blanda" que permito en el diseño.

2. Proxmox VE: la base de virtualización

Sobre el hipervisor corro Proxmox VE con cuatro VMs (las tres de Kubernetes que veremos en la siguiente sección, mas services y ia-server). Hay una pieza mas que no es VM: Proxmox mismo corre sobre el hierro fisico, y no expone su puerto de management (8006) en la LAN .x (lo deje fuera de ese segmento a proposito, por higiene).

Las VMs comparten el prefijo MAC bc:24:11, que es el rango que Proxmox auto-genera. Eso me sirve a la hora de correlacionar ARP: cualquier MAC que empiece por ahi es "cosa mia".


3. PostgreSQL 16 + NFS: la pieza de datos

La VM services es mi "capa de datos" del homelab. Dos servicios:

  • PostgreSQL 16: lo usan todas las apps del cluster de Kubernetes (este blog, CraftHost, y lo que se venga). Conexiones desde los nodos K8s a traves de la LAN, sin exposing el puerto al exterior. Las contraseñas viven en Kubernetes Secrets, nunca en archivos de configuración.
  • NFS server: lo uso para volumenes persistentes en K8s via el driver CSI nativo. Es comodo, pero tiene un trade-off: por simplicidad tengo no_root_squash en /etc/exports, lo que significa que el root del cliente NFS se mapea a root del servidor. Esto lo se y lo acepto porque el NFS solo es accesible desde la LAN y no hay multi-tenancy. En un entorno con varios usuarios lo dejaria en root_squash si o si.

4. Kubernetes v1.34.1: 3 nodos y a vivir

El cluster es deliberadamente pequeño: un control-plane y dos workers, todos Ubuntu 24.04, todos con 4 vCPU y 7.7 GiB de RAM. La idea es tener un cluster "serio" pero donde un solo nodo caido se note y duela - asi aprendo de verdad a operarlo.

  • k8svmm1 (control-plane): corre kube-apiserver, etcd, controller-manager, scheduler. Lo descubri en una auditoria de puertos y me di cuenta que etcd (2379/2380) estaba expuesto en la interfaz de la LAN sin firewall. Lo deje documentado como hallazgo: cualquier pod o servicio comprometido en la red podria leer el estado del cluster. En produccion esto iria en una interfaz interna o con NetworkPolicy estricta. Para mi homelab, lo asumo como riesgo calculado por la simplicidad.
  • k8svmn1 y k8svmn2 (workers): los dos identicos en recursos. El segundo tiene ademas el alias IP .56 que aparecio en el barrido ARP - es la IP que usa Calico/IPVS internamente, no algo que yo exponga a proposito.

Herramientas de red del cluster

  • CNI: Calico para networking y NetworkPolicy.
  • MetalLB en modo Layer 2: expone servicios LoadBalancer con IPs del rango .x real. El VIP publico del cluster es .230 y esta atado a la MAC de uno de los workers - cuando ese worker cae, MetalLB migra el VIP al otro (con el blip de ARP correspondiente, claro).
  • NGINX Gateway (Gateway API, no Ingress): escuchando en el VIP .230 por los puertos 80 y 443. Es el punto de entrada de todo el trafico HTTPS al cluster.
  • Cert-manager + cert-manager-csi-driver emiten los certificados TLS automaticamente con ACME (Let's Encrypt via DNS-01).

Gestion: kubectl y ArgoCD, sin SSH a nodos

Una regla sagrada: no hago SSH a los nodos del cluster. Toda la operacion pasa por: - kubectl desde ia-server para reads y debugging puntual - ArgoCD para cualquier cambio de estado

Si un nodo se rompe, lo re-creo desde Proxmox. No entro a "arreglarlo" a mano. Esa disciplina evita que acumule drift entre lo que esta en Git y lo que corre de verdad.


5. ArgoCD y el patrón app-of-apps

ArgoCD es el corazon del homelab en cuanto a operaciones. Lo tengo desplegado en el namespace argocd y esta accesible (solo por VPN) en argocd.x.luisito.dev.

El patron que uso es app-of-apps:

ApplicationSet "apps" (root)
  ├── Application portfolio
  ├── Application crafthost
  ├── Application nginx-gateway
  ├── Application cert-manager
  ├── Application metallb
  ├── Application postgresql-external  (referencia al .20)
  └── Application nfs-csi

La aplicacion raiz (apps) tiene un ApplicationSet o un repo de Helm/Jsonnet que describe toda la flota. Cuando quiero anadir una app nueva:

  1. La empaqueto como Helm chart en su propio repo.
  2. Anado un Application o ApplicationSet al repo de bootstrap.
  3. Hago commit, push, abro PR.
  4. ArgoCD reconcilia en pocos minutos.

No hay kubectl apply manuales. Si algo esta en el cluster y no esta en Git, es un bug.

Apps que corren hoy

  • portfolio-blog (este sitio): Django 5.2, base de datos Postgres en services, dos apps (portfolio y blog), expuesto en luisito.dev via el Gateway. Desplegado con su propio Helm chart.
  • CraftHost: el backend de un servidor de Minecraft que mantiene un grupo pequeno de amigos. Son 9 microservicios coordinados por ArgoCD.
  • NGINX Gateway + cert-manager: la pieza de ingress.
  • MetalLB: para los LoadBalancer services.
  • NFS CSI + un operator de PostgreSQL externo: la integracion con services.

Todas las imagenes se construyen en GitHub Actions y se suben a GitHub Container Registry, y los deployments leenlas por digest (no por tag) para tener despliegues reproducibles.


6. ia-server: la casa de Hermes

La VM ia-server es donde corro Hermes Agent, el asistente con el que estoy escribiendo este post. Es una VM Ubuntu 24.04 pequeña dedicada a esa unica tarea.

  • Sin acceso directo a Internet. Toda comunicacion con APIs externas (como el modelo de lenguaje que uso) pasa por el tunel de OpenVPN hasta pfSense, y de ahi sale. Esto me da un punto de auditoria centralizado y evita que la VM pueda exfiltrar datos sin que yo lo vea en los logs de pfSense.
  • Acceso solo por Telegram. Mi unica UI con Hermes es un chat de Telegram cifrado. No tiene web UI expuesta ni API publica.
  • Disco encriptado con LUKS. Si alguien se lleva el disco fisico, no lee nada sin la passphrase.

Es deliberadamente minima. Cuantas menos cosas corra ahi, menos superficie de ataque tengo.


Lecciones aprendidas (las que dolieron)

  1. Empezar con un cluster de 3 nodos en vez de 1 nodo "todo-en-uno". Los dos primeros meses use un solo nodo, y cuando quise simular una caida de control-plane no podia. Migrar de 1 a 3 nodos fue molesto, pero ahora puedo practicar todo lo que importa.
  2. El DNS interno no es tan necesario como parece. Tener 8.8.8.8 directo simplifica muchisimo el setup inicial. Si un dia necesito DNS local, lo añadire; mientras tanto, YAGNI.
  3. No exponerse a uno mismo mas de lo necesario. pfSense solo, SSH solo por VPN, sin dashboards de Proxmox en la LAN "normal", etc. La paranoia paga sola.
  4. GitOps desde el dia 1. ArgoCD y app-of-apps me obligan a ser disciplinado, pero me han ahorrado incontables horas de "que paso?" cuando algo cambia solo.

Que viene despues

  • Aprender mas de Gateway API y migrar los Ingress que aun me quedan.
  • Backups automaticos de PostgreSQL a otro host (hoy dependo de los snapshots de Proxmox).
  • Quizas un nodo GPU para experimentar con modelos locales.