#!/usr/bin/env bash # Debian 13 (Trixie) VM - Preset AZYLIS + UniFi OS Server (uosserver) # - Bridge par défaut: dhcp # - Cloud-init: activé + DHCP IPv4 (ipconfig0) # - root/root fonctionnel (unlock root sur Debian cloud) # - QEMU guest agent # - Resize disque (qm resize + growpart/resize_rootfs) # - Console noVNC plus confortable: VGA virtio + GRUB 1920x1080 + police 8x16 # - Notes Proxmox + logo AZYLIS # - Installation UniFi OS Server (podman + slirp4netns + installer + service uosserver) set -euo pipefail # ----------------------------- # Defaults (modifiable) # ----------------------------- HN_DEFAULT="azylis-unifios" BRG_DEFAULT="dhcp" CORE_DEFAULT="2" RAM_DEFAULT="2048" # MiB (reco 4G mini pour UOS) DISK_DEFAULT="30G" # ex: 20G, 30G, 50G START_VM_DEFAULT="no" # yes/no ONBOOT_DEFAULT="1" # 0/1 # Root access (LAB / template) CI_USER_DEFAULT="root" CI_PASS_DEFAULT="root" # ⚠️ à changer en prod # Debian 13 cloud image DEBIAN13_URL="https://cloud.debian.org/images/cloud/trixie/latest/debian-13-genericcloud-amd64.qcow2" # UniFi OS Server (linux x64) - DEFAULT demandé UOS_URL_DEFAULT="https://fw-download.ubnt.com/data/unifi-os-server/1856-linux-x64-5.0.6-33f4990f-6c68-4e72-9d9c-477496c22450.6-x64" # Notes/logo (Proxmox description) AZYLIS_SITE="https://www.azylis.net" AZYLIS_LOGO="https://www.azylis.net/favicon.ico" # remplace par une URL directe PNG/SVG si tu as mieux # ----------------------------- # Helpers # ----------------------------- YW=$'\033[33m' GN=$'\033[1;92m' RD=$'\033[01;31m' BL=$'\033[36m' CL=$'\033[m' TAB=" " msg_info(){ echo -e "${TAB}${YW}▶${CL} $*"; } msg_ok(){ echo -e "${TAB}${GN}✔${CL} $*"; } msg_err(){ echo -e "${TAB}${RD}✖${CL} $*" >&2; } need_cmd() { command -v "$1" >/dev/null 2>&1 || { msg_err "Commande manquante: $1"; exit 1; }; } get_valid_nextid() { local try_id try_id=$(pvesh get /cluster/nextid) while true; do if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then try_id=$((try_id + 1)); continue fi if lvs --noheadings -o lv_name 2>/dev/null | grep -qE "(^|[-_])${try_id}($|[-_])"; then try_id=$((try_id + 1)); continue fi break done echo "$try_id" } # ----------------------------- # Pre-flight # ----------------------------- if [[ "$(id -u)" -ne 0 ]]; then msg_err "Lance ce script en root sur le noeud Proxmox." exit 1 fi need_cmd pvesh need_cmd pvesm need_cmd qm need_cmd curl need_cmd awk need_cmd sed need_cmd whiptail # ----------------------------- # UI # ----------------------------- VMID="$(get_valid_nextid)" HN="$HN_DEFAULT" BRG="$BRG_DEFAULT" CORE_COUNT="$CORE_DEFAULT" RAM_SIZE="$RAM_DEFAULT" DISK_SIZE="$DISK_DEFAULT" START_VM="$START_VM_DEFAULT" UOS_URL="$UOS_URL_DEFAULT" if ! whiptail --backtitle "AZYLIS - Proxmox" --title "Debian 13 VM + UniFi OS Server" --yesno \ "Ce script va créer une VM Debian 13 (cloud image) avec presets AZYLIS + UniFi OS Server (uosserver).\n\nContinuer ?" 12 78; then msg_err "Annulé." exit 0 fi HN="$(whiptail --backtitle "AZYLIS - Proxmox" --title "Hostname" --inputbox "Hostname VM:" 8 70 "$HN" 3>&1 1>&2 2>&3 || true)" HN="${HN:-$HN_DEFAULT}" BRG="$(whiptail --backtitle "AZYLIS - Proxmox" --title "Bridge" --inputbox "Bridge Proxmox (nom Linux):" 8 70 "$BRG" 3>&1 1>&2 2>&3 || true)" BRG="${BRG:-$BRG_DEFAULT}" CORE_COUNT="$(whiptail --backtitle "AZYLIS - Proxmox" --title "CPU" --inputbox "vCPU:" 8 70 "$CORE_COUNT" 3>&1 1>&2 2>&3 || true)" CORE_COUNT="${CORE_COUNT:-$CORE_DEFAULT}" RAM_SIZE="$(whiptail --backtitle "AZYLIS - Proxmox" --title "RAM" --inputbox "RAM (MiB) (reco 4096+ pour UOS):" 8 70 "$RAM_SIZE" 3>&1 1>&2 2>&3 || true)" RAM_SIZE="${RAM_SIZE:-$RAM_DEFAULT}" DISK_SIZE="$(whiptail --backtitle "AZYLIS - Proxmox" --title "Disque" --inputbox "Taille disque (ex: 30G):" 8 70 "$DISK_SIZE" 3>&1 1>&2 2>&3 || true)" DISK_SIZE="${DISK_SIZE:-$DISK_DEFAULT}" # UOS URL - pré-remplie avec ta version 5.0.6 UOS_URL="$(whiptail --backtitle "AZYLIS - Proxmox" --title "UniFi OS Server (uosserver)" \ --inputbox "URL DIRECTE installeur Linux x64 (prérempli).\n\nTu peux la laisser telle quelle, ou coller une autre version depuis UI Releases/Download." 14 110 \ "$UOS_URL" 3>&1 1>&2 2>&3 || true)" UOS_URL="${UOS_URL:-$UOS_URL_DEFAULT}" if whiptail --backtitle "AZYLIS - Proxmox" --title "Démarrage" --defaultno --yesno \ "Démarrer la VM automatiquement à la fin ?" 10 70; then START_VM="yes" else START_VM="no" fi # ----------------------------- # Storage selection (images) # ----------------------------- msg_info "Détection des stockages compatibles (content: images)" STORAGE_MENU=() MSG_MAX_LEN=0 while read -r line; do TAG="$(awk '{print $1}' <<<"$line")" TYPE="$(awk '{print $2}' <<<"$line")" ITEM="Type: ${TYPE}" (( ${#ITEM} > MSG_MAX_LEN )) && MSG_MAX_LEN=${#ITEM} STORAGE_MENU+=("$TAG" "$ITEM" "OFF") done < <(pvesm status -content images | awk 'NR>1') if [[ ${#STORAGE_MENU[@]} -lt 3 ]]; then msg_err "Aucun stockage valide détecté (content images)." exit 1 fi if [[ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]]; then STORAGE="${STORAGE_MENU[0]}" else STORAGE="$(whiptail --backtitle "AZYLIS - Proxmox" --title "Storage" --radiolist \ "Choisis le stockage pour la VM:" 16 $((MSG_MAX_LEN + 30)) 6 \ "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)" fi msg_ok "Storage: ${BL}${STORAGE}${CL}" msg_ok "VMID: ${BL}${VMID}${CL} | Hostname: ${BL}${HN}${CL} | Bridge: ${BL}${BRG}${CL}" # ----------------------------- # Download image # ----------------------------- TMPDIR="$(mktemp -d)" cleanup() { rm -rf "$TMPDIR" >/dev/null 2>&1 || true; } trap cleanup EXIT cd "$TMPDIR" FILE="$(basename "$DEBIAN13_URL")" msg_info "Téléchargement Debian 13 cloud image: $FILE" curl -fL -o "$FILE" "$DEBIAN13_URL" msg_ok "Image téléchargée" # ----------------------------- # Create VM # ----------------------------- msg_info "Création VM" qm create "$VMID" \ -name "$HN" \ -cores "$CORE_COUNT" \ -memory "$RAM_SIZE" \ -ostype l26 \ -scsihw virtio-scsi-pci \ -net0 "virtio,bridge=${BRG}" \ -agent 1 \ -onboot "$ONBOOT_DEFAULT" \ -tablet 0 \ -localtime 1 >/dev/null # noVNC console comfort qm set "$VMID" --vga virtio >/dev/null qm set "$VMID" --bios ovmf >/dev/null qm set "$VMID" --serial0 socket >/dev/null msg_ok "VM créée" # ----------------------------- # Import disk # ----------------------------- msg_info "Import disque dans ${STORAGE}" IMPORT_LOG="$(qm importdisk "$VMID" "$FILE" "$STORAGE" 2>&1 || true)" IMPORT_DISK="$(awk -F"'" '/Successfully imported disk as/ {print $2}' <<<"$IMPORT_LOG" | tail -n1)" if [[ -z "${IMPORT_DISK:-}" ]]; then IMPORT_DISK="${STORAGE}:vm-${VMID}-disk-0" fi qm set "$VMID" \ --scsi0 "${IMPORT_DISK},discard=on,ssd=1" \ --scsi1 "${STORAGE}:cloudinit" \ --boot order=scsi0 >/dev/null # Resize disk on Proxmox side msg_info "Resize disque virtuel à ${DISK_SIZE}" qm resize "$VMID" scsi0 "$DISK_SIZE" >/dev/null msg_ok "Resize Proxmox OK" # Cloud-init network: DHCP IPv4 (affiché dans UI) qm set "$VMID" --ipconfig0 ip=dhcp >/dev/null # Cloud-init user/password (Proxmox fields) qm set "$VMID" --ciuser "$CI_USER_DEFAULT" --cipassword "$CI_PASS_DEFAULT" >/dev/null # ----------------------------- # Cloud-init user-data (FR + guest agent + grow root + 1080p + UOS Server) # ----------------------------- SNIPPET_DIR="/var/lib/vz/snippets" mkdir -p "$SNIPPET_DIR" USERDATA_FILE="${SNIPPET_DIR}/${VMID}-user-data.yaml" msg_info "Génération cloud-init user-data: ${USERDATA_FILE}" cat > "$USERDATA_FILE" < on force un root/root utilisable (LAB) disable_root: false ssh_pwauth: true chpasswd: expire: false list: | root:${CI_PASS_DEFAULT} packages: - qemu-guest-agent - cloud-guest-utils - locales - kbd - console-setup - keyboard-configuration - curl - ca-certificates - podman - slirp4netns - expect locale: fr_FR.UTF-8 write_files: # Console keymap FR + police petite - path: /etc/default/console-setup content: | ACTIVE_CONSOLES="/dev/tty[1-6]" CHARMAP="UTF-8" CODESET="Lat15" FONTFACE="Fixed" FONTSIZE="8x16" KEYMAP="fr" - path: /etc/default/keyboard content: | XKBLAYOUT="fr" XKBVARIANT="" XKBMODEL="pc105" XKBOPTIONS="" # Force GRUB gfxmode 1080p (utile pour noVNC/VGA) - path: /etc/default/grub.d/99-pve-video.cfg content: | GRUB_GFXMODE=1920x1080 GRUB_GFXPAYLOAD_LINUX=keep - path: /root/uos/install.exp permissions: "0755" content: | set timeout -1 spawn ./uos-installer.bin expect { -re {Proceed\?\s*\(y/N\):} { send "y\r"; exp_continue } eof } runcmd: # Root unlock (Debian cloud) + s'assurer que le mot de passe est bien actif - passwd -u root || true - echo "root:root" | chpasswd # Réseau: petite attente (DHCP) - bash -lc 'for i in {1..30}; do ping -c1 1.1.1.1 >/dev/null 2>&1 && break; sleep 2; done' # Locale FR - sed -i 's/^# *fr_FR.UTF-8 UTF-8/fr_FR.UTF-8 UTF-8/' /etc/locale.gen || true - locale-gen fr_FR.UTF-8 || true - update-locale LANG=fr_FR.UTF-8 || true # Clavier console FR immédiat - loadkeys fr || true - setupcon -k || true # GRUB update (pour 1080p) - update-grub || true # Agent Proxmox - systemctl enable qemu-guest-agent || true - systemctl start qemu-guest-agent || true # --- UniFi OS Server (uosserver) --- - bash -lc 'set -e; mkdir -p /root/uos && cd /root/uos && curl -fL -o uos-installer.bin "https://fw-download.ubnt.com/data/unifi-os-server/1856-linux-x64-5.0.6-33f4990f-6c68-4e72-9d9c-477496c22450.6-x64"' # droits d'exécution - bash -lc 'chmod +x /root/uos/uos-installer.bin /root/uos/install.exp' # lancement install - bash -lc 'cd /root/uos && expect /root/uos/install.exp | tee /root/uos/uos-install.log || true' # service - systemctl enable --now uosserver || true - systemctl status uosserver --no-pager -l || true - systemctl start uosserver EOF # Attach snippet to VM (requires 'local' storage with Snippets enabled) qm set "$VMID" --cicustom "user=local:snippets/${VMID}-user-data.yaml" >/dev/null msg_ok "Cloud-init user-data appliqué" # ----------------------------- # Proxmox Notes (Description) # ----------------------------- CREATED_AT="$(date -Is)" DESCRIPTION=$( cat < AZYLIS

AZYLIS — Debian 13 VM

Infos VM Accès (LAB) Provisioning Accès UniFi OS
Créé le ${CREATED_AT} EOF ) qm set "$VMID" -description "$DESCRIPTION" >/dev/null msg_ok "Notes VM (AZYLIS) ajoutées" # ----------------------------- # Finish # ----------------------------- msg_ok "VM Debian 13 prête: ${BL}${VMID}${CL}" if [[ "$START_VM" == "yes" ]]; then msg_info "Démarrage VM..." qm start "$VMID" >/dev/null msg_ok "VM démarrée." else msg_ok "VM laissée arrêtée (comme demandé)." fi echo echo "Commandes utiles :" echo " Dans la VM: systemctl status uosserver" echo " Dashboard: https://:11443"