
🌐 También en: English · Deutsch · Français
En el último artículo expuse el plan para reconstruir mi homelab como un pequeño centro de datos al estilo empresarial: cinco pilares, ocho hitos, un artículo del blog por hito. El hito 1 es la base sobre la que se apoya todo lo demás — tres máquinas físicas convertidas en un único clúster de Proxmox VE, más el módulo de Terraform que a partir de ahora aprovisiona cada VM encima. Este artículo cubre ambas cosas. Aviso: todo este proyecto está muy en obras. Nada de lo que hay aquí está «terminado» ni es definitivo — como mucho es una beta, y sigue cambiando sobre la marcha. Toma este artículo como una instantánea de cómo estaban las cosas cuando lo escribí, no como un montaje acabado.🎯 Objetivo de este hito
Tenían que cumplirse dos cosas antes de poder tocar Active Directory, GitLab o Kubernetes:- Tres máquinas HP independientes tenían que convertirse en un solo clúster de Proxmox VE, para poder gestionar, migrar y hacer copias de seguridad de las VM desde una única consola.
- Ninguna VM volvería a nacer a base de clics. Cada VM — desde el controlador de dominio hasta el control plane de Kubernetes — se crea con
terraform apply, no con un asistente en la interfaz de Proxmox.
🖥️ Hardware
Tres máquinas HP, deliberadamente distintas — es hardware reciclado, no un conjunto a juego:| Host | RAM | Almacenamiento | IP de gestión |
|---|---|---|---|
| HP1 | 64 GB | SSD de sistema 512 GB + SSD 2 TB | 192.168.10.x |
| HP2 | 32 GB | SSD de sistema 512 GB + SSD 2 TB | 192.168.10.x |
| HP3 | 32 GB | SSD de sistema 512 GB + 3×2 TB (ZFS RAIDZ1) | 192.168.10.x |
💽 Instalando Proxmox VE
Nada especial en la instalación en sí: ISO de Proxmox VE 9.2, grabada en un pendrive con Rufus, un pendrive por máquina, arrancar, instalar y repetir tres veces. Nada de medios virtuales remotos ni de PXE — para tres equipos encima de la misma mesa, un pendrive sigue siendo el camino más rápido desde cero hasta un hipervisor funcionando. Cada nodo recibió durante la instalación una IP estática en la red de gestión192.168.10.x/24 (.30, .40, .50 para HP1–HP3), que a la vez es la red en la que viven el clúster y todas las VM — más sobre ese compromiso más abajo. Un paso posterior a la instalación en los tres: cambiar los repositorios de paquetes. Proxmox viene configurado por defecto con el repositorio Enterprise, que requiere una suscripción de pago para descargar actualizaciones de verdad. Siguiendo los pasos documentados por el propio Proxmox, desactivé el repo Enterprise y apunté cada nodo al repositorio No-Subscription — perfectamente válido para pruebas y uso no productivo, que es justo lo que es un homelab, solo que sin la misma validación que recibe el repo Enterprise:# /etc/apt/sources.list.d/proxmox.sources
Types: deb
URIs: http://download.proxmox.com/debian/pve
Suites: trixie
Components: pve-no-subscription
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpgCon eso listo, la ronda de siempre en los tres nodos antes de hacer cualquier otra cosa:apt-get update
apt-get upgrade
apt-get dist-upgrade🌐 Red
Cada nodo tiene una sola NIC en bridge comovmbr0 (bridge de Linux, STP desactivado), que es a donde se conecta más adelante el network_device de cada VM. Las placas tienen un segundo puerto de red integrado, pero de momento está sin usar — candidato para una red dedicada de almacenamiento o de corosync en el futuro, pero nada que un clúster homelab de 3 nodos necesite el primer día. Esa es también la única simplificación deliberada que merece la pena señalar: corosync (el protocolo de heartbeat y quórum del clúster) va por la misma red que el tráfico de gestión y de las VM, con un único anillo:ring0_addr: HP1 = 192.168.10.x
ring0_addr: HP2 = 192.168.10.x
ring0_addr: HP3 = 192.168.10.xEn un clúster de producción aislarías corosync en su propia VLAN o en sus propias NIC, para que una red de gestión saturada no pueda provocar pérdidas de quórum espurias. Para tres nodos en una red doméstica sin más tráfico compitiendo por el ancho de banda, ese riesgo es aceptable — está en la lista de cosas que revisar si esto alguna vez deja de ser un homelab. Si alguna vez te topas con una pérdida de quórum espuria, RackNotes tiene una guía muy completa sobre la aritmética de votos, los modos de fallo de Corosync, QDevice y las vías de recuperación: Proxmox cluster quorum loss.🔗 Formando el clúster
Flujo estándar conpvecm: crear el clúster en HP1 y luego unir HP2 y HP3. Con tres miembros con voto, el clúster tolera exactamente un nodo caído (2 de 3 votos) antes de perder el quórum — la configuración de HA mínima viable, y precisamente el motivo de optar por tres nodos en lugar de dos. Una consulta al clúster hoy confirma que el camino feliz se mantuvo:$ pvecm status
Cluster name: homelab
Quorate: Yes
Nodes: 3
Nodeid Ip Name
1 192.168.10.x HP1 (local)
2 192.168.10.x HP2
3 192.168.10.x HP3🗄️ Distribución del almacenamiento
Aquí es donde los tres nodos dejan de ser idénticos. El segundo disco de cada nodo (o los discos, en el caso de HP3) está configurado de forma distinta a propósito:- HP1 & HP2: el SSD adicional de 2 TB se añade como simple almacenamiento de tipo directorio (
data/data-hp2) — sin ZFS, sin RAID, solo un sistema de archivos para discos de VM, ISOs y copias de seguridad. Un único SSD, nada con lo que hacer espejo, así que gana la opción más sencilla. - HP3: tres discos de 2 TB forman un pool ZFS en RAIDZ1 (
data-hp3), lo que da algo menos de 4 TB útiles con tolerancia a fallos de un disco. Es el nodo reservado para todo lo que no quiero perder por un único disco muerto — piensa en réplicas de Longhorn o datos de MinIO cuando llegue Kubernetes.
local (sistema de archivos raíz) y local-lvm (LVM-thin en el SSD de sistema) del instalador, que se usan para el propio sistema y como desbordamiento.🧱 De ClickOps a Infrastructure as Code
Con el clúster en marcha, el siguiente paso tentador es pulsar siete veces «Create VM» en la interfaz de Proxmox. Eso es exactamente lo que hice en la versión anterior de este homelab, y cada VM acabó siendo ligeramente distinta — aquí un ajuste de cloud-init olvidado, allá una IP estática tecleada a mano, y seis meses después ni rastro de lo que había hecho realmente. Esta vez no: cada VM de esta reconstrucción se define una sola vez, en Terraform, y es reproducible a partir de un clúster limpio.⚙️ El módulo de Terraform
El módulo vive en 01_terraform/ dentro del repo del proyecto y usa el provider bpg/proxmox. En lugar de montar una ISO de Ubuntu Server e ir haciendo clic por el instalador, cada VM se clona a partir de una imagen cloud de Ubuntu 26.04 y se configura por completo mediante cloud-init — IP estática, DNS, clave SSH, todo — así que no hay ningún paso de instalación interactivo en todo el pipeline:resource "proxmox_download_file" "ubuntu_cloud_image" {
content_type = "iso"
datastore_id = var.image_datastore_id
node_name = var.proxmox_node
url = var.ubuntu_cloud_image_url
file_name = "noble-server-cloudimg-amd64.img"
overwrite = false
}
resource "proxmox_virtual_environment_vm" "vm" {
for_each = local.vms
name = each.key
tags = ["terraform", "rebuild-2026"]
node_name = var.proxmox_node
vm_id = each.value.vmid
disk {
datastore_id = var.vm_datastore_id
file_id = proxmox_download_file.ubuntu_cloud_image.id
interface = "scsi0"
size = each.value.disk_gb
}
initialization {
ip_config {
ipv4 {
address = "${each.value.ip}/${var.network_prefix}"
gateway = var.network_gateway
}
}
user_account {
username = var.vm_username
keys = var.ssh_public_keys
}
}
}Las siete VM — una por rol en este hito — se declaran en un único mapa locals.vms, de modo que añadir una octava VM más adelante es un diff de cinco líneas, no un bloque resource copiado y pegado:| Nombre | Rol | IP | RAM | Disco |
|---|---|---|---|---|
| HP1-dc01 | AD / DNS / CA raíz | 192.168.10.x | 4 GB | 60 GB |
| HP1-gitlab01 | GitLab / Container Registry | 192.168.10.x | 8 GB | 120 GB |
| HP1-seed01 | VM de desarrollo (Ansible, kubectl, herramientas) | 192.168.10.x | 4 GB | 60 GB |
| HP1-vault01 | Gestión de secretos (fase 2) | 192.168.10.x | 2 GB | 40 GB |
| HP1-icinga01 | Monitorización | 192.168.10.x | 4 GB | 60 GB |
| HP1-k8s-cp01 | Control plane de RKE2 | 192.168.10.x | 8 GB | 80 GB |
| HP1-k8s-cp02 | Control plane de RKE2 | 192.168.10.x | 8 GB | 80 GB |
100 + <last IP octet> (131–137) — Proxmox exige ID ≥ 100, y así el ID y la dirección se relacionan de un vistazo, sin una tabla de consulta aparte.▶️ El despliegue
Todo el despliegue son tres comandos, una vez que tienes a mano un token de la API de Proxmox y una clave SSH:cp terraform.tfvars.example terraform.tfvars
# edit terraform.tfvars: API URL, API token, node name, SSH key
terraform init
terraform plan
terraform applyUn par de minutos después, las siete VM existen, arrancan y responden en sus IP asignadas — y Terraform te dice exactamente cuál es cuál:Outputs:
vm_ids = {
"HP1-dc01" = 131
"HP1-gitlab01" = 132
"HP1-icinga01" = 135
"HP1-k8s-cp01" = 136
"HP1-k8s-cp02" = 137
"HP1-seed01" = 133
"HP1-vault01" = 134
}
vm_ips = {
"HP1-dc01" = "192.168.10.x"
"HP1-gitlab01" = "192.168.10.x"
...
}🧩 Algunas cosas que conviene destacar
- Imagen cloud, no ISO. La ISO de Ubuntu que hay en el almacenamiento local de HP1 no la usa este módulo a propósito — clonar una imagen cloud y configurarla con cloud-init es más rápido y totalmente desatendido. La ISO solo sigue ahí para la rara instalación manual.
ignore_changesen elfile_iddel disco. Sin esto, Terraform quiere volver a importar la imagen base en cada plan, ya que el ID del archivo descargado no está pensado para reconciliarse tras el clonado inicial.- Los secretos nunca salen del repo interno.
terraform.tfvarscontiene el token de API y la clave SSH reales y está en el gitignore; además del gitignore, un hook pre-push impide activamente que llegue jamás al mirror público de GitHub de este proyecto. - El state es local, y no pasa nada. Un operador, un portátil que ejecuta
apply— un backend remoto resolvería un problema que todavía no tengo.
⚠️ Todo este proyecto — incluido el código de Terraform que se muestra más abajo — está permanentemente en obras. Funciona, hace lo que dice, pero sigue siendo una beta y se rehace constantemente. No des nada de esto por terminado ni estable.
📊 El punto ciego del ballooning en Windows
HP1-dc01 se aprovisiona con este módulo como cualquier otra VM, pero no sigue siendo Ubuntu mucho tiempo — justo después se convierte a Windows Server, que es lo que necesita Active Directory. En ese momento, su gráfica de RAM en el resumen de Proxmox se quedó plana en el 100 % de los 4 GB asignados, por muy ociosa que estuviera la VM en realidad. La causa: Proxmox no mide directamente el uso de memoria del invitado. Lo lee a través del dispositivo balloon virtual de QEMU, que solo informa de cifras reales si dentro del invitado hay un driver que lo alimente. En las VM Linux de este clúster viene incluido con qemu-guest-agent — ya tratado arriba en el arreglo del guest agent. Windows Server no trae nada equivalente de serie, así que sin software adicional el dispositivo balloon no tiene nada que contar, y Proxmox muestra la VM clavada en su asignación completa. La solución fue una segunda unidad de CD-ROM virtual: montar la ISO de drivers virtio-win e instalar desde ella el driver VirtIO Balloon con el Administrador de dispositivos. Es el mismo paquete de drivers que incluye también el equivalente para Windows del guest agent — una vez instalado, la gráfica del resumen empezó a reflejar la presión de memoria real en lugar de una línea plana pegada al techo. Cómo convertir esta VM en un controlador de dominio de verdad, en el próximo artículo.🔜 Próximos pasos
Con un clúster de 3 nodos con quórum y una forma repetible de levantar VM, el hito 2 empieza a convertirHP1-dc01 en un controlador de dominio de verdad: Active Directory, DNS y la CA raíz offline en la que acabará confiando todo lo demás de este homelab. Eso, en el próximo artículo. 




