commit 6d709c5a0773436b19af7e374d9a94a2bed63b96 Author: Christophe JEANNEROT Date: Sat Feb 21 12:13:01 2026 +0100 Ajouter debian12-fr.sh diff --git a/debian12-fr.sh b/debian12-fr.sh new file mode 100644 index 0000000..c184561 --- /dev/null +++ b/debian12-fr.sh @@ -0,0 +1,168 @@ +#!/usr/bin/env bash +set -euo pipefail + +# ========================== +# Debian 12 Cloud VM (FR) +# Proxmox VE (qm) +# - Clavier FR (AZERTY) + locale fr_FR.UTF-8 via cloud-init user-data +# ========================== + +# ---- Defaults (tu peux modifier) ---- +VMID="${VMID:-}" # si vide -> auto +NAME="${NAME:-debian12-fr}" +STORAGE="${STORAGE:-local-lvm}" # stockage pour le disque VM +SNIPPET_STORAGE="${SNIPPET_STORAGE:-local}" # stockage qui supporte "snippets" (souvent local) +BRIDGE="${BRIDGE:-vmbr0}" +CORES="${CORES:-2}" +RAM="${RAM:-2048}" # MiB +DISK_SIZE_GB="${DISK_SIZE_GB:-8}"# taille finale du disque (cloud image sera étendue) +START_VM="${START_VM:-yes}" # yes/no + +# ---- Cloud image ---- +DEBIAN_RELEASE="12" +IMG_URL="https://cloud.debian.org/images/cloud/bookworm/latest/debian-${DEBIAN_RELEASE}-genericcloud-amd64.qcow2" +IMG_NAME="debian-${DEBIAN_RELEASE}-genericcloud-amd64.qcow2" + +# ---- Locale/Keyboard ---- +LOCALE="${LOCALE:-fr_FR.UTF-8}" +KB_LAYOUT="${KB_LAYOUT:-fr}" # fr / be / us ... +CONSOLE_KEYMAP="${CONSOLE_KEYMAP:-fr}" # fr / fr-latin9 ... + +# ---- Helpers ---- +die() { echo "ERROR: $*" >&2; exit 1; } + +need_cmd() { + command -v "$1" >/dev/null 2>&1 || die "Commande requise manquante: $1" +} + +get_nextid() { + pvesh get /cluster/nextid +} + +# ---- Checks ---- +need_cmd qm +need_cmd pvesh +need_cmd curl +need_cmd qemu-img + +if [[ "$(id -u)" -ne 0 ]]; then + die "Lance ce script en root (sur le nœud Proxmox)." +fi + +# ---- Determine VMID ---- +if [[ -z "${VMID}" ]]; then + VMID="$(get_nextid)" +fi + +# Prevent overwrite +if qm status "${VMID}" &>/dev/null; then + die "VMID ${VMID} déjà utilisé." +fi + +echo "==> Création VMID=${VMID} NAME=${NAME}" + +# ---- Ensure snippet dir exists ---- +# /var/lib/vz/snippets correspond au storage "local" (par défaut). Si tu utilises un autre storage pour snippets, +# adapte SNIPPET_STORAGE et/ou le path. +SNIPPET_DIR="/var/lib/vz/snippets" +mkdir -p "${SNIPPET_DIR}" + +USERDATA_FILE="${SNIPPET_DIR}/${VMID}-user-data.yaml" + +cat > "${USERDATA_FILE}" < /etc/default/keyboard + - printf "KEYMAP=\\"${CONSOLE_KEYMAP}\\"\\n" > /etc/default/console-setup + - setupcon -k || true + + - command -v localectl >/dev/null 2>&1 && localectl set-locale LANG=${LOCALE} || true + - command -v localectl >/dev/null 2>&1 && localectl set-keymap ${CONSOLE_KEYMAP} || true +EOF + +echo "==> cloud-init user-data: ${USERDATA_FILE}" + +# ---- Download cloud image (cache in /var/lib/vz/template/iso) ---- +IMG_CACHE_DIR="/var/lib/vz/template/iso" +mkdir -p "${IMG_CACHE_DIR}" +IMG_PATH="${IMG_CACHE_DIR}/${IMG_NAME}" + +if [[ ! -f "${IMG_PATH}" ]]; then + echo "==> Téléchargement image: ${IMG_URL}" + curl -fL "${IMG_URL}" -o "${IMG_PATH}" +else + echo "==> Image déjà présente: ${IMG_PATH}" +fi + +# ---- Create VM shell ---- +qm create "${VMID}" \ + --name "${NAME}" \ + --memory "${RAM}" \ + --cores "${CORES}" \ + --net0 "virtio,bridge=${BRIDGE}" \ + --scsihw virtio-scsi-pci \ + --agent enabled=1 \ + --serial0 socket \ + --vga serial0 + +# ---- Import disk & attach ---- +echo "==> Import disque sur ${STORAGE}" +qm importdisk "${VMID}" "${IMG_PATH}" "${STORAGE}" + +# The imported disk name differs by storage type; use qm config to find it. +IMPORTED_DISK="$(qm config "${VMID}" | awk -v st="${STORAGE}" ' + $1 ~ /^unused[0-9]+:/ && $2 ~ "^"st":" {print $1; sub(":","",$1); print $2} +' | tail -n 1 | tail -n 1 || true)" + +if [[ -z "${IMPORTED_DISK}" ]]; then + # Fallback: take first unusedX line + IMPORTED_DISK="$(qm config "${VMID}" | awk '$1 ~ /^unused[0-9]+:/ {print $2; exit}' || true)" +fi + +[[ -n "${IMPORTED_DISK}" ]] || die "Impossible de retrouver le disque importé (unusedX)." + +echo "==> Disque importé: ${IMPORTED_DISK}" + +qm set "${VMID}" --scsi0 "${IMPORTED_DISK}" +# remove unused entry +UNUSED_KEY="$(qm config "${VMID}" | awk '$1 ~ /^unused[0-9]+:/ {print $1}' | head -n 1 | tr -d ':')" +if [[ -n "${UNUSED_KEY}" ]]; then + qm set "${VMID}" --delete "${UNUSED_KEY}" >/dev/null || true +fi + +# ---- Cloud-init drive + custom user-data ---- +qm set "${VMID}" --ide2 "${STORAGE}:cloudinit" +qm set "${VMID}" --boot order=scsi0 + +# Resize disk to target +echo "==> Resize disque à ${DISK_SIZE_GB}G" +qm resize "${VMID}" scsi0 "${DISK_SIZE_GB}G" + +# Attach cicustom user-data +echo "==> Attache user-data via cicustom (storage snippets: ${SNIPPET_STORAGE})" +qm set "${VMID}" --cicustom "user=${SNIPPET_STORAGE}:snippets/${VMID}-user-data.yaml" + +# Optional: DHCP on cloud image (default). You can pin IP via --ipconfig0 if needed. + +echo "==> VM créée. Cloud-init appliquera locale/clavier FR au premier boot." + +if [[ "${START_VM}" == "yes" ]]; then + echo "==> Démarrage VM" + qm start "${VMID}" +fi + +echo "✅ Terminé. VMID=${VMID}" \ No newline at end of file