Problema
En muchos homelabs la creación de un nuevo servicio implica una cadena de pasos repetitivos: crear el contenedor o la VM en Proxmox, asignar una IP, registrar el nombre en el DNS interno, exponer el puerto mediante Nginx Proxy Manager (NPM), actualizar un inventario en Git y, finalmente, añadir la aplicación a un dashboard como Homarr. Cada ciclo requiere cambiar entre la UI de Proxmox, la consola del DNS, la interfaz de NPM y el repositorio de configuración. Cuando el proceso se repite cientos de veces, el tiempo invertido y la probabilidad de errores humanos se disparan. El patrón es claro: la orquestación manual de recursos dispersos genera fricción y errores.
Causa
- Ausencia de una fuente de verdad única – Proxmox contiene la información de la VM, pero el DNS, NPM y el inventario viven en sistemas independientes. Cada herramienta necesita ser actualizada por separado.
- Falta de automatización post‑provisioning – Los scripts de “cloud‑init” o “community scripts” de Proxmox solo cubren la fase de arranque; no hay un disparador que informe al resto del ecosistema.
- Dependencia de acciones manuales – Los administradores suelen copiar y pegar valores (IP, nombre, puerto) entre pantallas, lo que genera inconsistencias cuando se olvida actualizar alguno de los componentes.
- Gestión de credenciales dispersas – Cada API (Proxmox, Cloudflare, NPM, Git) requiere su propio token; sin una capa que los centralice, la automatización se vuelve compleja.
Solución
Utilizar n8n como motor de orquestación. n8n permite recibir un webhook desde Proxmox al terminar la creación del contenedor/VM y, a partir de ahí, ejecutar una serie de nodos que interactúan con las APIs necesarias. El flujo típico es:
- Webhook de Proxmox – Configura el “post‑creation hook” para que envíe un JSON con
vmid,name,ipytype(LXC/VM). - Detección y normalización – Un nodo “Set” extrae los campos relevantes y los convierte en variables de entorno para los siguientes pasos.
- Creación del registro DNS – Usa la API de tu proveedor (ej. Cloudflare) para crear o actualizar un A‑record con la IP asignada.
- Configuración de Nginx Proxy Manager – Llama a la API de NPM para crear un “Proxy Host”, habilitar SSL automático y apuntar al puerto interno del contenedor.
- Actualización del inventario en Git – Con el nodo “Git‑Push” modifica
services.yml(o cualquier archivo de inventario) y crea un commit. - Registro en Homarr – Llama a la API de Homarr (o escribe directamente en su JSON de configuración) para añadir un nuevo tile.
- Notificaciones de error – Si cualquiera de los pasos falla, un nodo “HTTP Request” envía un mensaje a ntfy con el detalle del error.
Ventajas de este enfoque
- Fuente de verdad única: Proxmox sigue siendo el origen, pero n8n actúa como “control plane” que replica la información donde sea necesario.
- Idempotencia: Cada nodo verifica la existencia del recurso antes de crear uno nuevo, evitando duplicados.
- Escalabilidad: Añadir un nuevo componente (por ejemplo, un monitor de Prometheus) solo implica insertar otro nodo en el flujo.
- Auditoría: Cada ejecución queda registrada en los logs de n8n, facilitando el diagnóstico.
Cuándo aplicar esta solución
- Frecuencia alta de despliegues: Si creas más de una VM/LXC por semana, la ganancia de tiempo supera el coste de mantener el workflow.
- Entorno heterogéneo: Cuando DNS, NPM, Git y dashboards son herramientas distintas y no comparten un backend común.
- Necesidad de trazabilidad: Si requieres saber quién creó qué y cuándo, los logs de n8n proporcionan esa capa.
No es recomendable si tu infraestructura es estática (menos de 5 despliegues al año) o si ya utilizas una plataforma de gestión de infraestructura como Terraform que cubre todos esos recursos. En esos casos añadir n8n sería una capa innecesaria.
Código
# Ejemplo de llamada a la API de Proxmox para obtener datos del contenedor recién creado
PROXMOX_HOST="proxmox.example.com"
API_TOKEN="PVEAPIToken=USER!TOKENID=xxxxxxxxxxxxxxxxxxxx"
VMID=$1 # recibido vía webhook
curl -s -k -H "Authorization: $API_TOKEN" \
"https://${PROXMOX_HOST}:8006/api2/json/nodes/$(hostname)/lxc/${VMID}/config" \
| jq -r '.data | {name: .hostname, ip: .net0 | capture("ip=([^,]+)").0}'
# Creación de un registro DNS en Cloudflare (requiere CF_API_TOKEN)
CF_ZONE_ID="xxxxxxxxxxxxxxxxxxxx"
CF_API_TOKEN="xxxxxxxxxxxxxxxxxxxx"
NAME=$2 # nombre del host, ej. app.example.local
IP=$3
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/${CF_ZONE_ID}/dns_records" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json" \
--data "{\"type\":\"A\",\"name\":\"${NAME}\",\"content\":\"${IP}\",\"ttl\":120,\"proxied\":false}"
# Añadir Proxy Host en Nginx Proxy Manager
NPM_URL="https://npm.example.com/api"
NPM_TOKEN="xxxxxxxxxxxxxxxxxxxx"
HOST=$2
IP=$3
PORT=80 # puerto interno del contenedor
curl -s -X POST "${NPM_URL}/v1/proxy-hosts" \
-H "Authorization: Bearer ${NPM_TOKEN}" \
-H "Content-Type: application/json" \
--data "{
\"domain_names\": [\"${HOST}\"],
\"forward_host\": \"${IP}\",
\"forward_port\": ${PORT},
\"access_list_id\": null,
\"certificate_id\": null,
\"ssl_forced\": true,
\"http2_support\": true,
\"block_exploits\": true
}"
Verificación
- Proxmox – Confirma que el contenedor/VM aparece en la UI y que su IP coincide con la mostrada en el webhook.
- DNS – Ejecuta
dig @1.1.1.1 app.example.localy verifica que la respuesta sea la IP asignada. - NPM – Accede a
https://npm.example.comy busca el nuevo “Proxy Host”. Comprueba que el certificado SSL está activo y que la página del servicio carga sin errores. - Git – Revisa el último commit en el repositorio de
services.yml; debe contener la entrada del nuevo servicio. - Homarr – Abre el dashboard y verifica que el tile aparece al final de la fila configurada.
- ntfy – Si hubo fallos, revisa el canal configurado; de lo contrario, no debería haber mensajes.
Notas adicionales
- Gestión de tokens: Usa un “Secret Store” (por ejemplo, Vault o el propio gestor de credenciales de n8n) para evitar exponer claves en los nodos.
- Idempotencia en DNS: Cloudflare devuelve un error si el registro ya existe; captura el código
409y actualiza en su lugar con unPUT. - Rate limits: Algunas APIs (Cloudflare, NPM) tienen límites de llamadas por minuto. Si planeas crear varios contenedores simultáneamente, inserta nodos “Delay” entre llamadas.
- Rollback parcial: Si la creación del Proxy Host falla después de crear el registro DNS, considera añadir un nodo “HTTP Request” que elimine el registro DNS para mantener la consistencia.
- Versionado del workflow: Guarda el JSON del flujo de n8n en tu repositorio de configuración; así podrás revertir cambios o replicar el mismo proceso en otro clúster.
Con este patrón, la creación de un nuevo servicio en Proxmox pasa de ser una serie de pasos manuales a una única pulsación de “Crear”. La automatización no solo ahorra tiempo, sino que también garantiza que todos los componentes críticos (DNS, proxy, inventario y dashboard) permanezcan sincronizados.