#!/usr/bin/env bash set -euo pipefail # ============================================================ # Constructeur de VM UniFi OS pour Proxmox VE (Debian cloud) # # Corrections intégrées : # - UOS_URL réellement utilisée # - uos-installer.bin rendu exécutable # - Script expect avec shebang correct # - Gestion robuste des locales (évite le crash cloud-init) # - Détection automatique du stockage snippets # - Mot de passe root cohérent # - Journalisation claire # ============================================================ # --------- Valeurs par défaut ---------- DEFAULT_VMNAME="unifi-os" DEFAULT_CORES="2" DEFAULT_RAM="4096" # UniFi OS recommande 4 Go mini DEFAULT_DISK_GB="30" DEFAULT_BRIDGE="vmbr0" DEFAULT_VLAN="" DEFAULT_STORAGE="" DEFAULT_CI_USER="root" DEFAULT_CI_PASS="ChangeMe!123" DEFAULT_LOCALE="fr_FR.UTF-8" DEFAULT_TIMEZONE="Europe/Paris" # Image cloud Debian 12 DEBIAN_CLOUD_IMG_URL="https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-genericcloud-amd64.qcow2" # URL installateur UniFi OS (modifiable) DEFAULT_UOS_URL="https://dl.ui.com/unifi/firmware/UDMP/5.0.6/7bc09e3aa41a41e2a7d8c1d5fe3a8d77/udmpro-5.0.6-2d2f2db4f1144a4b9cb9a2f4c1f5d63f.bin" WORKDIR="/var/lib/vz/template/cache" SNIPPET_DIR="/var/lib/vz/snippets" # -------- Fonctions utilitaires -------- die() { echo "ERREUR: $*" >&2; exit 1; } need() { command -v "$1" >/dev/null 2>&1 || die "Dépendance manquante : $1"; } # Détecte un stockage Proxmox supportant les snippets cloud-init detect_snippet_storage() { local s s="$(pvesm status -content snippets 2>/dev/null | awk 'NR>1 && $3=="active"{print $1; exit}')" if [[ -n "${s}" ]]; then echo "${s}" return 0 fi if pvesm status | awk 'NR>1{print $1}' | grep -qx "local"; then echo "local" return 0 fi return 1 } # Détecte un stockage par défaut pour le disque detect_default_storage() { if pvesm status | awk 'NR>1{print $1}' | grep -qx "local-lvm"; then echo "local-lvm" elif pvesm status | awk 'NR>1{print $1}' | grep -qx "local"; then echo "local" else pvesm status | awk 'NR>1 && $3=="active"{print $1; exit}' fi } # -------- Vérifications -------- need qm need pvesm need wget need qemu-img [[ $EUID -eq 0 ]] || die "Exécuter en root sur le noeud Proxmox." mkdir -p "$WORKDIR" "$SNIPPET_DIR" echo "=== Création VM UniFi OS ===" read -rp "VMID (vide = auto) : " VMID [[ -z "${VMID}" ]] && VMID="$(pvesh get /cluster/nextid)" read -rp "Nom VM [${DEFAULT_VMNAME}] : " VMNAME VMNAME="${VMNAME:-$DEFAULT_VMNAME}" read -rp "CPU cores [${DEFAULT_CORES}] : " CORES CORES="${CORES:-$DEFAULT_CORES}" read -rp "RAM MB [${DEFAULT_RAM}] : " RAM RAM="${RAM:-$DEFAULT_RAM}" read -rp "Disque GB [${DEFAULT_DISK_GB}] : " DISK_GB DISK_GB="${DISK_GB:-$DEFAULT_DISK_GB}" read -rp "Bridge [${DEFAULT_BRIDGE}] : " BRIDGE BRIDGE="${BRIDGE:-$DEFAULT_BRIDGE}" read -rp "VLAN (vide = aucun) : " VLAN VLAN="${VLAN:-$DEFAULT_VLAN}" read -rp "Stockage (vide = auto) : " STORAGE STORAGE="${STORAGE:-$(detect_default_storage)}" read -rp "Utilisateur cloud-init [${DEFAULT_CI_USER}] : " CI_USER CI_USER="${CI_USER:-$DEFAULT_CI_USER}" read -rp "Mot de passe : " CI_PASS CI_PASS="${CI_PASS:-$DEFAULT_CI_PASS}" read -rp "Locale [${DEFAULT_LOCALE}] : " LOCALE LOCALE="${LOCALE:-$DEFAULT_LOCALE}" read -rp "Fuseau horaire [${DEFAULT_TIMEZONE}] : " TIMEZONE TIMEZONE="${TIMEZONE:-$DEFAULT_TIMEZONE}" read -rp "URL installateur UniFi OS : " UOS_URL UOS_URL="${UOS_URL:-$DEFAULT_UOS_URL}" # -------- Téléchargement image Debian -------- IMG_NAME="$(basename "${DEBIAN_CLOUD_IMG_URL}")" IMG_PATH="${WORKDIR}/${IMG_NAME}" if [[ ! -f "${IMG_PATH}" ]]; then echo "Téléchargement image Debian..." wget -O "${IMG_PATH}" "${DEBIAN_CLOUD_IMG_URL}" fi # -------- Création VM -------- qm create "$VMID" \ --name "$VMNAME" \ --cores "$CORES" \ --memory "$RAM" \ --net0 "virtio,bridge=${BRIDGE}$( [[ -n "$VLAN" ]] && echo ",tag=${VLAN}" )" \ --scsihw virtio-scsi-single \ --agent enabled=1 \ --serial0 socket \ --vga serial0 \ --ostype l26 qm importdisk "$VMID" "$IMG_PATH" "$STORAGE" VOL="$(qm config "$VMID" | awk '/^unused0:/{print $2}')" qm set "$VMID" --scsi0 "$VOL" qm set "$VMID" --boot order=scsi0 qm set "$VMID" --ide2 "$STORAGE:cloudinit" qm resize "$VMID" scsi0 "${DISK_GB}G" # -------- Cloud-init user-data -------- SNIPSTORE="$(detect_snippet_storage)" || die "Activer les snippets sur un stockage." USERDATA="${SNIPPET_DIR}/${VMID}-user-data.yaml" cat > "$USERDATA" <