El objetivo#

Un mini-NAS en casa —la mininas— sirviendo mis servicios self-hosted con TLS, dominios propios y todo reproducible. El resultado: k3s + Istio + cert-manager, y encima Nextcloud, WordPress, Mealie e Immich, cada uno con su base de datos, detrás de Cloudflare.

El stack#

Cliente → Cloudflare (proxy + SSL) → duckdns → router (PAT 443→30443)
        → Istio ingress (NodePort) → Gateway + VirtualService → Service → App (+ BD)
  • k3s (Traefik deshabilitado), Kubernetes ligero de un nodo.
  • Istio para el ingress y el routing por host (un Gateway/VirtualService por app).
  • cert-manager + Let’s Encrypt (DNS-01 vía API de Cloudflare) para el TLS.
  • SSD para las bases de datos, HDD (btrfs) para los ficheros pesados.

Las cicatrices (lo que de verdad enseña)#

  • 404 intermitentes: dos Gateway de Istio con el mismo host/puerto peleándose. Lección: un solo Gateway por host.
  • Un MariaDB multi-inquilino heredado: no se copia “la carpeta de una base” con InnoDB compartido → dump lógico por base, una instancia por app.
  • BDs al SSD, medios al HDD: los datadirs vuelan en SSD; las fotos no piden IOPS.
  • REDIS_PORT=NaN en Immich: Kubernetes inyecta variables de Service que chocan. Fix: enableServiceLinks: false.
  • La IP fantasma del reinicio: una IP secundaria se añadía con un hook de ifupdown que con netplan no se ejecuta. Lo que no es declarativo, no sobrevive a un reboot.

Lecciones#

  1. Declarativo o no existe.
  2. Una BD por app, en su namespace.
  3. Un Gateway por host.
  4. Reserva de recursos con cabeza en un nodo pequeño.
  5. Backups re-aplicables como primer paso hacia GitOps.

Montado sobre una mini-NAS, con más kubectl y café de los recomendables.