Máquinas Virtuales y Contenedores

Esta guía describe cómo crear y gestionar VMs de Home Assistant OS en Proxmox VE, incluyendo el script de creación automática y la gestión de red.

Arquitectura de red

Internet (GCP)
       │
    ens4 (IP dinámica GCP)
       │
 Proxmox Host — NAT/MASQUERADE
       ├── vmbr0 (192.168.100.1/24) — red interna Proxmox
       │       │
       │   OpenWRT VM (VMID 200)
       │       ├── eth0 → WAN → 192.168.100.2/24
       │       └── br-lan → LAN → 10.10.10.1/24
       │
       └── vmbr1 (10.10.10.0/24) — red de clientes
               │
          VMs HAOS → IP 10.10.10.<VMID>

Regla de IPs: cada VM recibe la IP 10.10.10.<VMID>. El VMID debe estar entre 1 y 254.

Requisitos previos

Script de creación de VMs HAOS

Este script automatiza la creación de VMs de Home Assistant OS en Proxmox VE. Solicita versión, almacenamiento, VMID y nombre, y crea la VM con configuración óptima.

Instalar el script

cat > /usr/local/bin/HA-vm.sh << 'EOF'
#!/usr/bin/env bash
set -euo pipefail

log()  { echo "[INFO]  $*"; }
err()  { echo "[ERROR] $*" >&2; exit 1; }
warn() { echo "[WARN]  $*"; }

[[ "$EUID" -ne 0 ]] && err "Por favor, ejecuta como root"

for cmd in curl jq wget xz pvesm qm; do
    command -v "$cmd" >/dev/null 2>&1 || err "Dependencia no encontrada: $cmd"
done

# 1. Selección de versión
log "Consultando versiones disponibles de HAOS..."
VERSIONS=$(curl -s https://api.github.com/repos/home-assistant/operating-system/releases \
    | jq -r '.[].tag_name' | head -n 10)

[[ -z "$VERSIONS" ]] && err "No se pudieron obtener versiones."

echo ""
echo "Selecciona la versión de HAOS:"
select VER in $VERSIONS; do
    [[ -n "$VER" ]] && break
    warn "Opción no válida."
done

# 2. Selección de almacenamiento
echo ""
echo "Selecciona el almacenamiento:"
mapfile -t STORAGES < <(pvesm status | awk 'NR>1 {print $1}')
select STORAGE in "${STORAGES[@]}"; do
    [[ -n "$STORAGE" ]] && break
    warn "Opción no válida."
done

# 3. VMID con validación
echo ""
while true; do
    read -rp "VMID (número entre 1 y 254): " VMID
    [[ "$VMID" =~ ^[0-9]+$ ]]             || { warn "VMID debe ser numérico."; continue; }
    [[ "$VMID" -ge 1 && "$VMID" -le 254 ]] || { warn "VMID debe estar entre 1 y 254."; continue; }
    if qm status "$VMID" &>/dev/null; then
        warn "El VMID $VMID ya existe. Elige otro."
    else
        break
    fi
done

read -rp "Nombre de la VM: " NAME
[[ -z "$NAME" ]] && err "El nombre no puede estar vacío."

# 4. Descarga de imagen
IMG_FILE="/tmp/haos_${VER}.qcow2"
IMG_URL="https://github.com/home-assistant/operating-system/releases/download/${VER}/haos_ova-${VER}.qcow2.xz"

trap 'rm -f "${IMG_FILE}.xz" "$IMG_FILE"' EXIT

log "Descargando HAOS ${VER}..."
wget -q --show-progress -O "${IMG_FILE}.xz" "$IMG_URL" \
    || err "Fallo en la descarga."

log "Descomprimiendo imagen..."
xz -d "${IMG_FILE}.xz"

[[ -f "$IMG_FILE" ]] || err "La imagen no se descomprimió correctamente."

# 5. Crear VM
log "Creando VM $VMID ($NAME)..."
qm create "$VMID" \
    --name "$NAME" \
    --memory 2048 \
    --cores 2 \
    --net0 virtio,bridge=vmbr1 \
    --scsihw virtio-scsi-pci \
    --bios ovmf \
    --machine q35 \
    --serial0 socket \
    --vga serial0

# 6. Disco EFI sin Secure Boot
log "Creando disco EFI (Secure Boot desactivado)..."
qm set "$VMID" --efidisk0 "${STORAGE}:4,efitype=4m,pre-enrolled-keys=0"

# 7. Importar disco principal
log "Importando disco HAOS..."
qm importdisk "$VMID" "$IMG_FILE" "$STORAGE"

# 8. Buscar y adjuntar disco importado
DISK_NAME=$(pvesm list "$STORAGE" --vmid "$VMID" \
    | grep "vm-${VMID}-disk-" \
    | grep -v "efidisk" \
    | awk '{print $1}' \
    | cut -d':' -f2)

[[ -z "$DISK_NAME" ]] && err "No se encontró el disco importado."

log "Adjuntando disco: $DISK_NAME"
qm set "$VMID" --scsi0 "${STORAGE}:${DISK_NAME},format=raw,discard=on,ssd=1"

# 9. Configurar arranque
qm set "$VMID" --boot order=scsi0

# 10. Asignar hookscript
HOOKSCRIPT_PATH="/var/lib/vz/snippets/hookscript.sh"
if [[ -f "$HOOKSCRIPT_PATH" ]]; then
    qm set "$VMID" --hookscript local:snippets/hookscript.sh
    log "Hookscript asignado."
else
    warn "Hookscript no encontrado en $HOOKSCRIPT_PATH."
fi

trap - EXIT
rm -f "$IMG_FILE"

echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "  ✅ VM creada correctamente"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "  VMID        : $VMID"
echo "  Nombre      : $NAME"
echo "  Versión HAOS: $VER"
echo "  Storage     : $STORAGE"
echo "  Red         : vmbr1"
echo "  IP asignada : 10.10.10.${VMID}"
echo "  UEFI        : OVMF + q35, Secure Boot OFF"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "  Para arrancar: qm start $VMID"
echo ""
EOF

chmod +x /usr/local/bin/HA-vm.sh

Usar el script

bash /usr/local/bin/HA-vm.sh

El script es interactivo — pidiendo versión, storage, VMID y nombre. Al finalizar la VM está lista para arrancar con qm start <VMID>.

Warning

El hookscript se asigna automáticamente al crear la VM. No hace falta asignarlo manualmente salvo en VMs creadas por otros medios.

Problema conocido — BdsDxe: Access Denied

Si la VM falla al arrancar con BdsDxe: Access Denied, el problema es Secure Boot activo. Solución:

qm set <VMID> --delete efidisk0
qm set <VMID> --efidisk0 <storage>:4,efitype=4m,pre-enrolled-keys=0

Contenedor LXC

Para crear un contenedor Debian desde línea de comandos:

pct create <ID> data:vztmpl/debian-13-standard_13.1-2_amd64.tar.zst \
  --hostname <nombre> \
  --cores 1 \
  --memory 512 \
  --swap 512 \
  --rootfs data:20 \
  --net0 name=eth0,bridge=vmbr0,ip=192.168.100.X/24,gw=192.168.100.1 \
  --net1 name=eth1,bridge=vmbr1,ip=10.10.10.X/24 \
  --nameserver 8.8.8.8 \
  --unprivileged 1 \
  --password <contraseña> \
  --start 1
Note

Usar siempre data como almacenamiento, nunca local o local-lvm.

Problema conocido — SSH en Debian 13

Por defecto Debian 13 no permite login de root por contraseña. Editar /etc/ssh/sshd_config y descomentar o modificar:

PermitRootLogin yes
PasswordAuthentication yes

Reiniciar SSH:

systemctl restart ssh

Ver también: OpenWRT en Proxmox, Configuración de Proxmox