erplibre/script/proxmox/install_proxmox.sh

636 lines
28 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
# © 2026 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
#
# Installe Proxmox VE — https://www.proxmox.com — SUR UNE DEBIAN existante.
#
# Pourquoi sur Debian : Proxmox ne publie aucune image cloud. Son ISO est un
# installateur qui formate le disque, ce qui ne se pilote pas depuis un
# déploiement cloud-init. La voie que l'amont documente lui-même pour ce cas
# est « Install Proxmox VE on Debian » : on part de l'image cloud Debian, on
# ajoute le dépôt pve, et les paquets font le reste. Le résultat est le même
# hyperviseur, avec le noyau Proxmox et l'interface web sur :8006.
#
# Architectures : amd64 et arm64 (arm64 officiel depuis PVE 9 — le Release de
# trixie annonce « amd64 arm64 »). PAS s390x : l'index « binary-s390x » du
# dépôt répond 404, le port n'existe pas.
#
# Réglages, par variables d'environnement :
# PVE_SUITE suite Debian visée (défaut : trixie, = PVE 9)
# PVE_REBOOT à 1, redémarre à la fin (défaut : ne redémarre PAS —
# lancé par SSH, un reboot couperait la session et ferait
# passer une installation réussie pour un échec)
# PVE_KEEP_DEBIAN_KERNEL à 1, garde le noyau Debian à côté du noyau pve
# PVE_OS_RELEASE fichier os-release à lire (défaut : /etc/os-release) ;
# sert à vérifier le script depuis une autre distribution
set -euo pipefail
Red='\033[0;31m'
Green='\033[0;32m'
Yellow='\033[0;33m'
Color_Off='\033[0m'
SUITE="${PVE_SUITE:-trixie}"
KEYRING=/usr/share/keyrings/proxmox-archive-keyring.gpg
SOURCES=/etc/apt/sources.list.d/pve-install-repo.sources
# Somme relevée sur la page amont « Install Proxmox VE on Debian 13 Trixie »,
# et VÉRIFIÉE contre le fichier servi. Elle vaut ceinture ET bretelle : c'est
# la clé qui authentifiera tout le reste, et la télécharger sans la contrôler
# reviendrait à faire confiance au seul transport.
KEY_URL="https://enterprise.proxmox.com/debian/proxmox-archive-keyring-${SUITE}.gpg"
KEY_SHA256_trixie=136673be77aba35dcce385b28737689ad64fd785a797e57897589aed08db6e45
# Ce qui a changé : décide du redémarrage final. Une installation déjà faite ne
# doit pas redémarrer la machine pour rien.
CHANGED=0
say() { echo -e "$@"; }
die() { say "${Red}✗${Color_Off} $*"; exit 1; }
DRY=0
usage() {
cat <<EOF
Installe Proxmox VE sur une Debian existante (amd64, arm64).
--dry-run dit ce qu'il ferait, sans rien changer
--help cette aide
Variables : PVE_SUITE (défaut trixie), PVE_REBOOT, PVE_KEEP_DEBIAN_KERNEL,
PVE_OS_RELEASE
EOF
}
while [ $# -gt 0 ]; do
case "$1" in
--dry-run) DRY=1 ;;
-h | --help) usage; exit 0 ;;
*) die "option inconnue : $1" ;;
esac
shift
done
# Toute action qui MODIFIE la machine passe par ici. En dry-run elle est
# annoncée, pas exécutée : c'est ce qui rend le script vérifiable de bout en
# bout sans hyperviseur ni dépôt à disposition.
run() {
if [ "${DRY}" = "1" ]; then
say " ${Yellow}[dry-run]${Color_Off} $*"
return 0
fi
"$@"
}
# --- 1. Architecture --------------------------------------------------------
case "$(uname -m)" in
x86_64) ARCH=amd64 ;;
aarch64 | arm64) ARCH=arm64 ;;
*)
die "Proxmox VE n'existe pas pour $(uname -m) :" \
"le dépôt ne publie que amd64 et arm64."
;;
esac
# --- 2. Debian, et la bonne suite ------------------------------------------
OS_RELEASE="${PVE_OS_RELEASE:-/etc/os-release}"
[ -r "${OS_RELEASE}" ] || die "${OS_RELEASE} illisible : Debian attendue."
# shellcheck disable=SC1090
. "${OS_RELEASE}"
if [ "${ID:-}" != "debian" ]; then
die "Proxmox VE s'installe sur Debian, pas sur « ${ID:-inconnu} »." \
"\n Redéployer la VM avec --distro proxmox (base Debian ${SUITE})."
fi
CODENAME="${VERSION_CODENAME:-}"
if [ -n "${CODENAME}" ] && [ "${CODENAME}" != "${SUITE}" ]; then
say "${Yellow}⚠${Color_Off} Debian « ${CODENAME} » alors que le dépôt visé" \
"est « ${SUITE} » : PVE_SUITE=${CODENAME} si c'est voulu."
fi
# --- 3. /etc/hosts : le nom d'hôte doit résoudre vers une IP ROUTABLE -------
# Ce n'est pas un détail de confort. Le système de grappe de Proxmox parcourt
# toutes les adresses du nom d'hôte jusqu'à en trouver une qui ne soit pas de
# bouclage ; l'entrée « 127.0.1.1 <nom> » que pose l'image cloud Debian le
# mène droit dans le mur, et pveproxy comme pvecm s'en trouvent mal.
# « hostname --ip-address » est le test que l'amont donne lui-même.
host_ip() {
local ip=""
for ip in \
"$(ip -4 route get 1 2>/dev/null | awk '{print $7; exit}')" \
"$(hostname -I 2>/dev/null | awk '{print $1}')" \
"$(ip -4 -o addr show scope global 2>/dev/null \
| awk '{split($4, a, "/"); print a[1]; exit}')"
do
case "$ip" in
127.*) continue ;;
[0-9]*.[0-9]*.[0-9]*.[0-9]*) echo "$ip"; return 0 ;;
esac
done
return 1
}
[FIX] proxmox : pmxcfs sans adresse routable, et le stockage vide Rapporté sur un Proxmox imbriqué. « pvesm » ne parle qu'à travers /etc/pve, monté par pmxcfs ; pmxcfs à terre, la commande répond « Connection refused », la liste est vide, et l'écran s'arrête sur « aucun stockage » — trois étages au-dessus du défaut. pmxcfs ne démarrait pas parce que le nom d'hôte ne résolvait que vers 127.0.1.1, et il cherche une adresse ROUTABLE. L'installation corrige bien /etc/hosts, mais l'image cloud règle « manage_etc_hosts: True » : cloud-init le réécrit à CHAQUE démarrage. C'est le redémarrage désormais automatique qui l'a révélé — l'installation corrigeait, le reboot amorçait le bon noyau, et cloud-init défaisait la correction dans le même mouvement. Un fichier de surcharge le gèle. Deuxième geste manquant : systemd marque pve-cluster « failed » après cinq essais rapprochés et n'y revient JAMAIS seul. Corriger /etc/hosts ne suffisait donc pas ; l'installation relance l'unité et CONSTATE le montage plutôt que de le supposer. Et l'écran nomme maintenant la cause quand il n'a pas de stockage, plutôt que de laisser chercher. Un détail qui aurait fait un faux diagnostic : la sonde de montage n'interroge pas storage.cfg. Ce fichier N'EXISTE PAS sur une installation neuve — Proxmox se contente alors de ses stockages par défaut, et « local » répond parfaitement. Vérifié sur l'hôte : /etc/pve monté, storage.cfg absent, « pvesm status » rendant local avec 25 Go libres. C'est « .version », fichier virtuel de pmxcfs, qui fait foi. --- EN --- Reported on a nested Proxmox. "pvesm" only speaks through /etc/pve, mounted by pmxcfs; with pmxcfs down the command answers "Connection refused", the list is empty, and the screen stops at "no storage" — three floors above the defect. pmxcfs would not start because the hostname resolved only to 127.0.1.1, and it needs a ROUTABLE address. The installer does fix /etc/hosts, but the cloud image sets "manage_etc_hosts: True": cloud-init rewrites it at EVERY boot. The now-automatic reboot is what revealed it — the install fixed it, the reboot booted the right kernel, and cloud-init undid the fix in the same motion. An override file freezes it. Second missing step: systemd marks pve-cluster "failed" after five rapid attempts and never returns to it on its own. Fixing /etc/hosts was therefore not enough; the installer restarts the unit and VERIFIES the mount rather than assuming it. And the screen now names the cause when it has no storage, instead of leaving you to hunt. One detail that would have made a false diagnosis: the mount probe does not ask for storage.cfg. That file DOES NOT EXIST on a fresh install — Proxmox then uses its default storages, and "local" answers perfectly. Verified on the host: /etc/pve mounted, storage.cfg absent, "pvesm status" returning local with 25 GB free. It is ".version", a pmxcfs virtual file, that tells the truth. Assisted-by: Claude Opus 5 (cherry picked from commit 6212853048ba8154f2833744e45076d70bd33c72)
2026-08-25 04:30:48 -04:00
# Sans ceci, tout ce que fait fix_hosts est ANNULÉ au prochain démarrage.
# L'image cloud Debian règle « manage_etc_hosts: True » : cloud-init réécrit
# alors /etc/hosts depuis son gabarit à chaque boot, et y remet
# « 127.0.1.1 <nom> ». pmxcfs, qui cherche une adresse non-bouclage pour le
# nom d'hôte, ne démarre plus — /etc/pve n'est pas monté, « pvesm » répond
# « Connection refused », et l'écran de déploiement conclut « il manque le
# stockage ». Le vrai défaut est trois étages plus bas.
#
# Vécu, et révélé par le redémarrage désormais automatique : l'installation
# corrigeait /etc/hosts, le reboot amorçait le noyau Proxmox, et cloud-init
# défaisait la correction dans le même mouvement.
#
# Un fichier de surcharge plutôt qu'une édition de cloud.cfg : c'est la voie
# que cloud-init documente, et une mise à jour du paquet ne l'écrase pas.
freeze_cloud_hosts() {
local dossier=/etc/cloud/cloud.cfg.d
local fichier="${dossier}/99-erplibre-hosts.cfg"
[ -d /etc/cloud ] || return 0
[FIX] proxmox : ne pas démarrer le pare-feu depuis l'extérieur Une révision adversariale de la réparation à distance a rendu un constat que ses TROIS lentilles — réseau, systemd, shell — ont trouvé indépendamment : démarrer pve-firewall peut couper le ssh qui répare. Sa configuration vit dans /var/lib/pve-cluster/config.db, donc elle est invisible tant que /etc/pve n'est pas monté — c'est-à-dire exactement dans l'état qu'on répare. On appliquerait des règles qu'on ne peut pas lire, sur la seule voie d'accès à la machine. Il n'est pas nécessaire au but : le stockage et le suivi demandent pve-cluster et pvestatd, l'interface web pveproxy. Il repartira au prochain démarrage, quand /etc/pve sera monté à temps. Le retirer de la liste coûte donc rien et supprime le seul geste qui pouvait isoler un hôte. Deux autres constats de la même révision, également réels. Le gel de cloud-init gardait sur l'EXISTENCE du fichier. Or « printf … > » le TRONQUE avant d'écrire : une coupure au mauvais moment laisse zéro octet, et la garde annonce « déjà gelé » pour toujours. cloud-init continue de remettre 127.0.1.1 à chaque démarrage et le défaut redevient invisible — celui-là même que ce code existe pour supprimer. La garde porte maintenant sur le CONTENU. Et les adresses de lien-local passaient pour routables. Mesuré : « hostname --ip-address » peut ne rendre QUE des fe80::, et une APIPA en 169.254 passait le seul test « ne commence pas par 127. ». pmxcfs n'a alors rien d'utilisable, mais le diagnostic concluait l'inverse et renvoyait vers journalctl au lieu de /etc/hosts. Enfin « la sonde n'a pas répondu » n'est plus lu comme « rien n'est monté » : un dépassement de délai rend les mêmes vides, et on affirmait une cause qu'on n'avait pas constatée. --- EN --- An adversarial review of the remote repair produced one finding all THREE of its lenses — network, systemd, shell — reached independently: starting pve-firewall can cut the ssh doing the repair. Its configuration lives in /var/lib/pve-cluster/config.db, so it is invisible while /etc/pve is unmounted — exactly the state being repaired. We would apply rules we cannot read, over the machine's only way in. It is not needed for the goal: storage and monitoring need pve-cluster and pvestatd, the web interface pveproxy. It will come back at the next boot, when /etc/pve mounts in time. Removing it from the list costs nothing and removes the one gesture that could isolate a host. Two more findings from the same review, equally real. The cloud-init freeze guarded on the file's EXISTENCE. But "printf … >" TRUNCATES before writing: an ill-timed cut leaves zero bytes, and the guard then reports "already frozen" forever. cloud-init keeps putting 127.0.1.1 back at every boot and the defect becomes invisible again — the very one this code exists to remove. The guard now looks at the CONTENT. And link-local addresses counted as routable. Measured: "hostname --ip-address" can return ONLY fe80:: entries, and an APIPA 169.254 passed the lone "does not start with 127." test. pmxcfs then has nothing usable, yet the diagnosis concluded the opposite and pointed at journalctl instead of /etc/hosts. Finally "the probe did not answer" is no longer read as "nothing is mounted": a timeout returns the same emptiness, and we were asserting a cause we had not measured. Assisted-by: Claude Opus 5 (cherry picked from commit fa9fb729d82e8d1a8e4fb549cc8061c7281b5dcb)
2026-08-25 06:31:30 -04:00
# Sur le CONTENU et non sur l'existence : « printf … > fichier » TRONQUE
# avant d'écrire. Une coupure au mauvais moment laisse un fichier de zéro
# octet, et une garde à l'existence annonce alors « déjà gelé » pour
# toujours — cloud-init continue de remettre 127.0.1.1 à chaque
# démarrage, et le défaut redevient invisible. Une redirection est de
# toute façon idempotente : il n'y a rien à protéger d'autre.
if grep -qE "^[[:space:]]*manage_etc_hosts:[[:space:]]*false" \
"${fichier}" 2>/dev/null; then
[FIX] proxmox : pmxcfs sans adresse routable, et le stockage vide Rapporté sur un Proxmox imbriqué. « pvesm » ne parle qu'à travers /etc/pve, monté par pmxcfs ; pmxcfs à terre, la commande répond « Connection refused », la liste est vide, et l'écran s'arrête sur « aucun stockage » — trois étages au-dessus du défaut. pmxcfs ne démarrait pas parce que le nom d'hôte ne résolvait que vers 127.0.1.1, et il cherche une adresse ROUTABLE. L'installation corrige bien /etc/hosts, mais l'image cloud règle « manage_etc_hosts: True » : cloud-init le réécrit à CHAQUE démarrage. C'est le redémarrage désormais automatique qui l'a révélé — l'installation corrigeait, le reboot amorçait le bon noyau, et cloud-init défaisait la correction dans le même mouvement. Un fichier de surcharge le gèle. Deuxième geste manquant : systemd marque pve-cluster « failed » après cinq essais rapprochés et n'y revient JAMAIS seul. Corriger /etc/hosts ne suffisait donc pas ; l'installation relance l'unité et CONSTATE le montage plutôt que de le supposer. Et l'écran nomme maintenant la cause quand il n'a pas de stockage, plutôt que de laisser chercher. Un détail qui aurait fait un faux diagnostic : la sonde de montage n'interroge pas storage.cfg. Ce fichier N'EXISTE PAS sur une installation neuve — Proxmox se contente alors de ses stockages par défaut, et « local » répond parfaitement. Vérifié sur l'hôte : /etc/pve monté, storage.cfg absent, « pvesm status » rendant local avec 25 Go libres. C'est « .version », fichier virtuel de pmxcfs, qui fait foi. --- EN --- Reported on a nested Proxmox. "pvesm" only speaks through /etc/pve, mounted by pmxcfs; with pmxcfs down the command answers "Connection refused", the list is empty, and the screen stops at "no storage" — three floors above the defect. pmxcfs would not start because the hostname resolved only to 127.0.1.1, and it needs a ROUTABLE address. The installer does fix /etc/hosts, but the cloud image sets "manage_etc_hosts: True": cloud-init rewrites it at EVERY boot. The now-automatic reboot is what revealed it — the install fixed it, the reboot booted the right kernel, and cloud-init undid the fix in the same motion. An override file freezes it. Second missing step: systemd marks pve-cluster "failed" after five rapid attempts and never returns to it on its own. Fixing /etc/hosts was therefore not enough; the installer restarts the unit and VERIFIES the mount rather than assuming it. And the screen now names the cause when it has no storage, instead of leaving you to hunt. One detail that would have made a false diagnosis: the mount probe does not ask for storage.cfg. That file DOES NOT EXIST on a fresh install — Proxmox then uses its default storages, and "local" answers perfectly. Verified on the host: /etc/pve mounted, storage.cfg absent, "pvesm status" returning local with 25 GB free. It is ".version", a pmxcfs virtual file, that tells the truth. Assisted-by: Claude Opus 5 (cherry picked from commit 6212853048ba8154f2833744e45076d70bd33c72)
2026-08-25 04:30:48 -04:00
say " cloud-init ne touche déjà plus à /etc/hosts"
return 0
fi
say " cloud-init : gel de /etc/hosts (${fichier})"
if [ "${DRY}" = "1" ]; then
say " ${Yellow}[dry-run]${Color_Off} manage_etc_hosts: false" \
"> ${fichier}"
return 0
fi
sudo mkdir -p "${dossier}"
printf '%s\n' \
"# Posé par ERPLibre : Proxmox exige que le nom d'hôte résolve vers" \
"# une adresse ROUTABLE. cloud-init y remettait 127.0.1.1 à chaque" \
"# démarrage, et pmxcfs ne démarrait plus." \
"manage_etc_hosts: false" \
| sudo tee "${fichier}" >/dev/null
CHANGED=1
}
fix_hosts() {
local ip fqdn short
ip="$(host_ip)" || die "aucune adresse IPv4 routable : réseau absent ?"
[FIX] proxmox : pmxcfs sans adresse routable, et le stockage vide Rapporté sur un Proxmox imbriqué. « pvesm » ne parle qu'à travers /etc/pve, monté par pmxcfs ; pmxcfs à terre, la commande répond « Connection refused », la liste est vide, et l'écran s'arrête sur « aucun stockage » — trois étages au-dessus du défaut. pmxcfs ne démarrait pas parce que le nom d'hôte ne résolvait que vers 127.0.1.1, et il cherche une adresse ROUTABLE. L'installation corrige bien /etc/hosts, mais l'image cloud règle « manage_etc_hosts: True » : cloud-init le réécrit à CHAQUE démarrage. C'est le redémarrage désormais automatique qui l'a révélé — l'installation corrigeait, le reboot amorçait le bon noyau, et cloud-init défaisait la correction dans le même mouvement. Un fichier de surcharge le gèle. Deuxième geste manquant : systemd marque pve-cluster « failed » après cinq essais rapprochés et n'y revient JAMAIS seul. Corriger /etc/hosts ne suffisait donc pas ; l'installation relance l'unité et CONSTATE le montage plutôt que de le supposer. Et l'écran nomme maintenant la cause quand il n'a pas de stockage, plutôt que de laisser chercher. Un détail qui aurait fait un faux diagnostic : la sonde de montage n'interroge pas storage.cfg. Ce fichier N'EXISTE PAS sur une installation neuve — Proxmox se contente alors de ses stockages par défaut, et « local » répond parfaitement. Vérifié sur l'hôte : /etc/pve monté, storage.cfg absent, « pvesm status » rendant local avec 25 Go libres. C'est « .version », fichier virtuel de pmxcfs, qui fait foi. --- EN --- Reported on a nested Proxmox. "pvesm" only speaks through /etc/pve, mounted by pmxcfs; with pmxcfs down the command answers "Connection refused", the list is empty, and the screen stops at "no storage" — three floors above the defect. pmxcfs would not start because the hostname resolved only to 127.0.1.1, and it needs a ROUTABLE address. The installer does fix /etc/hosts, but the cloud image sets "manage_etc_hosts: True": cloud-init rewrites it at EVERY boot. The now-automatic reboot is what revealed it — the install fixed it, the reboot booted the right kernel, and cloud-init undid the fix in the same motion. An override file freezes it. Second missing step: systemd marks pve-cluster "failed" after five rapid attempts and never returns to it on its own. Fixing /etc/hosts was therefore not enough; the installer restarts the unit and VERIFIES the mount rather than assuming it. And the screen now names the cause when it has no storage, instead of leaving you to hunt. One detail that would have made a false diagnosis: the mount probe does not ask for storage.cfg. That file DOES NOT EXIST on a fresh install — Proxmox then uses its default storages, and "local" answers perfectly. Verified on the host: /etc/pve mounted, storage.cfg absent, "pvesm status" returning local with 25 GB free. It is ".version", a pmxcfs virtual file, that tells the truth. Assisted-by: Claude Opus 5 (cherry picked from commit 6212853048ba8154f2833744e45076d70bd33c72)
2026-08-25 04:30:48 -04:00
freeze_cloud_hosts
short="$(hostname -s)"
fqdn="$(hostname -f 2>/dev/null || echo "${short}")"
[ "${fqdn}" = "${short}" ] && fqdn="${short}.local"
if grep -qE "^[[:space:]]*127\.0\.1\.1[[:space:]]" /etc/hosts; then
say " retrait de l'entrée 127.0.1.1 (bouclage) pour ${short}"
run sudo sed -i -E "/^[[:space:]]*127\.0\.1\.1[[:space:]]/d" \
/etc/hosts
CHANGED=1
fi
if ! grep -qE "^[[:space:]]*${ip//./\\.}[[:space:]]+.*\b${short}\b" \
/etc/hosts; then
say " ${short} -> ${ip} dans /etc/hosts"
if [ "${DRY}" = "1" ]; then
say " ${Yellow}[dry-run]${Color_Off} ${ip} ${fqdn} ${short}" \
">> /etc/hosts"
else
printf '%s\t%s %s\n' "${ip}" "${fqdn}" "${short}" \
| sudo tee -a /etc/hosts >/dev/null
fi
CHANGED=1
fi
# Le test de l'amont, mot pour mot : au moins une adresse non-bouclage.
local vu routables
vu="$(hostname --ip-address 2>/dev/null || true)"
routables="$(printf '%s\n' ${vu} | grep -vE '^(127\.|::1$)' || true)"
[ -n "${routables}" ] || die \
"« hostname --ip-address » rend « ${vu:-rien} » : le nom d'hôte ne" \
"résout toujours pas vers une adresse routable."
say " hostname --ip-address : $(printf '%s ' ${routables})"
[FIX] suivi : relevé Proxmox squelettique, index par nom, état terminal Une cause, deux symptômes. « /cluster/resources » est bâti par pvestatd ; celui-ci arrêté, l'hôte rend quand même une entrée par VM, mais SQUELETTIQUE — ni nom, ni mémoire, ni disque, et « status: unknown ». Le relevé était indexé par NOM : l'entrée disparaissait donc, la VM passait pour absente alors que l'hôte venait de la nommer, et trois tours plus tard 🗑. Comme « effacée » est un état TERMINAL, la ligne comptait pour finie — d'où « 1/1 terminées · 00:09 » sur une installation qui tournait. Le relevé est maintenant indexé par VMID, seul identifiant unique d'un hôte Proxmox, et la correspondance vers les noms se fait là où le manifeste est sous les yeux. Une entrée squelettique reste donc une VM présente, avec ce que l'hôte sait d'elle — sa taille occupée, que « du » donne par VMID. Reste à savoir pourquoi pvestatd était mort. Son journal le dit mot pour mot : « ipcc_send_rec failed: Connection refused » — pve-cluster absent, c'est-à-dire la panne /etc/hosts d'hier. Tous les services de Proxmox avaient échoué ensemble, et systemd n'y revient jamais seul. L'installation relançait le seul pve-cluster ; elle relance désormais l'ensemble, pve-cluster d'abord puisqu'il monte /etc/pve. Vérifié sur l'hôte : pvestatd relancé, et les colonnes passent de « - - - » à « 3.4G/4.0G, 2.3G/25G, 2.2G écrit ». --- EN --- One cause, two symptoms. "/cluster/resources" is built by pvestatd; with it stopped the host still returns one entry per VM, but SKELETAL — no name, no memory, no disk, and "status: unknown". Readings were indexed by NAME, so that entry vanished, the VM looked absent although the host had just named it, and three rounds later 🗑. Since "deleted" is a TERMINAL state the row counted as finished — hence "1/1 done · 00:09" on a running install. Readings are now indexed by VMID, a Proxmox host's only unique identifier, and the mapping to names happens where the manifest is at hand. A skeletal entry therefore stays a present VM, with whatever the host does know about it — its used size, which "du" reports per VMID. Why was pvestatd dead? Its journal says it verbatim: "ipcc_send_rec failed: Connection refused" — no pve-cluster, that is yesterday's /etc/hosts fault. All of Proxmox's services had failed together, and systemd never returns to them on its own. The installer restarted pve-cluster alone; it now restarts the whole set, pve-cluster first since it mounts /etc/pve. Verified on the host: pvestatd restarted, and the columns go from "- - -" to "3.4G/4.0G, 2.3G/25G, 2.2G written". Assisted-by: Claude Opus 5 (cherry picked from commit 3fb85f66842d4b0e9d6ae6446691229b31ef725a)
2026-08-25 05:05:39 -04:00
revive_pve_services
[FIX] proxmox : pmxcfs sans adresse routable, et le stockage vide Rapporté sur un Proxmox imbriqué. « pvesm » ne parle qu'à travers /etc/pve, monté par pmxcfs ; pmxcfs à terre, la commande répond « Connection refused », la liste est vide, et l'écran s'arrête sur « aucun stockage » — trois étages au-dessus du défaut. pmxcfs ne démarrait pas parce que le nom d'hôte ne résolvait que vers 127.0.1.1, et il cherche une adresse ROUTABLE. L'installation corrige bien /etc/hosts, mais l'image cloud règle « manage_etc_hosts: True » : cloud-init le réécrit à CHAQUE démarrage. C'est le redémarrage désormais automatique qui l'a révélé — l'installation corrigeait, le reboot amorçait le bon noyau, et cloud-init défaisait la correction dans le même mouvement. Un fichier de surcharge le gèle. Deuxième geste manquant : systemd marque pve-cluster « failed » après cinq essais rapprochés et n'y revient JAMAIS seul. Corriger /etc/hosts ne suffisait donc pas ; l'installation relance l'unité et CONSTATE le montage plutôt que de le supposer. Et l'écran nomme maintenant la cause quand il n'a pas de stockage, plutôt que de laisser chercher. Un détail qui aurait fait un faux diagnostic : la sonde de montage n'interroge pas storage.cfg. Ce fichier N'EXISTE PAS sur une installation neuve — Proxmox se contente alors de ses stockages par défaut, et « local » répond parfaitement. Vérifié sur l'hôte : /etc/pve monté, storage.cfg absent, « pvesm status » rendant local avec 25 Go libres. C'est « .version », fichier virtuel de pmxcfs, qui fait foi. --- EN --- Reported on a nested Proxmox. "pvesm" only speaks through /etc/pve, mounted by pmxcfs; with pmxcfs down the command answers "Connection refused", the list is empty, and the screen stops at "no storage" — three floors above the defect. pmxcfs would not start because the hostname resolved only to 127.0.1.1, and it needs a ROUTABLE address. The installer does fix /etc/hosts, but the cloud image sets "manage_etc_hosts: True": cloud-init rewrites it at EVERY boot. The now-automatic reboot is what revealed it — the install fixed it, the reboot booted the right kernel, and cloud-init undid the fix in the same motion. An override file freezes it. Second missing step: systemd marks pve-cluster "failed" after five rapid attempts and never returns to it on its own. Fixing /etc/hosts was therefore not enough; the installer restarts the unit and VERIFIES the mount rather than assuming it. And the screen now names the cause when it has no storage, instead of leaving you to hunt. One detail that would have made a false diagnosis: the mount probe does not ask for storage.cfg. That file DOES NOT EXIST on a fresh install — Proxmox then uses its default storages, and "local" answers perfectly. Verified on the host: /etc/pve mounted, storage.cfg absent, "pvesm status" returning local with 25 GB free. It is ".version", a pmxcfs virtual file, that tells the truth. Assisted-by: Claude Opus 5 (cherry picked from commit 6212853048ba8154f2833744e45076d70bd33c72)
2026-08-25 04:30:48 -04:00
}
[FIX] suivi : relevé Proxmox squelettique, index par nom, état terminal Une cause, deux symptômes. « /cluster/resources » est bâti par pvestatd ; celui-ci arrêté, l'hôte rend quand même une entrée par VM, mais SQUELETTIQUE — ni nom, ni mémoire, ni disque, et « status: unknown ». Le relevé était indexé par NOM : l'entrée disparaissait donc, la VM passait pour absente alors que l'hôte venait de la nommer, et trois tours plus tard 🗑. Comme « effacée » est un état TERMINAL, la ligne comptait pour finie — d'où « 1/1 terminées · 00:09 » sur une installation qui tournait. Le relevé est maintenant indexé par VMID, seul identifiant unique d'un hôte Proxmox, et la correspondance vers les noms se fait là où le manifeste est sous les yeux. Une entrée squelettique reste donc une VM présente, avec ce que l'hôte sait d'elle — sa taille occupée, que « du » donne par VMID. Reste à savoir pourquoi pvestatd était mort. Son journal le dit mot pour mot : « ipcc_send_rec failed: Connection refused » — pve-cluster absent, c'est-à-dire la panne /etc/hosts d'hier. Tous les services de Proxmox avaient échoué ensemble, et systemd n'y revient jamais seul. L'installation relançait le seul pve-cluster ; elle relance désormais l'ensemble, pve-cluster d'abord puisqu'il monte /etc/pve. Vérifié sur l'hôte : pvestatd relancé, et les colonnes passent de « - - - » à « 3.4G/4.0G, 2.3G/25G, 2.2G écrit ». --- EN --- One cause, two symptoms. "/cluster/resources" is built by pvestatd; with it stopped the host still returns one entry per VM, but SKELETAL — no name, no memory, no disk, and "status: unknown". Readings were indexed by NAME, so that entry vanished, the VM looked absent although the host had just named it, and three rounds later 🗑. Since "deleted" is a TERMINAL state the row counted as finished — hence "1/1 done · 00:09" on a running install. Readings are now indexed by VMID, a Proxmox host's only unique identifier, and the mapping to names happens where the manifest is at hand. A skeletal entry therefore stays a present VM, with whatever the host does know about it — its used size, which "du" reports per VMID. Why was pvestatd dead? Its journal says it verbatim: "ipcc_send_rec failed: Connection refused" — no pve-cluster, that is yesterday's /etc/hosts fault. All of Proxmox's services had failed together, and systemd never returns to them on its own. The installer restarted pve-cluster alone; it now restarts the whole set, pve-cluster first since it mounts /etc/pve. Verified on the host: pvestatd restarted, and the columns go from "- - -" to "3.4G/4.0G, 2.3G/25G, 2.2G written". Assisted-by: Claude Opus 5 (cherry picked from commit 3fb85f66842d4b0e9d6ae6446691229b31ef725a)
2026-08-25 05:05:39 -04:00
# Les services de Proxmox abandonnent après cinq essais rapprochés : systemd
# marque l'unité « failed » et n'y revient JAMAIS de lui-même — « Start request
# repeated too quickly ». Or ils ont TOUS échoué pendant que /etc/hosts était
# faux. Corriger le fichier ne suffit donc pas.
[FIX] proxmox : pmxcfs sans adresse routable, et le stockage vide Rapporté sur un Proxmox imbriqué. « pvesm » ne parle qu'à travers /etc/pve, monté par pmxcfs ; pmxcfs à terre, la commande répond « Connection refused », la liste est vide, et l'écran s'arrête sur « aucun stockage » — trois étages au-dessus du défaut. pmxcfs ne démarrait pas parce que le nom d'hôte ne résolvait que vers 127.0.1.1, et il cherche une adresse ROUTABLE. L'installation corrige bien /etc/hosts, mais l'image cloud règle « manage_etc_hosts: True » : cloud-init le réécrit à CHAQUE démarrage. C'est le redémarrage désormais automatique qui l'a révélé — l'installation corrigeait, le reboot amorçait le bon noyau, et cloud-init défaisait la correction dans le même mouvement. Un fichier de surcharge le gèle. Deuxième geste manquant : systemd marque pve-cluster « failed » après cinq essais rapprochés et n'y revient JAMAIS seul. Corriger /etc/hosts ne suffisait donc pas ; l'installation relance l'unité et CONSTATE le montage plutôt que de le supposer. Et l'écran nomme maintenant la cause quand il n'a pas de stockage, plutôt que de laisser chercher. Un détail qui aurait fait un faux diagnostic : la sonde de montage n'interroge pas storage.cfg. Ce fichier N'EXISTE PAS sur une installation neuve — Proxmox se contente alors de ses stockages par défaut, et « local » répond parfaitement. Vérifié sur l'hôte : /etc/pve monté, storage.cfg absent, « pvesm status » rendant local avec 25 Go libres. C'est « .version », fichier virtuel de pmxcfs, qui fait foi. --- EN --- Reported on a nested Proxmox. "pvesm" only speaks through /etc/pve, mounted by pmxcfs; with pmxcfs down the command answers "Connection refused", the list is empty, and the screen stops at "no storage" — three floors above the defect. pmxcfs would not start because the hostname resolved only to 127.0.1.1, and it needs a ROUTABLE address. The installer does fix /etc/hosts, but the cloud image sets "manage_etc_hosts: True": cloud-init rewrites it at EVERY boot. The now-automatic reboot is what revealed it — the install fixed it, the reboot booted the right kernel, and cloud-init undid the fix in the same motion. An override file freezes it. Second missing step: systemd marks pve-cluster "failed" after five rapid attempts and never returns to it on its own. Fixing /etc/hosts was therefore not enough; the installer restarts the unit and VERIFIES the mount rather than assuming it. And the screen now names the cause when it has no storage, instead of leaving you to hunt. One detail that would have made a false diagnosis: the mount probe does not ask for storage.cfg. That file DOES NOT EXIST on a fresh install — Proxmox then uses its default storages, and "local" answers perfectly. Verified on the host: /etc/pve mounted, storage.cfg absent, "pvesm status" returning local with 25 GB free. It is ".version", a pmxcfs virtual file, that tells the truth. Assisted-by: Claude Opus 5 (cherry picked from commit 6212853048ba8154f2833744e45076d70bd33c72)
2026-08-25 04:30:48 -04:00
#
[FIX] suivi : relevé Proxmox squelettique, index par nom, état terminal Une cause, deux symptômes. « /cluster/resources » est bâti par pvestatd ; celui-ci arrêté, l'hôte rend quand même une entrée par VM, mais SQUELETTIQUE — ni nom, ni mémoire, ni disque, et « status: unknown ». Le relevé était indexé par NOM : l'entrée disparaissait donc, la VM passait pour absente alors que l'hôte venait de la nommer, et trois tours plus tard 🗑. Comme « effacée » est un état TERMINAL, la ligne comptait pour finie — d'où « 1/1 terminées · 00:09 » sur une installation qui tournait. Le relevé est maintenant indexé par VMID, seul identifiant unique d'un hôte Proxmox, et la correspondance vers les noms se fait là où le manifeste est sous les yeux. Une entrée squelettique reste donc une VM présente, avec ce que l'hôte sait d'elle — sa taille occupée, que « du » donne par VMID. Reste à savoir pourquoi pvestatd était mort. Son journal le dit mot pour mot : « ipcc_send_rec failed: Connection refused » — pve-cluster absent, c'est-à-dire la panne /etc/hosts d'hier. Tous les services de Proxmox avaient échoué ensemble, et systemd n'y revient jamais seul. L'installation relançait le seul pve-cluster ; elle relance désormais l'ensemble, pve-cluster d'abord puisqu'il monte /etc/pve. Vérifié sur l'hôte : pvestatd relancé, et les colonnes passent de « - - - » à « 3.4G/4.0G, 2.3G/25G, 2.2G écrit ». --- EN --- One cause, two symptoms. "/cluster/resources" is built by pvestatd; with it stopped the host still returns one entry per VM, but SKELETAL — no name, no memory, no disk, and "status: unknown". Readings were indexed by NAME, so that entry vanished, the VM looked absent although the host had just named it, and three rounds later 🗑. Since "deleted" is a TERMINAL state the row counted as finished — hence "1/1 done · 00:09" on a running install. Readings are now indexed by VMID, a Proxmox host's only unique identifier, and the mapping to names happens where the manifest is at hand. A skeletal entry therefore stays a present VM, with whatever the host does know about it — its used size, which "du" reports per VMID. Why was pvestatd dead? Its journal says it verbatim: "ipcc_send_rec failed: Connection refused" — no pve-cluster, that is yesterday's /etc/hosts fault. All of Proxmox's services had failed together, and systemd never returns to them on its own. The installer restarted pve-cluster alone; it now restarts the whole set, pve-cluster first since it mounts /etc/pve. Verified on the host: pvestatd restarted, and the columns go from "- - -" to "3.4G/4.0G, 2.3G/25G, 2.2G written". Assisted-by: Claude Opus 5 (cherry picked from commit 3fb85f66842d4b0e9d6ae6446691229b31ef725a)
2026-08-25 05:05:39 -04:00
# L'ordre compte : pve-cluster d'abord, il monte /etc/pve dont les autres
# dépendent.
#
# pvestatd n'est pas un luxe. C'est lui qui remplit « /cluster/resources » ;
# arrêté, l'hôte rend une entrée SQUELETTIQUE par VM — ni nom, ni mémoire, ni
# disque, et « status: unknown ». Le tableau de bord n'a alors aucune colonne
# vivante, et il a même pris cette entrée pour une VM disparue.
[FIX] proxmox : ne pas démarrer le pare-feu depuis l'extérieur Une révision adversariale de la réparation à distance a rendu un constat que ses TROIS lentilles — réseau, systemd, shell — ont trouvé indépendamment : démarrer pve-firewall peut couper le ssh qui répare. Sa configuration vit dans /var/lib/pve-cluster/config.db, donc elle est invisible tant que /etc/pve n'est pas monté — c'est-à-dire exactement dans l'état qu'on répare. On appliquerait des règles qu'on ne peut pas lire, sur la seule voie d'accès à la machine. Il n'est pas nécessaire au but : le stockage et le suivi demandent pve-cluster et pvestatd, l'interface web pveproxy. Il repartira au prochain démarrage, quand /etc/pve sera monté à temps. Le retirer de la liste coûte donc rien et supprime le seul geste qui pouvait isoler un hôte. Deux autres constats de la même révision, également réels. Le gel de cloud-init gardait sur l'EXISTENCE du fichier. Or « printf … > » le TRONQUE avant d'écrire : une coupure au mauvais moment laisse zéro octet, et la garde annonce « déjà gelé » pour toujours. cloud-init continue de remettre 127.0.1.1 à chaque démarrage et le défaut redevient invisible — celui-là même que ce code existe pour supprimer. La garde porte maintenant sur le CONTENU. Et les adresses de lien-local passaient pour routables. Mesuré : « hostname --ip-address » peut ne rendre QUE des fe80::, et une APIPA en 169.254 passait le seul test « ne commence pas par 127. ». pmxcfs n'a alors rien d'utilisable, mais le diagnostic concluait l'inverse et renvoyait vers journalctl au lieu de /etc/hosts. Enfin « la sonde n'a pas répondu » n'est plus lu comme « rien n'est monté » : un dépassement de délai rend les mêmes vides, et on affirmait une cause qu'on n'avait pas constatée. --- EN --- An adversarial review of the remote repair produced one finding all THREE of its lenses — network, systemd, shell — reached independently: starting pve-firewall can cut the ssh doing the repair. Its configuration lives in /var/lib/pve-cluster/config.db, so it is invisible while /etc/pve is unmounted — exactly the state being repaired. We would apply rules we cannot read, over the machine's only way in. It is not needed for the goal: storage and monitoring need pve-cluster and pvestatd, the web interface pveproxy. It will come back at the next boot, when /etc/pve mounts in time. Removing it from the list costs nothing and removes the one gesture that could isolate a host. Two more findings from the same review, equally real. The cloud-init freeze guarded on the file's EXISTENCE. But "printf … >" TRUNCATES before writing: an ill-timed cut leaves zero bytes, and the guard then reports "already frozen" forever. cloud-init keeps putting 127.0.1.1 back at every boot and the defect becomes invisible again — the very one this code exists to remove. The guard now looks at the CONTENT. And link-local addresses counted as routable. Measured: "hostname --ip-address" can return ONLY fe80:: entries, and an APIPA 169.254 passed the lone "does not start with 127." test. pmxcfs then has nothing usable, yet the diagnosis concluded the opposite and pointed at journalctl instead of /etc/hosts. Finally "the probe did not answer" is no longer read as "nothing is mounted": a timeout returns the same emptiness, and we were asserting a cause we had not measured. Assisted-by: Claude Opus 5 (cherry picked from commit fa9fb729d82e8d1a8e4fb549cc8061c7281b5dcb)
2026-08-25 06:31:30 -04:00
# pve-firewall n'y est PAS, et c'est délibéré. Sa configuration vit dans
# /var/lib/pve-cluster/config.db, donc elle est invisible tant que /etc/pve
# n'est pas monté — c'est-à-dire exactement dans l'état qu'on répare. Le
# démarrer, c'est appliquer des règles qu'on ne peut pas lire sur la seule
# voie d'accès à la machine : ce script tourne au bout d'un ssh, et une VM
# imbriquée n'a pas d'autre porte. Une révision adversariale l'a classé
# « isole l'hôte » par trois lentilles indépendantes.
#
# Il n'est de toute façon pas nécessaire au but : le stockage et le suivi
# demandent pve-cluster et pvestatd, l'interface web pveproxy. Le pare-feu
# repartira au prochain démarrage, quand /etc/pve sera monté à temps.
PVE_SERVICES="pve-cluster pvestatd pvedaemon pveproxy"
[FIX] suivi : relevé Proxmox squelettique, index par nom, état terminal Une cause, deux symptômes. « /cluster/resources » est bâti par pvestatd ; celui-ci arrêté, l'hôte rend quand même une entrée par VM, mais SQUELETTIQUE — ni nom, ni mémoire, ni disque, et « status: unknown ». Le relevé était indexé par NOM : l'entrée disparaissait donc, la VM passait pour absente alors que l'hôte venait de la nommer, et trois tours plus tard 🗑. Comme « effacée » est un état TERMINAL, la ligne comptait pour finie — d'où « 1/1 terminées · 00:09 » sur une installation qui tournait. Le relevé est maintenant indexé par VMID, seul identifiant unique d'un hôte Proxmox, et la correspondance vers les noms se fait là où le manifeste est sous les yeux. Une entrée squelettique reste donc une VM présente, avec ce que l'hôte sait d'elle — sa taille occupée, que « du » donne par VMID. Reste à savoir pourquoi pvestatd était mort. Son journal le dit mot pour mot : « ipcc_send_rec failed: Connection refused » — pve-cluster absent, c'est-à-dire la panne /etc/hosts d'hier. Tous les services de Proxmox avaient échoué ensemble, et systemd n'y revient jamais seul. L'installation relançait le seul pve-cluster ; elle relance désormais l'ensemble, pve-cluster d'abord puisqu'il monte /etc/pve. Vérifié sur l'hôte : pvestatd relancé, et les colonnes passent de « - - - » à « 3.4G/4.0G, 2.3G/25G, 2.2G écrit ». --- EN --- One cause, two symptoms. "/cluster/resources" is built by pvestatd; with it stopped the host still returns one entry per VM, but SKELETAL — no name, no memory, no disk, and "status: unknown". Readings were indexed by NAME, so that entry vanished, the VM looked absent although the host had just named it, and three rounds later 🗑. Since "deleted" is a TERMINAL state the row counted as finished — hence "1/1 done · 00:09" on a running install. Readings are now indexed by VMID, a Proxmox host's only unique identifier, and the mapping to names happens where the manifest is at hand. A skeletal entry therefore stays a present VM, with whatever the host does know about it — its used size, which "du" reports per VMID. Why was pvestatd dead? Its journal says it verbatim: "ipcc_send_rec failed: Connection refused" — no pve-cluster, that is yesterday's /etc/hosts fault. All of Proxmox's services had failed together, and systemd never returns to them on its own. The installer restarted pve-cluster alone; it now restarts the whole set, pve-cluster first since it mounts /etc/pve. Verified on the host: pvestatd restarted, and the columns go from "- - -" to "3.4G/4.0G, 2.3G/25G, 2.2G written". Assisted-by: Claude Opus 5 (cherry picked from commit 3fb85f66842d4b0e9d6ae6446691229b31ef725a)
2026-08-25 05:05:39 -04:00
revive_pve_services() {
[FIX] proxmox : pmxcfs sans adresse routable, et le stockage vide Rapporté sur un Proxmox imbriqué. « pvesm » ne parle qu'à travers /etc/pve, monté par pmxcfs ; pmxcfs à terre, la commande répond « Connection refused », la liste est vide, et l'écran s'arrête sur « aucun stockage » — trois étages au-dessus du défaut. pmxcfs ne démarrait pas parce que le nom d'hôte ne résolvait que vers 127.0.1.1, et il cherche une adresse ROUTABLE. L'installation corrige bien /etc/hosts, mais l'image cloud règle « manage_etc_hosts: True » : cloud-init le réécrit à CHAQUE démarrage. C'est le redémarrage désormais automatique qui l'a révélé — l'installation corrigeait, le reboot amorçait le bon noyau, et cloud-init défaisait la correction dans le même mouvement. Un fichier de surcharge le gèle. Deuxième geste manquant : systemd marque pve-cluster « failed » après cinq essais rapprochés et n'y revient JAMAIS seul. Corriger /etc/hosts ne suffisait donc pas ; l'installation relance l'unité et CONSTATE le montage plutôt que de le supposer. Et l'écran nomme maintenant la cause quand il n'a pas de stockage, plutôt que de laisser chercher. Un détail qui aurait fait un faux diagnostic : la sonde de montage n'interroge pas storage.cfg. Ce fichier N'EXISTE PAS sur une installation neuve — Proxmox se contente alors de ses stockages par défaut, et « local » répond parfaitement. Vérifié sur l'hôte : /etc/pve monté, storage.cfg absent, « pvesm status » rendant local avec 25 Go libres. C'est « .version », fichier virtuel de pmxcfs, qui fait foi. --- EN --- Reported on a nested Proxmox. "pvesm" only speaks through /etc/pve, mounted by pmxcfs; with pmxcfs down the command answers "Connection refused", the list is empty, and the screen stops at "no storage" — three floors above the defect. pmxcfs would not start because the hostname resolved only to 127.0.1.1, and it needs a ROUTABLE address. The installer does fix /etc/hosts, but the cloud image sets "manage_etc_hosts: True": cloud-init rewrites it at EVERY boot. The now-automatic reboot is what revealed it — the install fixed it, the reboot booted the right kernel, and cloud-init undid the fix in the same motion. An override file freezes it. Second missing step: systemd marks pve-cluster "failed" after five rapid attempts and never returns to it on its own. Fixing /etc/hosts was therefore not enough; the installer restarts the unit and VERIFIES the mount rather than assuming it. And the screen now names the cause when it has no storage, instead of leaving you to hunt. One detail that would have made a false diagnosis: the mount probe does not ask for storage.cfg. That file DOES NOT EXIST on a fresh install — Proxmox then uses its default storages, and "local" answers perfectly. Verified on the host: /etc/pve mounted, storage.cfg absent, "pvesm status" returning local with 25 GB free. It is ".version", a pmxcfs virtual file, that tells the truth. Assisted-by: Claude Opus 5 (cherry picked from commit 6212853048ba8154f2833744e45076d70bd33c72)
2026-08-25 04:30:48 -04:00
command -v systemctl >/dev/null 2>&1 || return 0
[FIX] suivi : relevé Proxmox squelettique, index par nom, état terminal Une cause, deux symptômes. « /cluster/resources » est bâti par pvestatd ; celui-ci arrêté, l'hôte rend quand même une entrée par VM, mais SQUELETTIQUE — ni nom, ni mémoire, ni disque, et « status: unknown ». Le relevé était indexé par NOM : l'entrée disparaissait donc, la VM passait pour absente alors que l'hôte venait de la nommer, et trois tours plus tard 🗑. Comme « effacée » est un état TERMINAL, la ligne comptait pour finie — d'où « 1/1 terminées · 00:09 » sur une installation qui tournait. Le relevé est maintenant indexé par VMID, seul identifiant unique d'un hôte Proxmox, et la correspondance vers les noms se fait là où le manifeste est sous les yeux. Une entrée squelettique reste donc une VM présente, avec ce que l'hôte sait d'elle — sa taille occupée, que « du » donne par VMID. Reste à savoir pourquoi pvestatd était mort. Son journal le dit mot pour mot : « ipcc_send_rec failed: Connection refused » — pve-cluster absent, c'est-à-dire la panne /etc/hosts d'hier. Tous les services de Proxmox avaient échoué ensemble, et systemd n'y revient jamais seul. L'installation relançait le seul pve-cluster ; elle relance désormais l'ensemble, pve-cluster d'abord puisqu'il monte /etc/pve. Vérifié sur l'hôte : pvestatd relancé, et les colonnes passent de « - - - » à « 3.4G/4.0G, 2.3G/25G, 2.2G écrit ». --- EN --- One cause, two symptoms. "/cluster/resources" is built by pvestatd; with it stopped the host still returns one entry per VM, but SKELETAL — no name, no memory, no disk, and "status: unknown". Readings were indexed by NAME, so that entry vanished, the VM looked absent although the host had just named it, and three rounds later 🗑. Since "deleted" is a TERMINAL state the row counted as finished — hence "1/1 done · 00:09" on a running install. Readings are now indexed by VMID, a Proxmox host's only unique identifier, and the mapping to names happens where the manifest is at hand. A skeletal entry therefore stays a present VM, with whatever the host does know about it — its used size, which "du" reports per VMID. Why was pvestatd dead? Its journal says it verbatim: "ipcc_send_rec failed: Connection refused" — no pve-cluster, that is yesterday's /etc/hosts fault. All of Proxmox's services had failed together, and systemd never returns to them on its own. The installer restarted pve-cluster alone; it now restarts the whole set, pve-cluster first since it mounts /etc/pve. Verified on the host: pvestatd restarted, and the columns go from "- - -" to "3.4G/4.0G, 2.3G/25G, 2.2G written". Assisted-by: Claude Opus 5 (cherry picked from commit 3fb85f66842d4b0e9d6ae6446691229b31ef725a)
2026-08-25 05:05:39 -04:00
local unite etat casse=""
for unite in ${PVE_SERVICES}; do
systemctl list-unit-files "${unite}.service" >/dev/null 2>&1 || continue
etat="$(systemctl is-active "${unite}" 2>/dev/null || true)"
[ "${etat}" = "active" ] && continue
casse="${casse} ${unite}"
done
[ -n "${casse}" ] || return 0
say " services à relancer :${casse}"
[FIX] proxmox : pmxcfs sans adresse routable, et le stockage vide Rapporté sur un Proxmox imbriqué. « pvesm » ne parle qu'à travers /etc/pve, monté par pmxcfs ; pmxcfs à terre, la commande répond « Connection refused », la liste est vide, et l'écran s'arrête sur « aucun stockage » — trois étages au-dessus du défaut. pmxcfs ne démarrait pas parce que le nom d'hôte ne résolvait que vers 127.0.1.1, et il cherche une adresse ROUTABLE. L'installation corrige bien /etc/hosts, mais l'image cloud règle « manage_etc_hosts: True » : cloud-init le réécrit à CHAQUE démarrage. C'est le redémarrage désormais automatique qui l'a révélé — l'installation corrigeait, le reboot amorçait le bon noyau, et cloud-init défaisait la correction dans le même mouvement. Un fichier de surcharge le gèle. Deuxième geste manquant : systemd marque pve-cluster « failed » après cinq essais rapprochés et n'y revient JAMAIS seul. Corriger /etc/hosts ne suffisait donc pas ; l'installation relance l'unité et CONSTATE le montage plutôt que de le supposer. Et l'écran nomme maintenant la cause quand il n'a pas de stockage, plutôt que de laisser chercher. Un détail qui aurait fait un faux diagnostic : la sonde de montage n'interroge pas storage.cfg. Ce fichier N'EXISTE PAS sur une installation neuve — Proxmox se contente alors de ses stockages par défaut, et « local » répond parfaitement. Vérifié sur l'hôte : /etc/pve monté, storage.cfg absent, « pvesm status » rendant local avec 25 Go libres. C'est « .version », fichier virtuel de pmxcfs, qui fait foi. --- EN --- Reported on a nested Proxmox. "pvesm" only speaks through /etc/pve, mounted by pmxcfs; with pmxcfs down the command answers "Connection refused", the list is empty, and the screen stops at "no storage" — three floors above the defect. pmxcfs would not start because the hostname resolved only to 127.0.1.1, and it needs a ROUTABLE address. The installer does fix /etc/hosts, but the cloud image sets "manage_etc_hosts: True": cloud-init rewrites it at EVERY boot. The now-automatic reboot is what revealed it — the install fixed it, the reboot booted the right kernel, and cloud-init undid the fix in the same motion. An override file freezes it. Second missing step: systemd marks pve-cluster "failed" after five rapid attempts and never returns to it on its own. Fixing /etc/hosts was therefore not enough; the installer restarts the unit and VERIFIES the mount rather than assuming it. And the screen now names the cause when it has no storage, instead of leaving you to hunt. One detail that would have made a false diagnosis: the mount probe does not ask for storage.cfg. That file DOES NOT EXIST on a fresh install — Proxmox then uses its default storages, and "local" answers perfectly. Verified on the host: /etc/pve mounted, storage.cfg absent, "pvesm status" returning local with 25 GB free. It is ".version", a pmxcfs virtual file, that tells the truth. Assisted-by: Claude Opus 5 (cherry picked from commit 6212853048ba8154f2833744e45076d70bd33c72)
2026-08-25 04:30:48 -04:00
if [ "${DRY}" = "1" ]; then
[FIX] suivi : relevé Proxmox squelettique, index par nom, état terminal Une cause, deux symptômes. « /cluster/resources » est bâti par pvestatd ; celui-ci arrêté, l'hôte rend quand même une entrée par VM, mais SQUELETTIQUE — ni nom, ni mémoire, ni disque, et « status: unknown ». Le relevé était indexé par NOM : l'entrée disparaissait donc, la VM passait pour absente alors que l'hôte venait de la nommer, et trois tours plus tard 🗑. Comme « effacée » est un état TERMINAL, la ligne comptait pour finie — d'où « 1/1 terminées · 00:09 » sur une installation qui tournait. Le relevé est maintenant indexé par VMID, seul identifiant unique d'un hôte Proxmox, et la correspondance vers les noms se fait là où le manifeste est sous les yeux. Une entrée squelettique reste donc une VM présente, avec ce que l'hôte sait d'elle — sa taille occupée, que « du » donne par VMID. Reste à savoir pourquoi pvestatd était mort. Son journal le dit mot pour mot : « ipcc_send_rec failed: Connection refused » — pve-cluster absent, c'est-à-dire la panne /etc/hosts d'hier. Tous les services de Proxmox avaient échoué ensemble, et systemd n'y revient jamais seul. L'installation relançait le seul pve-cluster ; elle relance désormais l'ensemble, pve-cluster d'abord puisqu'il monte /etc/pve. Vérifié sur l'hôte : pvestatd relancé, et les colonnes passent de « - - - » à « 3.4G/4.0G, 2.3G/25G, 2.2G écrit ». --- EN --- One cause, two symptoms. "/cluster/resources" is built by pvestatd; with it stopped the host still returns one entry per VM, but SKELETAL — no name, no memory, no disk, and "status: unknown". Readings were indexed by NAME, so that entry vanished, the VM looked absent although the host had just named it, and three rounds later 🗑. Since "deleted" is a TERMINAL state the row counted as finished — hence "1/1 done · 00:09" on a running install. Readings are now indexed by VMID, a Proxmox host's only unique identifier, and the mapping to names happens where the manifest is at hand. A skeletal entry therefore stays a present VM, with whatever the host does know about it — its used size, which "du" reports per VMID. Why was pvestatd dead? Its journal says it verbatim: "ipcc_send_rec failed: Connection refused" — no pve-cluster, that is yesterday's /etc/hosts fault. All of Proxmox's services had failed together, and systemd never returns to them on its own. The installer restarted pve-cluster alone; it now restarts the whole set, pve-cluster first since it mounts /etc/pve. Verified on the host: pvestatd restarted, and the columns go from "- - -" to "3.4G/4.0G, 2.3G/25G, 2.2G written". Assisted-by: Claude Opus 5 (cherry picked from commit 3fb85f66842d4b0e9d6ae6446691229b31ef725a)
2026-08-25 05:05:39 -04:00
say " ${Yellow}[dry-run]${Color_Off} systemctl reset-failed puis" \
"start :${casse}"
[FIX] proxmox : pmxcfs sans adresse routable, et le stockage vide Rapporté sur un Proxmox imbriqué. « pvesm » ne parle qu'à travers /etc/pve, monté par pmxcfs ; pmxcfs à terre, la commande répond « Connection refused », la liste est vide, et l'écran s'arrête sur « aucun stockage » — trois étages au-dessus du défaut. pmxcfs ne démarrait pas parce que le nom d'hôte ne résolvait que vers 127.0.1.1, et il cherche une adresse ROUTABLE. L'installation corrige bien /etc/hosts, mais l'image cloud règle « manage_etc_hosts: True » : cloud-init le réécrit à CHAQUE démarrage. C'est le redémarrage désormais automatique qui l'a révélé — l'installation corrigeait, le reboot amorçait le bon noyau, et cloud-init défaisait la correction dans le même mouvement. Un fichier de surcharge le gèle. Deuxième geste manquant : systemd marque pve-cluster « failed » après cinq essais rapprochés et n'y revient JAMAIS seul. Corriger /etc/hosts ne suffisait donc pas ; l'installation relance l'unité et CONSTATE le montage plutôt que de le supposer. Et l'écran nomme maintenant la cause quand il n'a pas de stockage, plutôt que de laisser chercher. Un détail qui aurait fait un faux diagnostic : la sonde de montage n'interroge pas storage.cfg. Ce fichier N'EXISTE PAS sur une installation neuve — Proxmox se contente alors de ses stockages par défaut, et « local » répond parfaitement. Vérifié sur l'hôte : /etc/pve monté, storage.cfg absent, « pvesm status » rendant local avec 25 Go libres. C'est « .version », fichier virtuel de pmxcfs, qui fait foi. --- EN --- Reported on a nested Proxmox. "pvesm" only speaks through /etc/pve, mounted by pmxcfs; with pmxcfs down the command answers "Connection refused", the list is empty, and the screen stops at "no storage" — three floors above the defect. pmxcfs would not start because the hostname resolved only to 127.0.1.1, and it needs a ROUTABLE address. The installer does fix /etc/hosts, but the cloud image sets "manage_etc_hosts: True": cloud-init rewrites it at EVERY boot. The now-automatic reboot is what revealed it — the install fixed it, the reboot booted the right kernel, and cloud-init undid the fix in the same motion. An override file freezes it. Second missing step: systemd marks pve-cluster "failed" after five rapid attempts and never returns to it on its own. Fixing /etc/hosts was therefore not enough; the installer restarts the unit and VERIFIES the mount rather than assuming it. And the screen now names the cause when it has no storage, instead of leaving you to hunt. One detail that would have made a false diagnosis: the mount probe does not ask for storage.cfg. That file DOES NOT EXIST on a fresh install — Proxmox then uses its default storages, and "local" answers perfectly. Verified on the host: /etc/pve mounted, storage.cfg absent, "pvesm status" returning local with 25 GB free. It is ".version", a pmxcfs virtual file, that tells the truth. Assisted-by: Claude Opus 5 (cherry picked from commit 6212853048ba8154f2833744e45076d70bd33c72)
2026-08-25 04:30:48 -04:00
return 0
fi
[FIX] suivi : relevé Proxmox squelettique, index par nom, état terminal Une cause, deux symptômes. « /cluster/resources » est bâti par pvestatd ; celui-ci arrêté, l'hôte rend quand même une entrée par VM, mais SQUELETTIQUE — ni nom, ni mémoire, ni disque, et « status: unknown ». Le relevé était indexé par NOM : l'entrée disparaissait donc, la VM passait pour absente alors que l'hôte venait de la nommer, et trois tours plus tard 🗑. Comme « effacée » est un état TERMINAL, la ligne comptait pour finie — d'où « 1/1 terminées · 00:09 » sur une installation qui tournait. Le relevé est maintenant indexé par VMID, seul identifiant unique d'un hôte Proxmox, et la correspondance vers les noms se fait là où le manifeste est sous les yeux. Une entrée squelettique reste donc une VM présente, avec ce que l'hôte sait d'elle — sa taille occupée, que « du » donne par VMID. Reste à savoir pourquoi pvestatd était mort. Son journal le dit mot pour mot : « ipcc_send_rec failed: Connection refused » — pve-cluster absent, c'est-à-dire la panne /etc/hosts d'hier. Tous les services de Proxmox avaient échoué ensemble, et systemd n'y revient jamais seul. L'installation relançait le seul pve-cluster ; elle relance désormais l'ensemble, pve-cluster d'abord puisqu'il monte /etc/pve. Vérifié sur l'hôte : pvestatd relancé, et les colonnes passent de « - - - » à « 3.4G/4.0G, 2.3G/25G, 2.2G écrit ». --- EN --- One cause, two symptoms. "/cluster/resources" is built by pvestatd; with it stopped the host still returns one entry per VM, but SKELETAL — no name, no memory, no disk, and "status: unknown". Readings were indexed by NAME, so that entry vanished, the VM looked absent although the host had just named it, and three rounds later 🗑. Since "deleted" is a TERMINAL state the row counted as finished — hence "1/1 done · 00:09" on a running install. Readings are now indexed by VMID, a Proxmox host's only unique identifier, and the mapping to names happens where the manifest is at hand. A skeletal entry therefore stays a present VM, with whatever the host does know about it — its used size, which "du" reports per VMID. Why was pvestatd dead? Its journal says it verbatim: "ipcc_send_rec failed: Connection refused" — no pve-cluster, that is yesterday's /etc/hosts fault. All of Proxmox's services had failed together, and systemd never returns to them on its own. The installer restarted pve-cluster alone; it now restarts the whole set, pve-cluster first since it mounts /etc/pve. Verified on the host: pvestatd restarted, and the columns go from "- - -" to "3.4G/4.0G, 2.3G/25G, 2.2G written". Assisted-by: Claude Opus 5 (cherry picked from commit 3fb85f66842d4b0e9d6ae6446691229b31ef725a)
2026-08-25 05:05:39 -04:00
for unite in ${casse}; do
sudo systemctl reset-failed "${unite}" 2>/dev/null || true
sudo systemctl start "${unite}" 2>&1 || \
say " ${Yellow}⚠${Color_Off} ${unite} :" \
"journalctl -u ${unite} -n 30"
[FIX] proxmox : pmxcfs sans adresse routable, et le stockage vide Rapporté sur un Proxmox imbriqué. « pvesm » ne parle qu'à travers /etc/pve, monté par pmxcfs ; pmxcfs à terre, la commande répond « Connection refused », la liste est vide, et l'écran s'arrête sur « aucun stockage » — trois étages au-dessus du défaut. pmxcfs ne démarrait pas parce que le nom d'hôte ne résolvait que vers 127.0.1.1, et il cherche une adresse ROUTABLE. L'installation corrige bien /etc/hosts, mais l'image cloud règle « manage_etc_hosts: True » : cloud-init le réécrit à CHAQUE démarrage. C'est le redémarrage désormais automatique qui l'a révélé — l'installation corrigeait, le reboot amorçait le bon noyau, et cloud-init défaisait la correction dans le même mouvement. Un fichier de surcharge le gèle. Deuxième geste manquant : systemd marque pve-cluster « failed » après cinq essais rapprochés et n'y revient JAMAIS seul. Corriger /etc/hosts ne suffisait donc pas ; l'installation relance l'unité et CONSTATE le montage plutôt que de le supposer. Et l'écran nomme maintenant la cause quand il n'a pas de stockage, plutôt que de laisser chercher. Un détail qui aurait fait un faux diagnostic : la sonde de montage n'interroge pas storage.cfg. Ce fichier N'EXISTE PAS sur une installation neuve — Proxmox se contente alors de ses stockages par défaut, et « local » répond parfaitement. Vérifié sur l'hôte : /etc/pve monté, storage.cfg absent, « pvesm status » rendant local avec 25 Go libres. C'est « .version », fichier virtuel de pmxcfs, qui fait foi. --- EN --- Reported on a nested Proxmox. "pvesm" only speaks through /etc/pve, mounted by pmxcfs; with pmxcfs down the command answers "Connection refused", the list is empty, and the screen stops at "no storage" — three floors above the defect. pmxcfs would not start because the hostname resolved only to 127.0.1.1, and it needs a ROUTABLE address. The installer does fix /etc/hosts, but the cloud image sets "manage_etc_hosts: True": cloud-init rewrites it at EVERY boot. The now-automatic reboot is what revealed it — the install fixed it, the reboot booted the right kernel, and cloud-init undid the fix in the same motion. An override file freezes it. Second missing step: systemd marks pve-cluster "failed" after five rapid attempts and never returns to it on its own. Fixing /etc/hosts was therefore not enough; the installer restarts the unit and VERIFIES the mount rather than assuming it. And the screen now names the cause when it has no storage, instead of leaving you to hunt. One detail that would have made a false diagnosis: the mount probe does not ask for storage.cfg. That file DOES NOT EXIST on a fresh install — Proxmox then uses its default storages, and "local" answers perfectly. Verified on the host: /etc/pve mounted, storage.cfg absent, "pvesm status" returning local with 25 GB free. It is ".version", a pmxcfs virtual file, that tells the truth. Assisted-by: Claude Opus 5 (cherry picked from commit 6212853048ba8154f2833744e45076d70bd33c72)
2026-08-25 04:30:48 -04:00
CHANGED=1
[FIX] suivi : relevé Proxmox squelettique, index par nom, état terminal Une cause, deux symptômes. « /cluster/resources » est bâti par pvestatd ; celui-ci arrêté, l'hôte rend quand même une entrée par VM, mais SQUELETTIQUE — ni nom, ni mémoire, ni disque, et « status: unknown ». Le relevé était indexé par NOM : l'entrée disparaissait donc, la VM passait pour absente alors que l'hôte venait de la nommer, et trois tours plus tard 🗑. Comme « effacée » est un état TERMINAL, la ligne comptait pour finie — d'où « 1/1 terminées · 00:09 » sur une installation qui tournait. Le relevé est maintenant indexé par VMID, seul identifiant unique d'un hôte Proxmox, et la correspondance vers les noms se fait là où le manifeste est sous les yeux. Une entrée squelettique reste donc une VM présente, avec ce que l'hôte sait d'elle — sa taille occupée, que « du » donne par VMID. Reste à savoir pourquoi pvestatd était mort. Son journal le dit mot pour mot : « ipcc_send_rec failed: Connection refused » — pve-cluster absent, c'est-à-dire la panne /etc/hosts d'hier. Tous les services de Proxmox avaient échoué ensemble, et systemd n'y revient jamais seul. L'installation relançait le seul pve-cluster ; elle relance désormais l'ensemble, pve-cluster d'abord puisqu'il monte /etc/pve. Vérifié sur l'hôte : pvestatd relancé, et les colonnes passent de « - - - » à « 3.4G/4.0G, 2.3G/25G, 2.2G écrit ». --- EN --- One cause, two symptoms. "/cluster/resources" is built by pvestatd; with it stopped the host still returns one entry per VM, but SKELETAL — no name, no memory, no disk, and "status: unknown". Readings were indexed by NAME, so that entry vanished, the VM looked absent although the host had just named it, and three rounds later 🗑. Since "deleted" is a TERMINAL state the row counted as finished — hence "1/1 done · 00:09" on a running install. Readings are now indexed by VMID, a Proxmox host's only unique identifier, and the mapping to names happens where the manifest is at hand. A skeletal entry therefore stays a present VM, with whatever the host does know about it — its used size, which "du" reports per VMID. Why was pvestatd dead? Its journal says it verbatim: "ipcc_send_rec failed: Connection refused" — no pve-cluster, that is yesterday's /etc/hosts fault. All of Proxmox's services had failed together, and systemd never returns to them on its own. The installer restarted pve-cluster alone; it now restarts the whole set, pve-cluster first since it mounts /etc/pve. Verified on the host: pvestatd restarted, and the columns go from "- - -" to "3.4G/4.0G, 2.3G/25G, 2.2G written". Assisted-by: Claude Opus 5 (cherry picked from commit 3fb85f66842d4b0e9d6ae6446691229b31ef725a)
2026-08-25 05:05:39 -04:00
done
[FIX] proxmox : pmxcfs sans adresse routable, et le stockage vide Rapporté sur un Proxmox imbriqué. « pvesm » ne parle qu'à travers /etc/pve, monté par pmxcfs ; pmxcfs à terre, la commande répond « Connection refused », la liste est vide, et l'écran s'arrête sur « aucun stockage » — trois étages au-dessus du défaut. pmxcfs ne démarrait pas parce que le nom d'hôte ne résolvait que vers 127.0.1.1, et il cherche une adresse ROUTABLE. L'installation corrige bien /etc/hosts, mais l'image cloud règle « manage_etc_hosts: True » : cloud-init le réécrit à CHAQUE démarrage. C'est le redémarrage désormais automatique qui l'a révélé — l'installation corrigeait, le reboot amorçait le bon noyau, et cloud-init défaisait la correction dans le même mouvement. Un fichier de surcharge le gèle. Deuxième geste manquant : systemd marque pve-cluster « failed » après cinq essais rapprochés et n'y revient JAMAIS seul. Corriger /etc/hosts ne suffisait donc pas ; l'installation relance l'unité et CONSTATE le montage plutôt que de le supposer. Et l'écran nomme maintenant la cause quand il n'a pas de stockage, plutôt que de laisser chercher. Un détail qui aurait fait un faux diagnostic : la sonde de montage n'interroge pas storage.cfg. Ce fichier N'EXISTE PAS sur une installation neuve — Proxmox se contente alors de ses stockages par défaut, et « local » répond parfaitement. Vérifié sur l'hôte : /etc/pve monté, storage.cfg absent, « pvesm status » rendant local avec 25 Go libres. C'est « .version », fichier virtuel de pmxcfs, qui fait foi. --- EN --- Reported on a nested Proxmox. "pvesm" only speaks through /etc/pve, mounted by pmxcfs; with pmxcfs down the command answers "Connection refused", the list is empty, and the screen stops at "no storage" — three floors above the defect. pmxcfs would not start because the hostname resolved only to 127.0.1.1, and it needs a ROUTABLE address. The installer does fix /etc/hosts, but the cloud image sets "manage_etc_hosts: True": cloud-init rewrites it at EVERY boot. The now-automatic reboot is what revealed it — the install fixed it, the reboot booted the right kernel, and cloud-init undid the fix in the same motion. An override file freezes it. Second missing step: systemd marks pve-cluster "failed" after five rapid attempts and never returns to it on its own. Fixing /etc/hosts was therefore not enough; the installer restarts the unit and VERIFIES the mount rather than assuming it. And the screen now names the cause when it has no storage, instead of leaving you to hunt. One detail that would have made a false diagnosis: the mount probe does not ask for storage.cfg. That file DOES NOT EXIST on a fresh install — Proxmox then uses its default storages, and "local" answers perfectly. Verified on the host: /etc/pve mounted, storage.cfg absent, "pvesm status" returning local with 25 GB free. It is ".version", a pmxcfs virtual file, that tells the truth. Assisted-by: Claude Opus 5 (cherry picked from commit 6212853048ba8154f2833744e45076d70bd33c72)
2026-08-25 04:30:48 -04:00
# Le montage n'est pas instantané : on le CONSTATE plutôt que de le
# supposer, et on le dit quand il n'arrive pas.
local i
for i in 1 2 3 4 5 6 7 8 9 10; do
[ -e /etc/pve/.version ] && break
sleep 1
done
if [ -e /etc/pve/.version ]; then
say " ${Green}✓${Color_Off} /etc/pve monté"
else
say " ${Yellow}⚠${Color_Off} /etc/pve toujours absent :" \
"journalctl -u pve-cluster -n 30"
fi
}
# --- 4. Dépôt et clé --------------------------------------------------------
add_repo() {
local attendu="KEY_SHA256_${SUITE}"
attendu="${!attendu:-}"
if [ ! -s "${KEYRING}" ]; then
say " clé du dépôt -> ${KEYRING}"
run sudo mkdir -p "$(dirname "${KEYRING}")"
run sudo wget -q "${KEY_URL}" -O "${KEYRING}" \
|| die "téléchargement de la clé impossible : ${KEY_URL}"
# Un wget qui rend 0 sans laisser de fichier — proxy captif, disque
# plein — ferait mourir la suite sur un message de sha256sum au lieu
# d'un diagnostic.
if [ "${DRY}" != "1" ]; then
sudo test -s "${KEYRING}" \
|| die "clé absente ou vide après téléchargement : ${KEYRING}"
fi
CHANGED=1
fi
if [ -n "${attendu}" ] && [ "${DRY}" = "1" ]; then
say " clé à vérifier contre sha256 ${attendu:0:16}…"
elif [ -n "${attendu}" ]; then
local vu
vu="$(sudo sha256sum "${KEYRING}" 2>/dev/null | awk '{print $1}')" \
|| true
[ -n "${vu}" ] || die "somme de la clé illisible : ${KEYRING}"
if [ "${vu}" != "${attendu}" ]; then
# On efface la clé douteuse : la laisser en place ferait passer la
# prochaine exécution pour bonne, le fichier étant non vide.
run sudo rm -f "${KEYRING}"
die "somme de la clé inattendue :\n vue ${vu}\n" \
" attendue ${attendu}"
fi
say " clé vérifiée (sha256 ${vu:0:16}…)"
else
say "${Yellow}⚠${Color_Off} aucune somme connue pour « ${SUITE} » :" \
"clé acceptée sans contrôle."
fi
# Format deb822, celui que l'amont recommande sur Debian 13.
local voulu
voulu="$(printf 'Types: deb\nURIs: http://download.proxmox.com/debian/pve\nSuites: %s\nComponents: pve-no-subscription\nSigned-By: %s\n' \
"${SUITE}" "${KEYRING}")"
if [ "$(cat "${SOURCES}" 2>/dev/null || true)" != "${voulu}" ]; then
say " dépôt pve-no-subscription -> ${SOURCES}"
if [ "${DRY}" = "1" ]; then
say " ${Yellow}[dry-run]${Color_Off} ${SOURCES} :" \
"$(printf '%s' "${voulu}" | tr '\n' '|')"
else
printf '%s\n' "${voulu}" | sudo tee "${SOURCES}" >/dev/null
fi
CHANGED=1
fi
}
# --- 6. Dépôt entreprise ----------------------------------------------------
# « proxmox-ve » installe SON dépôt entreprise (pve-enterprise.sources), qui
# exige un abonnement payant. Sans lui, tout « apt update » ultérieur échoue :
# « 401 Unauthorized » puis « The repository is not signed », et la machine ne
# peut plus rien installer — pas même une mise à jour de sécurité. Mesuré sur
# la VM d'essai, au deuxième passage du script.
#
# On le désactive au lieu de l'effacer : « Enabled: false » est la forme deb822
# prévue pour cela, elle survit aux mises à jour du paquet, et il suffit de
# retirer la ligne le jour où un abonnement existe.
disable_enterprise() {
local f
for f in /etc/apt/sources.list.d/pve-enterprise.sources \
/etc/apt/sources.list.d/ceph.sources; do
[ -e "${f}" ] || continue
if sudo grep -qiE '^[[:space:]]*Enabled:[[:space:]]*(false|no)' \
"${f}"; then
continue
fi
say " dépôt entreprise désactivé : $(basename "${f}")"
if [ "${DRY}" = "1" ]; then
say " ${Yellow}[dry-run]${Color_Off} Enabled: false >> ${f}"
else
printf 'Enabled: false\n' | sudo tee -a "${f}" >/dev/null
fi
CHANGED=1
done
# Les anciennes formes « .list », au cas où une mise à jour les remette.
for f in /etc/apt/sources.list.d/pve-enterprise.list; do
[ -e "${f}" ] || continue
sudo grep -qE '^[[:space:]]*#' "${f}" && continue
say " dépôt entreprise commenté : $(basename "${f}")"
run sudo sed -i -E 's/^([[:space:]]*deb)/#\1/' "${f}"
CHANGED=1
done
}
# --- 5. Les paquets ---------------------------------------------------------
# Disque d'amorçage, pour la préréponse de grub-pc.
boot_disk() {
local src
src="$(findmnt -no SOURCE /boot 2>/dev/null \
|| findmnt -no SOURCE / 2>/dev/null)"
[ -n "${src}" ] || return 1
local dq
dq="$(lsblk -no pkname "${src}" 2>/dev/null | head -1)"
[ -n "${dq}" ] || return 1
printf '/dev/%s\n' "${dq}"
}
# Deux paquets posent des questions debconf, et une seule sans réponse suffit à
# faire échouer TOUTE la transaction apt :
#
# - postfix demande son type et son nom de courrier. Sans préréponse,
# l'installation attend une saisie que personne ne verra — un déploiement
# par SSH y reste pendu.
# - grub-pc demande SUR QUEL DISQUE s'installer. C'est le piège propre à
# l'image cloud : elle amorce en EFI (grub-cloud-amd64), les paquets pve
# tirent grub-pc par-dessus, et sa post-installation refuse de deviner —
# « You must correct your GRUB install devices before proceeding », mesuré,
# dpkg s'arrête et le noyau Proxmox reste à moitié configuré.
preseed_debconf() {
command -v debconf-set-selections >/dev/null 2>&1 || return 0
local lignes disque
lignes="$(printf '%s\n' \
"postfix postfix/main_mailer_type select Local only" \
"postfix postfix/mailname string $(hostname -f 2>/dev/null \
|| hostname -s)")"
if disque="$(boot_disk)"; then
lignes="$(printf '%s\n%s\n' "${lignes}" \
"grub-pc grub-pc/install_devices multiselect ${disque}")"
else
say "${Yellow}⚠${Color_Off} disque d'amorçage introuvable :" \
"grub-pc pourrait demander où s'installer."
fi
# Pas de tube vers « run » : en dry-run il ne lirait pas son entrée, le
# printf recevrait SIGPIPE, et « set -o pipefail » emporterait le script —
# mort silencieuse sur un code 141. Vécu.
if [ "${DRY}" = "1" ]; then
say " ${Yellow}[dry-run]${Color_Off} debconf-set-selections :" \
"$(printf '%s' "${lignes}" | tr '\n' '|')"
return 0
fi
printf '%s\n' "${lignes}" | sudo debconf-set-selections
}
# « DPkg::Lock::Timeout » : sur une VM fraîchement déployée, cloud-init tient
# encore le verrou d'apt — mesuré, « E: Could not get lock
# /var/lib/apt/lists/lock. It is held by process 996 (apt-get) », et le script
# mourait 40 secondes après le démarrage. apt sait ATTENDRE son tour depuis la
# 1.9 ; sans cette option il abandonne immédiatement.
apt_get() {
run sudo env DEBIAN_FRONTEND=noninteractive \
apt-get -o Dpkg::Options::=--force-confold \
-o DPkg::Lock::Timeout=600 -y "$@"
}
# Attendre la fin de cloud-init AVANT de toucher à apt : c'est lui qui pose les
# paquets de la première mise en route. Son état final n'est PAS un critère —
# vérifié sur l'image Debian 13, où il rend « error » pour deux modules sans
# rapport (console-setup absent, update-locale) tout en ayant terminé son
# travail. On attend qu'il ait fini, pas qu'il soit content.
wait_cloud_init() {
command -v cloud-init >/dev/null 2>&1 || return 0
say " attente de la fin de cloud-init…"
if [ "${DRY}" = "1" ]; then
say " ${Yellow}[dry-run]${Color_Off} cloud-init status --wait"
return 0
fi
timeout 600 cloud-init status --wait >/dev/null 2>&1 || true
return 0
}
[FIX] proxmox : apt-daily tient le verrou au démarrage Trois pannes trouvées en LANÇANT la descente, aucune vue en la relisant — ni par moi, ni par l'attaque adversariale. Le premier « apt update » d'une image cloud échoue sur un verrou qui n'est pas celui qu'on croit. Mesuré une seconde après le premier ssh : E: Could not get lock /var/lib/apt/lists/lock. It is held by process 1026 (apt-get) Ce n'est pas cloud-init — « status --wait » avait rendu la main. C'est apt-daily, le minuteur de Debian, qui se déclenche au démarrage. Et le verrou des LISTES n'est pas couvert par « DPkg::Lock::Timeout », que l'installeur réglait pourtant déjà à 600 s : cette attente ne vaut que pour dpkg. On arrête donc les minuteurs, puis on RÉESSAIE — arrêter une unité n'interrompt pas l'apt-get déjà en vol. Le défaut touchait tout déploiement Proxmox, pas seulement ce test. Le premier étage n'avait pas d'alias ssh. « deploy_qemu.py » en ligne de commande n'écrit pas d'entrée ~/.ssh/config — le menu le fait, la CLI non. La descente aurait attendu son plein délai avant de conclure « jamais joignable » sur une VM qui répondait à son adresse. Elle l'écrit maintenant elle-même, depuis l'adresse résolue, et refuse d'avancer si la VM n'en a pas. Et la réserve de l'hôte est proportionnelle. Quatre gigaoctets sur une machine de soixante, c'était 6 % laissés au système : le jour où les invités touchent vraiment leur mémoire, c'est l'hôte qui part en swap — et la mesure serait celle du swap, pas de l'imbrication. Un huitième, avec le plancher d'avant pour les petites machines. Ce que la descente a établi en trois étages : 392 s, 644 s, 1120 s, soit 1,7 fois par étage. Puis la poignée de main ssh passe de 77 à 1664 secondes au quatrième — vingt fois d'un seul cran. Le coude est là. Et le mur que j'avais pris pour une limite d'imbrication n'en était pas une. La VM qui gelait au quatrième étage avait douze vCPU ; celle-ci en a deux et elle passe, en écrivant. C'était une limite de parallélisme SOUS imbrication — exactement ce que l'algorithme borne, vérifié pour la première fois plutôt que supposé. --- EN --- Three faults found by RUNNING the descent, none seen by reading it — neither by me nor by the adversarial attack. A cloud image's first "apt update" fails on a lock that is not the one you expect. Measured one second after the first ssh: E: Could not get lock /var/lib/apt/lists/lock. It is held by process 1026 (apt-get) It is not cloud-init — "status --wait" had returned. It is apt-daily, Debian's timer, firing at boot. And the LISTS lock is not covered by "DPkg::Lock::Timeout", which the installer already set to 600 s: that wait only applies to dpkg. So we stop the timers, then RETRY — stopping a unit does not interrupt the apt-get already in flight. The defect affected every Proxmox deployment, not just this test. The first level had no ssh alias. "deploy_qemu.py" on the command line does not write a ~/.ssh/config entry — the menu does, the CLI does not. The descent would have waited its full timeout before concluding "never reachable" about a VM answering at its address. It now writes the entry itself, from the resolved address, and refuses to proceed if the VM has none. And the host's reserve is proportional. Four gigabytes on a sixty-gigabyte machine left 6 % to the system: the day the guests really touch their memory, the host swaps — and the measurement would be of swap, not of nesting. One eighth now, keeping the old floor for small machines. What the descent established over three levels: 392 s, 644 s, 1120 s — 1.7x per level. Then the ssh handshake goes from 77 to 1664 seconds at the fourth: twenty times in one step. That is the elbow. And the wall I had taken for a nesting limit was not one. The VM that froze at the fourth level had twelve vCPU; this one has two and it gets through, writing. It was a limit of parallelism UNDER nesting — exactly what the algorithm caps, verified for the first time rather than assumed. Assisted-by: Claude Opus 5 (cherry picked from commit 7f86562cbd8f10017dcb88fe4272efc162cbccbc)
2026-08-27 04:27:50 -04:00
# Le premier « apt update » d'une image cloud tombe sur un verrou qui n'est
# pas celui qu'on croit. Mesuré, une seconde après le premier ssh :
#
# E: Could not get lock /var/lib/apt/lists/lock.
# It is held by process 1026 (apt-get)
#
# Ce n'est pas cloud-init — « cloud-init status --wait » avait rendu la main.
# C'est apt-daily, le minuteur de Debian, qui se déclenche au démarrage. Et le
# verrou des LISTES n'est pas couvert par « DPkg::Lock::Timeout », qui ne vaut
# que pour celui de dpkg : l'attente configurée ne s'applique donc pas ici.
#
# On arrête les minuteurs, puis on RÉESSAIE — arrêter une unité n'interrompt
# pas l'apt-get déjà en vol, et cloud-init peut en avoir un autre en route.
prepare_apt() {
run sudo systemctl stop apt-daily.service apt-daily-upgrade.service \
apt-daily.timer apt-daily-upgrade.timer >/dev/null 2>&1 || true
local i
for i in $(seq 1 12); do
if apt_get update; then
return 0
fi
say " verrou apt tenu, nouvel essai dans 15 s (${i}/12)"
sleep 15
done
die "apt update impossible : le verrou des listes reste tenu."
}
install_pve() {
wait_cloud_init
preseed_debconf
# Réparer une transaction laissée à moitié par une exécution précédente :
# sans réponse à grub-pc, dpkg s'arrête au milieu et tout apt suivant
# refuse de travailler. Inoffensif quand rien n'est cassé.
if ! sudo dpkg -C >/dev/null 2>&1; then
say " paquets à moitié configurés : dpkg --configure -a"
run sudo env DEBIAN_FRONTEND=noninteractive dpkg --configure -a \
|| true
fi
# AVANT le premier apt : sur un second passage, le dépôt entreprise posé
# par proxmox-ve ferait échouer « apt update » (401) et rien n'irait plus
# loin — pas même la désactivation, si elle attendait la fin.
disable_enterprise
say "\n---- apt update ----"
[FIX] proxmox : apt-daily tient le verrou au démarrage Trois pannes trouvées en LANÇANT la descente, aucune vue en la relisant — ni par moi, ni par l'attaque adversariale. Le premier « apt update » d'une image cloud échoue sur un verrou qui n'est pas celui qu'on croit. Mesuré une seconde après le premier ssh : E: Could not get lock /var/lib/apt/lists/lock. It is held by process 1026 (apt-get) Ce n'est pas cloud-init — « status --wait » avait rendu la main. C'est apt-daily, le minuteur de Debian, qui se déclenche au démarrage. Et le verrou des LISTES n'est pas couvert par « DPkg::Lock::Timeout », que l'installeur réglait pourtant déjà à 600 s : cette attente ne vaut que pour dpkg. On arrête donc les minuteurs, puis on RÉESSAIE — arrêter une unité n'interrompt pas l'apt-get déjà en vol. Le défaut touchait tout déploiement Proxmox, pas seulement ce test. Le premier étage n'avait pas d'alias ssh. « deploy_qemu.py » en ligne de commande n'écrit pas d'entrée ~/.ssh/config — le menu le fait, la CLI non. La descente aurait attendu son plein délai avant de conclure « jamais joignable » sur une VM qui répondait à son adresse. Elle l'écrit maintenant elle-même, depuis l'adresse résolue, et refuse d'avancer si la VM n'en a pas. Et la réserve de l'hôte est proportionnelle. Quatre gigaoctets sur une machine de soixante, c'était 6 % laissés au système : le jour où les invités touchent vraiment leur mémoire, c'est l'hôte qui part en swap — et la mesure serait celle du swap, pas de l'imbrication. Un huitième, avec le plancher d'avant pour les petites machines. Ce que la descente a établi en trois étages : 392 s, 644 s, 1120 s, soit 1,7 fois par étage. Puis la poignée de main ssh passe de 77 à 1664 secondes au quatrième — vingt fois d'un seul cran. Le coude est là. Et le mur que j'avais pris pour une limite d'imbrication n'en était pas une. La VM qui gelait au quatrième étage avait douze vCPU ; celle-ci en a deux et elle passe, en écrivant. C'était une limite de parallélisme SOUS imbrication — exactement ce que l'algorithme borne, vérifié pour la première fois plutôt que supposé. --- EN --- Three faults found by RUNNING the descent, none seen by reading it — neither by me nor by the adversarial attack. A cloud image's first "apt update" fails on a lock that is not the one you expect. Measured one second after the first ssh: E: Could not get lock /var/lib/apt/lists/lock. It is held by process 1026 (apt-get) It is not cloud-init — "status --wait" had returned. It is apt-daily, Debian's timer, firing at boot. And the LISTS lock is not covered by "DPkg::Lock::Timeout", which the installer already set to 600 s: that wait only applies to dpkg. So we stop the timers, then RETRY — stopping a unit does not interrupt the apt-get already in flight. The defect affected every Proxmox deployment, not just this test. The first level had no ssh alias. "deploy_qemu.py" on the command line does not write a ~/.ssh/config entry — the menu does, the CLI does not. The descent would have waited its full timeout before concluding "never reachable" about a VM answering at its address. It now writes the entry itself, from the resolved address, and refuses to proceed if the VM has none. And the host's reserve is proportional. Four gigabytes on a sixty-gigabyte machine left 6 % to the system: the day the guests really touch their memory, the host swaps — and the measurement would be of swap, not of nesting. One eighth now, keeping the old floor for small machines. What the descent established over three levels: 392 s, 644 s, 1120 s — 1.7x per level. Then the ssh handshake goes from 77 to 1664 seconds at the fourth: twenty times in one step. That is the elbow. And the wall I had taken for a nesting limit was not one. The VM that froze at the fourth level had twelve vCPU; this one has two and it gets through, writing. It was a limit of parallelism UNDER nesting — exactly what the algorithm caps, verified for the first time rather than assumed. Assisted-by: Claude Opus 5 (cherry picked from commit 7f86562cbd8f10017dcb88fe4272efc162cbccbc)
2026-08-27 04:27:50 -04:00
prepare_apt
# Le noyau d'abord, comme l'amont le prescrit : c'est lui qui porte les
# modules dont pve a besoin, et l'installer seul laisse une machine qui
# redémarre proprement même si la suite échoue.
if ! dpkg -s proxmox-default-kernel >/dev/null 2>&1; then
say "\n---- noyau Proxmox ----"
apt_get install proxmox-default-kernel
CHANGED=1
else
say " noyau Proxmox déjà posé"
fi
if ! dpkg -s proxmox-ve >/dev/null 2>&1; then
say "\n---- proxmox-ve, postfix, open-iscsi, chrony ----"
apt_get install proxmox-ve postfix open-iscsi chrony
CHANGED=1
# C'est CETTE installation qui vient de poser le dépôt entreprise :
# le désactiver tout de suite, avant que le ménage ne rappelle apt.
disable_enterprise
else
say " proxmox-ve déjà posé"
fi
}
# --- 6. Ménage --------------------------------------------------------------
# os-prober ajoute au menu d'amorçage les systèmes trouvés sur les disques des
# VM invitées : sur un hyperviseur, c'est une liste de faux départs.
# Le noyau Debian, lui, n'a plus de raison d'être une fois celui de pve en
# place — et laissé par défaut, grub peut y revenir.
cleanup() {
if dpkg -s os-prober >/dev/null 2>&1; then
say " retrait d'os-prober"
apt_get remove os-prober
CHANGED=1
fi
[ "${PVE_KEEP_DEBIAN_KERNEL:-0}" = "1" ] && return 0
# Ne JAMAIS retirer le noyau Debian si celui de Proxmox n'est pas posé :
# la machine ne redémarrerait plus. Vérifié, pas supposé — une étape apt
# peut avoir échoué plus haut sans arrêter le reste.
if ! dpkg -s proxmox-default-kernel >/dev/null 2>&1; then
say " noyau Proxmox absent : le noyau Debian reste en place."
return 0
fi
local metas
# Tout « linux-image-* » SAUF ceux de Proxmox. L'amont écrit
# « linux-image-6.12* », la version de trixie ; le motif large couvre les
# versions suivantes, et l'exclusion protège le noyau qu'on vient de
# poser — le retirer laisserait une VM qui n'amorce plus.
# « db:Status-Status » filtre les paquets RÉELLEMENT installés : dpkg
# connaît aussi ceux qu'il a désinstallés (« config-files »,
# « not-installed »), et les passer à apt donnait « is not installed, so
# not removed » — puis un CHANGED=1 qui réclamait un redémarrage inutile.
metas="$(dpkg-query -W -f '${Package} ${db:Status-Status}\n' \
'linux-image-*' 2>/dev/null \
| awk '$2 == "installed" {print $1}' \
| grep -vE 'pve|proxmox' || true)"
if [ -n "${metas}" ]; then
say " retrait du noyau Debian : $(echo "${metas}" | tr '\n' ' ')"
# shellcheck disable=SC2086
apt_get remove ${metas}
run sudo update-grub 2>/dev/null || true
CHANGED=1
fi
return 0
}
# --- 6bis. Amorçage EFI de secours -----------------------------------------
# Une image cloud amorce par le CHEMIN DE SECOURS de l'UEFI —
# \EFI\BOOT\BOOTX64.EFI — parce qu'aucune entrée NVRAM ne la nomme. Les
# paquets grub de Proxmox y recopient bien leurs binaires, mais PAS le petit
# grub.cfg qui indique où trouver la vraie configuration. GRUB s'arrête alors
# sur son invite de secours « grub> » : ni menu, ni noyau.
#
# Vécu, capture d'écran à l'appui : après le premier redémarrage, la VM brûlait
# 100 % d'un cœur SANS lire une seule fois le disque, et l'écran affichait
# « starting Boot0001 UEFI Misc Device » suivi de « grub> ».
#
# On recopie le stub que Debian a généré pour son propre chemin : il porte
# l'UUID de la racine, donc il fonctionne depuis n'importe quel chargeur.
# « grub-install --removable » ferait la même chose en réécrivant le chargeur ;
# copier un fichier est plus sûr — cela ne touche pas au chemin qui marche.
fix_efi_fallback() {
local esp="${PVE_ESP:-/boot/efi}"
local secours="${esp}/EFI/BOOT"
# sudo sur CHAQUE lecture. /boot/efi est une vfat montée « umask=077 » :
# root seul y entre, et un « [ -d ] » non privilégié y répond FAUX. Ce
# correctif ne faisait donc RIEN, en silence, et la VM retombait sur
# « grub> » au redémarrage suivant — vécu deux fois. Le glob du shell est
# aveugle pour la même raison : il faut énumérer avec sudo.
sudo test -d "${secours}" || return 0
sudo test -e "${secours}/grub.cfg" && return 0
local stub=""
# « || true » : quand aucun stub n'existe, grep ne trouve rien et rend 1
# — avec « set -o pipefail », l'affectation échoue et le script s'arrête
# AVANT d'avoir dit ce qui manque. Attrapé par un test, pas sur la machine
# réelle, où un stub existait et masquait le cas.
stub="$(sudo sh -c "ls ${esp}/EFI/*/grub.cfg 2>/dev/null" \
| grep -v '/EFI/BOOT/grub.cfg' | head -1 || true)"
if [ -z "${stub}" ]; then
say "${Yellow}⚠${Color_Off} aucun grub.cfg à recopier sous ${esp} :" \
"vérifier l'amorçage avant de redémarrer."
return 0
fi
say " amorçage de secours : $(dirname "${stub}" | xargs basename)/grub.cfg" \
"-> EFI/BOOT/"
run sudo cp "${stub}" "${secours}/grub.cfg"
CHANGED=1
}
# --- 7. Déroulé -------------------------------------------------------------
say "${Green}==>${Color_Off} Proxmox VE ${SUITE} sur ${ARCH}"
say "\n---- nom d'hôte et /etc/hosts ----"
fix_hosts
say "\n---- dépôt Proxmox ----"
add_repo
install_pve
say "\n---- ménage ----"
cleanup
say "\n---- amorçage ----"
fix_efi_fallback
IP="$(host_ip || echo localhost)"
if [ "${DRY}" = "1" ]; then
# Ne rien annoncer qui n'ait eu lieu : en dry-run, rien n'a été installé.
say "\n${Yellow}✓${Color_Off} dry-run terminé : rien n'a été changé."
say " Ce qui serait joignable ensuite : https://${IP}:8006"
exit 0
fi
say "\n${Green}✓${Color_Off} Proxmox VE installé."
say " Interface web : ${Green}https://${IP}:8006${Color_Off}"
# Proxmox authentifie par PAM : c'est le root du système qui ouvre l'interface.
# Sur une image cloud il est VERROUILLÉ (« passwd -S root » rend « L »), donc
# l'interface est inutilisable tant qu'on ne lui a pas donné un mot de passe.
# Le dire ici plutôt que de laisser chercher devant un formulaire qui refuse.
if [ "$(sudo passwd -S root 2>/dev/null | awk '{print $2}')" = "L" ]; then
say " Compte : root, ${Yellow}sans mot de passe${Color_Off} —" \
"l'interface le refusera. À faire : ${Green}sudo passwd root${Color_Off}"
else
say " Compte : root (mot de passe du système)"
fi
say " Une VM Proxmox est un hyperviseur DANS une VM : ses propres invités"
say " demandent la virtualisation imbriquée à tous les étages."
if [ "${CHANGED}" = "0" ]; then
say "\n Rien n'a changé : pas de redémarrage."
exit 0
fi
if [ "${PVE_REBOOT:-0}" != "1" ]; then
say "\n${Yellow}⚠${Color_Off} Redémarrage NÉCESSAIRE pour amorcer le" \
"noyau Proxmox : sudo reboot"
exit 0
fi
say "\n---- redémarrage pour amorcer le noyau Proxmox ----"
run sudo systemctl reboot