Problema
Mantener un homelab con decenas de servicios (home‑assistant, Plex, Paperless‑ngx, LLMs, etc.) suele colapsar cuando la complejidad supera la capacidad de gestión. Los síntomas típicos son:
- Caídas inesperadas de contenedores que no se reinician automáticamente.
- Pérdida de datos por backups incompletos o inconsistentes.
- Accesos remotos inseguros o imposibles cuando se cambia la red.
- Intervenciones manuales frecuentes para actualizar configuraciones DNS o certificados.
El reto es diseñar una arquitectura que permita añadir o retirar servicios sin romper la disponibilidad, mientras se minimiza el tiempo de operación y la superficie de error.
Causa
Los fallos más recurrentes provienen de tres áreas:
- Orquestación dispersa – Ejecutar Docker Compose directamente en máquinas físicas o VMs sin una capa de gestión centralizada genera configuraciones divergentes y dificulta la replicación.
- Gestión de secretos y certificados – Almacenar credenciales en repositorios Git o en archivos locales expone información sensible y obliga a rotar manualmente los certificados.
- Backups ad‑hoc – Copias de seguridad realizadas por cada aplicación de forma independiente provocan redundancia, falta de consistencia entre bases de datos y volúmenes, y una visión fragmentada del estado del sistema.
En entornos donde el hardware es heterogéneo (racks, mini‑PC, Raspberry Pi) y la red está basada en equipos Ubiquiti, la falta de un esquema unificado de DNS y de túneles seguros agrava los problemas de conectividad.
Solución
Una arquitectura basada en Proxmox VE como hipervisor, LXC para aislar cada rol y Docker Compose dentro de los contenedores ofrece un equilibrio entre ligereza y control. Los componentes clave son:
1. Proxmox como capa única de virtualización
- Usa dos nodos: uno “principal” (Xeon + ECC) y otro “auxiliar” (Dell T20) para distribuir la carga.
- Configura HA a nivel de VM/LXC para que, si un nodo falla, los contenedores se migran automáticamente.
2. LXC + Docker Compose
- Cada LXC ejecuta un único stack Docker, lo que mantiene la separación de procesos y permite versionar la configuración con Git.
- Mantén la imagen base mínima (por ejemplo
debian:bookworm-slim) y agrega solo Docker ydocker-compose.
3. DNS split‑horizon con Pi‑hole
- Un Pi‑hole actúa como resolvedor interno y publica un registro
*.lab.localque apunta a la IP interna de cada LXC. - Configura Cloudflare Tunnel (cloudflared) para exponer solo los servicios que requieren acceso externo y usa un wildcard certificado gestionado por Cloudflare.
4. Acceso remoto seguro
- Despliega un servidor WireGuard en la red de gestión (UDM‑Pro) y permite que todos los dispositivos externos se conecten a través de él.
- Bloquea cualquier acceso directo a puertos públicos; los servicios críticos (Plex, Paperless) solo son accesibles vía la VPN.
5. Backups centralizados con Proxmox Backup Server (PBS)
- Programa backups nocturnos de todos los LXC y VM a un NAS (UNAS Pro) en RAID 6.
- Complementa con restic para copias off‑site a Backblaze B2, cifradas con una clave almacenada en 1Password.
6. Despliegue reproducible con Ansible
- Mantén un repositorio Git que contiene los playbooks de Ansible, los archivos
docker-compose.ymly los templates Jinja2 para los archivos de configuración. - En tiempo de despliegue, Ansible extrae los secretos de 1Password (via
opCLI) y los inyecta en los contenedores, evitando que aparezcan en el código.
7. Observabilidad ligera
- Instala Glance, Beszel y WUD en contenedores dedicados para monitorear recursos, versiones de contenedores y actualizaciones de paquetes.
- Configura alertas a Healthchecks.io para cada job de backup y para los scripts de sincronización de iCloud Photos.
Cuándo aplicar esta solución
Aplica este enfoque cuando:
- Tienes más de 5 servicios críticos que deben estar siempre disponibles.
- La infraestructura incluye hardware mixto (rack, mini‑PC, SBC) y deseas una capa de abstracción única.
- Necesitas una estrategia de backup que cubra tanto máquinas virtuales como datos de aplicaciones.
- Quieres evitar la gestión manual de certificados y secretos.
No es necesario si:
- Solo ejecutas uno o dos contenedores en una única máquina.
- No requieres acceso remoto fuera de la LAN.
- La tolerancia a fallos es mínima y puedes aceptar reinicios manuales.
Código
# Ansible task: crear LXC, instalar Docker y desplegar docker-compose
- name: Crear contenedor LXC en Proxmox
community.general.proxmox:
api_user: "{{ proxmox_user }}"
api_password: "{{ proxmox_pass }}"
api_host: "{{ proxmox_host }}"
node: "{{ proxmox_node }}"
vmid: "{{ lxc_id }}"
hostname: "{{ lxc_name }}"
ostemplate: "local:vztmpl/debian-12-standard_12.0-1_amd64.tar.gz"
storage: "local-lvm"
cores: 2
memory: 2048
swap: 512
netif: "name=eth0,bridge=vmbr0,ip={{ lxc_ip }}/24,gw=192.168.1.1"
state: present
- name: Instalar Docker dentro del LXC
ansible.builtin.shell: |
apt-get update && apt-get install -y docker.io docker-compose
args:
executable: /bin/bash
become: true
delegate_to: "{{ lxc_ip }}"
- name: Copiar docker‑compose.yml al contenedor
ansible.builtin.copy:
src: files/{{ service_name }}/docker-compose.yml
dest: /opt/{{ service_name }}/docker-compose.yml
mode: '0644'
delegate_to: "{{ lxc_ip }}"
- name: Levantar stack Docker
ansible.builtin.shell: |
cd /opt/{{ service_name }} && docker-compose up -d
args:
executable: /bin/bash
become: true
delegate_to: "{{ lxc_ip }}"
Verificación
- Estado de HA – En la UI de Proxmox, verifica que cada LXC tenga el flag “HA” activado y que el nodo secundario muestre la réplica.
- Resolución DNS – Desde una máquina cliente, ejecuta
dig service.lab.localy confirma que la IP devuelta corresponde al contenedor esperado. - Acceso VPN – Conecta un cliente WireGuard y prueba
curl https://plex.lab.local/status. Debería responder sin error de certificado. - Backup – Revisa el log de PBS (
/var/log/pbs/pbs.log) y confirma que el snapshot del LXC aparece en la listapbs-manager list. Ejecuta una restauración de prueba en un contenedor de staging. - Alertas – Abre Healthchecks.io y verifica que los últimos pings de los jobs de backup y de sincronización de iCloud estén marcados como “OK”.
Notas adicionales
- Versionado de imágenes – Usa tags semánticos (
myapp:1.4.2) en losdocker-compose.yml. Evitalatestpara que Ansible pueda detectar cambios y redeployar solo cuando sea necesario. - Rotación de claves – Programa una tarea mensual que genere una nueva clave GPG, la almacene en 1Password y actualice los contenedores mediante Ansible.
- Control de recursos – Limita CPU y memoria en la definición LXC; los contenedores Docker heredarán esas cuotas, evitando que un servicio consuma todo el nodo.
- Pruebas de falla – Simula la caída del nodo principal desconectando la alimentación; verifica que los contenedores migren y que los servicios externos (WireGuard, DNS) sigan respondiendo.
- Documentación viva – Mantén un
README.mden el repositorio de Ansible que describa el flujo de despliegue, los puertos expuestos y los pasos de recuperación.
Con este esquema, el homelab se vuelve predecible, fácil de mantener y capaz de sobrevivir a fallos de hardware sin intervención constante. La clave está en centralizar la orquestación, automatizar los secretos y respaldar todo en una capa de backup coherente.