No sabría entender este trabajo sin la investigación. Tras tres años en el CERN, al volver a Bilbao decidí trabajar por mi cuenta y seguir investigando y aprendiendo. Creo que emprender es el reto profesional definitivo, y a la vez una expresión de creatividad y un reclamo de libertad.
Zetesis viene del griego ζήτησις, indagación: buscar la causa antes de proponer la solución.
Montar un homelab desde cero: seguridad y operaciones - Homelab (04/06)
Caso realHomelabSeguridadOperaciones
En el Post 3 vimos cómo las aplicaciones pasan de Git a contenedores en ejecución. Pero nos saltamos una pregunta crítica: ¿cómo llegan los secretos a esos contenedores?
Una contraseña de base de datos, un token de API, un certificado TLS — nada de esto puede vivir en Git en texto plano. Y una vez desplegados, hay que respaldarlos. Y si todo falla, necesitas una forma de reconstruir desde cero.
Este post cubre las tres capas de gestión de secretos, la estrategia de backup, la domótica, y lo que necesitarías para recuperarte de un desastre total. Es lo aburrido pero imprescindible que marca la diferencia entre un proyecto de fin de semana y una infraestructura en la que puedes confiar.
El problema de los secretos
Todo el homelab se gestiona desde un único repositorio Git. Genial para reproducibilidad y auditoría, pero genera una tensión: las configuraciones tienen que estar en Git para que funcione el despliegue GitOps, los secretos no pueden estar en Git por razones obvias de seguridad, y aun así los secretos tienen que llegar a los servicios de forma automática en el momento del despliegue.
No hay una sola herramienta que resuelva esto. Son tres, cada una para una parte del problema.
Capa 1: Infisical (la caja fuerte)
Infisical es un gestor de secretos autoalojado. Pensad en él como un almacén de contraseñas para la infraestructura. Todos los secretos del homelab — contraseñas de bases de datos, tokens de API, credenciales OAuth, contraseñas SMTP — viven en Infisical como fuente única de verdad.
Infisical corre en el clúster escipion (red Roma) y es accesible en secrets.zetesis.localhost. Al ser autoalojado, los secretos nunca salen del control del homelab.
Dos vías de salida
Para servicios Docker Compose — ptolomeo (el agente de CD) obtiene los secretos de Infisical en el momento del despliegue y los inyecta como variables de entorno:
# .doco-cd.yaml — ptolomeo lee esto
external_secrets:
DB_PASSWORD: <project-id>:prod:/my-app/DB_PASSWORD
SMTP_HOST: <project-id>:prod:/my-app/SMTP_HOST
Cuando ptolomeo despliega un stack, llama a la API de Infisical, obtiene los valores, los escribe en .env y ejecuta docker compose up. El contenedor ve DB_PASSWORD=xyz123 como una variable de entorno normal.
Para Kubernetes — el External Secrets Operator (ESO) corre dentro del clúster y sincroniza periódicamente los secretos de Infisical como Secrets nativos de Kubernetes:
ESO crea un Secret de Kubernetes llamado web-secrets con los valores de Infisical. Los pods lo montan como variables de entorno o ficheros — sin saber de dónde vienen los secretos.
ESO refresca cada minuto. Si rotas una contraseña en Infisical, el Secret de Kubernetes se actualiza automáticamente. Sin necesidad de redesplegar.
El patrón ClusterSecretStore
En alejandro, los secretos se organizan con componentes Kustomize siguiendo el mismo patrón base/overlay que la infraestructura (del Post 3):
manifests/infisical/
base/
cluster-secret-store.yaml — Plantilla con placeholders
secrets-stripe/ — Claves de procesamiento de pagos
secrets-ai/ — Claves de API de LLM
overlays/
prod/kustomization.yaml — Parchea nombre del store + slug de entorno
staging/kustomization.yaml
La base define una plantilla de ClusterSecretStore. Cada overlay la parchea con el proyecto y entorno de Infisical correctos. Así, producción lee del entorno prod de Infisical y staging lee de staging — misma estructura, credenciales distintas.
Capa 2: SOPS/age (el candado de los ficheros)
Hay ficheros con secretos que tienen que existir en el repositorio Git. Por ejemplo, Talos Linux necesita los certificados del clúster y los tokens de arranque para generar las configuraciones de máquina. Estos viven en talsecret.sops.yaml junto a talconfig.yaml.
SOPS cifra los valores de un fichero YAML dejando las claves legibles. Combinado con age (una herramienta de cifrado), genera ficheros que se pueden commitear sin riesgo:
# Lo que vive en Git (cifrado)
cluster:
id: ENC[AES256_GCM,data:QqUK9Xr6cWv0ed9F...,tag:tnMuAX...,type:str]
secret: ENC[AES256_GCM,data:ncoTvU2yA5He7n2r...,tag:o5SrlE...,type:str]
Se ve la estructura (cluster.id, cluster.secret) pero no los valores. Descifrar requiere la clave privada de age — que está almacenada en Infisical, nunca en Git.
El fichero .sops.yaml en la raíz del repo le indica a SOPS qué clave pública usar:
Infisical proporciona la clave privada de age como variable de entorno. SOPS la usa para descifrar los ficheros. La salida descifrada va a clusterconfig/ (gitignored, nunca se commitea).
Qué hay cifrado en Git
Fichero
Contenido
talsecret.sops.yaml
Certificados del clúster Talos, tokens de etcd
inline-secrets.sops.yaml
Secrets K8s de arranque (credenciales ESO, auth Git de ArgoCD)
secrets.env
Secretos de servicios Docker (CF_API_TOKEN de Caddy, etc.)
Todo lo demás se queda en Infisical y nunca toca Git.
Capa 3: el arranque del huevo y la gallina
El rompecabezas: ESO necesita credenciales para conectarse a Infisical. Pero esas credenciales son un Secret de Kubernetes. Y ESO es precisamente lo que crea Secrets de Kubernetes desde Infisical. ¿De dónde salen entonces las credenciales de ESO?
La respuesta: inline manifests de Talos. El fichero inline-secrets.sops.yaml contiene manifiestos de Secret de Kubernetes cifrados con SOPS. Cuando Talos arranca el plano de control, aplica estos manifiestos directamente — antes de que ArgoCD o ESO siquiera arranquen. Así se rompe la dependencia circular:
Loading diagram...
Estos secretos de arranque son los únicos gestionados vía SOPS. A partir de ahí, todo es automático a través de ESO.
Cómo encajan las tres capas
Loading diagram...
Infisical es la fuente única de verdad. ptolomeo hace de puente entre Infisical y los contenedores Docker (variables de entorno). ESO hace de puente entre Infisical y los pods de Kubernetes (Secrets nativos). Y SOPS/age cubre el caso especial de ficheros que tienen que existir en Git.
Estrategia de backup
Todos los datos del homelab se respaldan en un único lugar: MinIO en spinoza (10.1.0.11). La herramienta de backup es Restic — un programa de backup cifrado y deduplicado que soporta S3.
Hosts Docker: tolstoi
Todos los VPS y VMs corren un servicio llamado tolstoi — un wrapper de Restic que se ejecuta a diario a las 3:00 de la mañana. Respalda volúmenes Docker a MinIO a través de la pasarela Tailscale (cervantes):
Cada despliegue extiende esta base con sus propios volúmenes y bucket S3:
Host
Bucket
Qué se respalda
von-braun
von-braun-restic
Datos de Caddy, BD de CrowdSec
escohotado
escohotado-restic
PostgreSQL, Ghost, Typesense
unamuno
unamuno-restic
Foros, PostgreSQL
Kubernetes: K8up
En los clústeres Kubernetes, K8up sustituye a tolstoi. Es un operador de backup nativo de Kubernetes que descubre y respalda PVCs (Persistent Volume Claims) automáticamente. La programación se define como un recurso de Kubernetes:
apiVersion: k8up.io/v1
kind: Schedule
metadata:
name: backup-schedule
namespace: turing
spec:
backend:
s3:
endpoint: http://minio-atenas.data.svc.cluster.local:9000
bucket: escipion-restic
backup:
schedule: '30 2 * * *' # 2:30 AM a diario
prune:
schedule: '0 4 * * 0' # Domingos a las 4 AM
retention:
keepDaily: 7
keepWeekly: 4
keepMonthly: 6
check:
schedule: '0 5 * * 0' # Domingos a las 5 AM
Tres operaciones automatizadas: backup diario a las 2:30, que hace snapshot de todos los PVCs del namespace; prune semanal los domingos, que elimina snapshots antiguos según la política de retención; y check semanal tras el prune, que verifica la integridad del backup.
K8up se configura por namespace. En escipion hay programaciones separadas para turing (Infisical), gauss (Harbor) y traefik. Cada uno respalda a su propio prefijo en el bucket.
Todo converge en spinoza
Loading diagram...
Los hosts Docker llegan a MinIO a través de la pasarela Tailscale cervantes. escipion y alejandro llegan por el mesh de Tailscale (Roma a Atenas).
Domótica
El homelab no es solo servidores — también controla la casa. Dos servicios corren en la VM aristoteles de la red Atenas (marco-aurelio).
rothbard: Zigbee2MQTT
Zigbee2MQTT hace de puente entre dispositivos Zigbee del hogar (luces, sensores, interruptores) y MQTT, un protocolo de mensajería ligero. Corre junto a un broker MQTT Mosquitto:
El coordinador Zigbee (un dongle USB) habla con los dispositivos directamente — sin ningún servicio en la nube de por medio. Zigbee2MQTT traduce los mensajes de los dispositivos a topics MQTT, dejándolos disponibles para cualquier sistema de automatización.
mises: Homebridge
Homebridge expone dispositivos no-HomeKit a Apple Home. Corre en modo de red host para gestionar el descubrimiento mDNS:
Homebridge recoge los dispositivos publicados en MQTT por Zigbee2MQTT y los expone como accesorios HomeKit. Un "Oye Siri, apaga las luces del salón" acaba provocando un mensaje MQTT que pasa de Homebridge a Zigbee2MQTT, de ahí a la radio Zigbee, y de la radio a la bombilla.
Ambos servicios son accesibles a través del reverse proxy Caddy local (trajano) en rothbard.zetesis.localhost y mises.zetesis.localhost.
Recuperación ante desastres
Si todo se va al traste, hacen falta exactamente seis valores almacenados fuera de la infraestructura para reconstruir:
Secreto
Para qué
Clave privada age
Descifrar los ficheros SOPS del repo
Usuario del almacén de copias
Acceder al backup de Infisical en MinIO
Contraseña del almacén de copias
Acceder al backup de Infisical en MinIO
Contraseña de cifrado de las copias
Descifrar el backup de Restic
Clave de cifrado del gestor de secretos
Arrancar Infisical desde el backup
Secreto de arranque del gestor de secretos
Arrancar Infisical desde el backup
Con estos seis valores y un clon del repositorio Git, el camino de reconstrucción es:
Descifrar los ficheros SOPS con la clave age
Arrancar el primer nodo Talos con talhelper genconfig + talosctl apply-config
Bootstrap de ArgoCD con kubectl apply -f bootstrap.yaml
Restaurar Infisical desde el backup de MinIO usando las claves de Restic y cifrado
Esperar — ESO conecta con Infisical, los secretos se propagan, los servicios arrancan
Una vez que Infisical está arriba, el resto es automático. ESO sincroniza secretos, ArgoCD despliega aplicaciones, ptolomeo tira en los hosts Docker. La reconstrucción completa está documentada en el FIRST_STEPS.md del repo.
Escenarios de pérdida
Qué se pierde
Impacto
Recuperación
Solo la clave age
No se pueden descifrar los ficheros SOPS
Obtenerla de Infisical
Solo Infisical
No se pueden desplegar servicios nuevos
Restaurar desde el backup en MinIO
Clave age + Infisical
Todo
Regenerar todos los secretos desde cero
Solo el repo Git
Se pierde la configuración
Re-clonar desde GitHub
Lo esencial: la clave age y las credenciales del backup de Infisical tienen que existir en algún sitio fuera del homelab — un gestor de contraseñas, un papel en una caja fuerte, un USB offline. Sin ellos, se empieza de cero.
GitGuardian: la red de seguridad
Como toda la infraestructura está en Git, hay una capa más: GitGuardian escanea cada push y cada pull request en busca de secretos commiteados por accidente:
Si alguien commitea una contraseña en texto plano por error, GitGuardian la detecta antes de que llegue a la rama principal.
Lo que hemos construido
Hagamos zoom out. A lo largo de esta serie hemos cubierto:
La visión general — Hardware, nombres, qué corre dónde
Redes — WireGuard sitio a sitio, Tailscale en malla, Cloudflare en el borde, reverse proxy Caddy
Kubernetes y GitOps — Talos Linux, App-of-Apps de ArgoCD, ApplicationSets, ptolomeo
Seguridad y operaciones — Tres capas de secretos (Infisical, SOPS, ESO), backups con Restic, domótica
Todo funciona desde un único repositorio Git. Dos sistemas de CD (ArgoCD + ptolomeo) despliegan en Kubernetes y hosts Docker respectivamente. Los secretos fluyen desde Infisical por tres mecanismos distintos según el destino. Todo se respalda a MinIO en spinoza.
¿Está sobredimensionado para un homelab? Seguramente. Pero cada pieza existe porque me topé con un problema real — y la solución me enseñó algo que ahora uso a nivel profesional. Ese es el verdadero valor de un homelab: un terreno de juego donde lo que te juegas es poco, pero las lecciones son de verdad.
Con los secretos resueltos y una respuesta escrita a «¿y si arde todo?», queda ver el sistema funcionando y saber recuperarlo. Eso es lo que viene en los dos últimos posts.