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:

  1. 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.
  2. 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.
  3. 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 y docker-compose.

3. DNS split‑horizon con Pi‑hole

  • Un Pi‑hole actúa como resolvedor interno y publica un registro *.lab.local que 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.yml y los templates Jinja2 para los archivos de configuración.
  • En tiempo de despliegue, Ansible extrae los secretos de 1Password (via op CLI) 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

  1. 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.
  2. Resolución DNS – Desde una máquina cliente, ejecuta dig service.lab.local y confirma que la IP devuelta corresponde al contenedor esperado.
  3. Acceso VPN – Conecta un cliente WireGuard y prueba curl https://plex.lab.local/status. Debería responder sin error de certificado.
  4. Backup – Revisa el log de PBS (/var/log/pbs/pbs.log) y confirma que el snapshot del LXC aparece en la lista pbs-manager list. Ejecuta una restauración de prueba en un contenedor de staging.
  5. 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 los docker-compose.yml. Evita latest para 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.md en 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.