Aller au contenu
Perfect Homelab [E12] : Migration ZFS de Neo, réplication et HA Manager
  1. Posts/

Perfect Homelab [E12] : Migration ZFS de Neo, réplication et HA Manager

Fabien ALLAMANCHE
Auteur
Fabien ALLAMANCHE
Géomaticien @ Vienne Condrieu Agglomération
Sommaire
Perfect Homelab - Cet article fait partie d'une série.
Partie 12: Cet article
Perfect Homelab

Rappel de l’état à la fin de l’E11
#

À la fin de l’E11, les filets de sécurité sont opérationnels :

graph TB
    subgraph MATRIX["CLUSTER MATRIX"]
        Morpheus["Morpheus
10.10.10.5
ZFS mirror NVMe"] Neo["Neo
10.10.10.6
LVM SSD SATA
⚠️ migration ZFS à venir"] end Oracle["oracle
192.168.0.50
corosync-qnetd
3 votes ✅"] ns1["ns1.dns.allfabox.fr
10.10.10.53
RPi 3B — Primary ✅"] LXC107["LXC 107 — PBS 4.2.1
10.10.10.7 ✅"] LXC130["LXC 130 — Smarthome ✅"] Morpheus <-->|corosync| Neo Morpheus <-->|TCP 5403| Oracle Neo <-->|TCP 5403| Oracle Morpheus --> LXC107 Morpheus --> LXC130 style Morpheus fill:#dbeafe,stroke:#1e40af,stroke-width:2px,color:#000 style Neo fill:#fef3c7,stroke:#b45309,stroke-width:2px,color:#000 style Oracle fill:#dcfce7,stroke:#166534,stroke-width:2px,color:#000 style ns1 fill:#f3e8ff,stroke:#7e22ce,stroke-width:2px,color:#000 style LXC107 fill:#dcfce7,stroke:#166534,stroke-width:2px,color:#000 style LXC130 fill:#dcfce7,stroke:#166534,stroke-width:2px,color:#000
  • QDevice oracle → quorum à 3 votes, cluster stable même si un nœud tombe ✅
  • Technitium ns1 sur RPi (10.10.10.53) → résolution DNS homelab opérationnelle ✅
  • Routes réseau double NAT → oracle atteint le cluster Proxmox ✅
  • Neo toujours en LVM → c’est l’objet de cet épisode

Partie 1 — Réinstallation de Neo en ZFS
#

Prérequis vérifiés avant de commencer
#

✅ QDevice oracle actif → si Neo tombe, Morpheus garde le quorum
✅ PBS mirroré sur Morpheus → 14 groupes, 0 perte de données
✅ LXC Smarthome sur Morpheus → domotique continue de tourner
✅ RPi DNS opérationnel → DNS tient sans LXC 253
flowchart TD
    A["Vérifications préalables
QDevice ✅ | PBS mirroré ✅
DNS RPi ✅ | Smarthome ✅"] B["Dernière synchro PBS
14 groupes — 0 perte de données"] C["pvecm delnode neo
Retrait propre du cluster"] D["Boot ISO Proxmox 9.2
Ventoy — ZFS RAID0 single disk"] E["Installation Proxmox sur Neo
sda: Crucial BX500 931.5 Go
DNS: 10.10.10.53 RPi"] F["pvecm add 10.10.10.5
Réintégration au cluster"] G["pvecm qdevice setup --force
Reconfiguration QDevice"] H["Nettoyage artefacts
LXC et VM fantômes"] I["Neo ZFS opérationnel ✅
rpool: 897 Go disponibles"] A --> B B --> C C --> D D --> E E --> F F --> G G --> H H --> I style A fill:#dbeafe,stroke:#1e40af,stroke-width:2px,color:#000 style B fill:#dbeafe,stroke:#1e40af,stroke-width:2px,color:#000 style C fill:#fef3c7,stroke:#b45309,stroke-width:2px,color:#000 style D fill:#fef3c7,stroke:#b45309,stroke-width:2px,color:#000 style E fill:#fef3c7,stroke:#b45309,stroke-width:2px,color:#000 style F fill:#dbeafe,stroke:#1e40af,stroke-width:2px,color:#000 style G fill:#dbeafe,stroke:#1e40af,stroke-width:2px,color:#000 style H fill:#fef3c7,stroke:#b45309,stroke-width:2px,color:#000 style I fill:#dcfce7,stroke:#166534,stroke-width:2px,color:#000

Dernière synchronisation PBS
#

On s’assure de synchroniser une dernière fois notre datastore PBS.

pct exec 107 -- proxmox-backup-manager sync-job run neo-pbs-sync
# → 14 groups, 0 snapshots nouveaux, TASK OK ✅

Retrait de Neo du cluster
#

# Depuis Morpheus
pvecm delnode neo

Installation Proxmox 9.2 sur Neo (ZFS)
#

Boot sur ISO Proxmox 9.2 via Ventoy, avec les paramètres :

Filesystem : ZFS (RAID0 — single disk)
Disk       : sda (Crucial BX500 931.5 Go)
Hostname   : neo.pve.allfabox.fr
IP         : 10.10.10.6/24
Gateway    : 10.10.10.1
DNS        : 10.10.10.53  ← le RPi !

Résultat ZFS sur Neo
#

rpool : ONLINE, 897 Go disponibles (single SSD SATA)

Réintégration au cluster
#

# Sur Morpheus : récupérer l'empreinte du certificat du cluster
pvecm fingerprint
# → 2A:3F:...:9C
Info : Le fingerprint est l’empreinte du certificat SSL du nœud cible (Morpheus). Proxmox l’exige pour vérifier l’identité du serveur rejoint et écarter toute attaque man-in-the-middle. Récupérez-la sur Morpheus avec pvecm fingerprint, ou laissez Proxmox l’afficher : si vous omettez --fingerprint, la jonction passe en mode interactif et vous demande de confirmer l’empreinte avant de continuer.
# Sur Neo : ajouter Morpheus dans /etc/hosts
echo "10.10.10.5 morpheus.allfabox.lan" >> /etc/hosts

# Rejoindre le cluster avec l'empreinte récupérée
pvecm add 10.10.10.5 --fingerprint 2A:3F:...:9C
# → successfully added node 'Neo' to cluster ✅

Reconfiguration du QDevice sur Neo
#

apt install -y corosync-qdevice
pvecm qdevice setup 192.168.0.50 --force

Nettoyage des anciens artefacts
#

Après réintégration, les anciens LXC et datastores LVM apparaissent en fantômes. Nettoyage :

# Supprimer les configs LXC fantômes
rm /etc/pve/nodes/Neo/lxc/230.conf
rm /etc/pve/nodes/Neo/lxc/253.conf
rm /etc/pve/nodes/Neo/qemu-server/500.conf
rm /etc/pve/nodes/Neo/qemu-server/999.conf

Partie 2 — Stockage ZFS unifié et DNS secondaire
#

Storage ZFS cluster-wide
#

C’est le point le plus important de cet épisode. Mal compris, il bloque toutes les migrations entre nœuds. Bien posé, il rend le cluster homogène et la réplication ZFS triviale.

Après réintégration de Neo, il fallait déclarer son storage ZFS. Deux approches s’offraient à nous, et le choix conditionne toute la suite. Mais avant cela, un mot sur la notion de storage chez Proxmox.

Qu’est-ce qu’un « storage » sous Proxmox ?
#

Sous Proxmox VE, un storage est une abstraction : un emplacement déclaré où Proxmox sait lire et écrire des données. Ce n’est pas le disque physique lui-même, mais une définition logique qui dit à Proxmox « voici un endroit utilisable, voici son type et voici ce qu’on a le droit d’y mettre ».

Chaque storage possède trois caractéristiques essentielles :

Caractéristique Rôle Exemple
ID Le nom logique par lequel on le référence partout datastore, local, local-zfs
Type La technologie de stockage sous-jacente zfspool, lvmthin, dir, nfs, cephfs
Content Les types de données autorisés images (disques VM), rootdir (disques LXC), backup, iso, vztmpl

Toutes les définitions vivent dans un seul fichier, /etc/pve/storage.cfg. Point crucial en cluster : ce fichier est stocké dans le système de fichiers cluster Proxmox (pmxcfs), donc toute modification est automatiquement répliquée sur l’ensemble des nœuds.

graph TB
    CFG["/etc/pve/storage.cfg
(répliqué via pmxcfs)"] subgraph S1["storage « datastore »"] T1["Type: zfspool"] C1["Content: images, rootdir"] end DISK["Disque physique réel
rpool/datastore (ZFS local)"] VM["Disque d'une VM/LXC
datastore:subvol-XXX-disk-0"] CFG --> S1 VM -->|référence l'ID| S1 S1 -->|pointe vers| DISK style CFG fill:#f3e8ff,stroke:#7e22ce,stroke-width:2px,color:#000 style T1 fill:#dbeafe,stroke:#1e40af,stroke-width:2px,color:#000 style C1 fill:#dbeafe,stroke:#1e40af,stroke-width:2px,color:#000 style DISK fill:#dcfce7,stroke:#166534,stroke-width:2px,color:#000 style VM fill:#fef3c7,stroke:#b45309,stroke-width:2px,color:#000
Astuce : Retenez la chaîne de résolution. Une VM ne connaît jamais le chemin physique de son disque ; elle ne connaît que l’ID du storage (datastore:...). Proxmox traduit cet ID, via storage.cfg, vers l’emplacement réel sur le nœud courant. C’est précisément cette indirection qui rend la migration entre nœuds possible.

Les deux approches possibles
#

graph TB
    subgraph MAUVAIS["❌ Approche naïve — un storage par nœud"]
        direction LR
        M1["Morpheus
storage: morpheus-datastore"] N1["Neo
storage: neo-datastore"] M1 -.->|migration
renommage manuel
du disque requis| N1 end subgraph BON["✅ Approche cluster-wide — un seul ID"] direction LR M2["Morpheus
storage: datastore"] N2["Neo
storage: datastore"] M2 -->|migration
référence identique
aucun renommage| N2 end MAUVAIS ~~~ BON style M1 fill:#fee2e2,stroke:#991b1b,stroke-width:2px,color:#000 style N1 fill:#fee2e2,stroke:#991b1b,stroke-width:2px,color:#000 style M2 fill:#dcfce7,stroke:#166534,stroke-width:2px,color:#000 style N2 fill:#dcfce7,stroke:#166534,stroke-width:2px,color:#000

Plutôt que de créer un storage neo-datastore séparé, on adopte la logique d’un storage cluster-wide avec le même nom sur tous les nœuds — comme dans les architectures Proxmox multi-nœuds professionnelles.

L’idée : un seul ID Proxmox datastore, déclaré une fois dans /etc/pve/storage.cfg (fichier répliqué automatiquement sur tout le cluster), et disponible à la fois sur Morpheus et Neo. Sur chaque nœud, cet ID pointe vers le dataset ZFS local rpool/datastore.

Le concept clé : même nom logique, données locales distinctes
#

C’est le point qui prête à confusion. Ce n’est PAS du stockage partagé. Il n’y a aucun disque commun entre les deux nœuds. Chaque nœud écrit sur son propre pool ZFS local — Morpheus sur ses NVMe en mirror, Neo sur son SSD SATA.

graph TB
    subgraph CLUSTER["Cluster Matrix — ID Proxmox unique : « datastore »"]
        direction LR
        subgraph M["Morpheus"]
            MZ["rpool/datastore
NVMe mirror local"] end subgraph N["Neo"] NZ["rpool/datastore
SSD SATA local"] end end APP["Disque d'un LXC/VM
référencé : datastore:subvol-XXX-disk-0"] APP -->|sur Morpheus| MZ APP -->|sur Neo| NZ style MZ fill:#dbeafe,stroke:#1e40af,stroke-width:2px,color:#000 style NZ fill:#fef3c7,stroke:#b45309,stroke-width:2px,color:#000 style APP fill:#f3e8ff,stroke:#7e22ce,stroke-width:2px,color:#000
Attention : Ne confondez pas nom logique partagé et stockage partagé. Ici, les deux nœuds exposent le même ID Proxmox (datastore), mais chacun écrit sur son disque ZFS local. Un LXC sur Neo n’accède pas aux données de Morpheus — c’est la réplication ZFS (configurée plus loin) qui copie les datasets d’un nœud à l’autre.

Mise en œuvre
#

Bonne nouvelle : il n’y a rien à éditer à la main. Le storage datastore existait déjà sur Morpheus (créé lors d’un épisode précédent). Il suffit de créer le dataset ZFS côté Neo, puis d’étendre le storage existant aux deux nœuds avec une seule commande pvesm.

Étape 1 — Créer le dataset ZFS sur Neo. Le storage Proxmox attend de trouver rpool/datastore localement ; il faut donc le créer côté Neo (il existe déjà sur Morpheus) :

# Sur Neo — créer le dataset ZFS local
zfs create rpool/datastore

Étape 2 — Rattacher Neo au storage existant. Une seule commande suffit : pvesm set met à jour la définition du storage pour y ajouter Neo. Pas besoin d’ouvrir un éditeur :

# Depuis n'importe quel nœud — étendre le storage aux deux nœuds
pvesm set datastore --nodes morpheus,neo

Étape 3 — Vérifier. Sur chaque nœud, le storage datastore doit apparaître active. Sur Neo, on attend les ~897 Go du SSD SATA :

# Sur Neo
pvesm status
# Name        Type      Status   Total    Used   Available   %
# datastore   zfspool   active   897 Go   0 B    897 Go      0% ✅

Info : La commande pvesm set écrit elle-même dans /etc/pve/storage.cfg — vous n’éditez jamais ce fichier manuellement. Comme il vit dans le système de fichiers cluster (pmxcfs), la modification est automatiquement répliquée sur tous les nœuds. À titre informatif, voici à quoi ressemble la définition résultante :

# /etc/pve/storage.cfg (généré par pvesm)
zfspool: datastore          # ← un seul ID logique pour tout le cluster
    pool rpool/datastore    # ← le dataset ZFS local, identique sur chaque nœud
    content images,rootdir  # ← disques de VMs (images) et de LXC (rootdir)
    nodes morpheus,neo      # ← les deux nœuds qui exposent ce storage
    sparse 1                # ← allocation fine (thin provisioning) ZFS
Info : Avec cet ID commun, les disques des LXC/VMs sont toujours référencés datastore:subvol-XXX-disk-0, qu’ils soient sur Morpheus ou Neo. Proxmox résout cette référence vers le rpool/datastore local du nœud qui héberge la machine. Résultat : les migrations entre nœuds n’exigent aucun renommage de disque, la réplication ZFS est directe, et la configuration reste parfaitement homogène.

Le vrai objectif : faire circuler les VMs et LXC entre les deux nœuds
#

Voilà toute la raison d’être de cette architecture. Si l’on a réinstallé Neo en ZFS pour rejoindre Morpheus, c’est précisément pour pouvoir déplacer une VM ou un LXC d’un nœud à l’autre, à la demande ou automatiquement en cas de panne.

Le storage datastore partagé entre les deux nœuds est le socle qui rend cela possible. Concrètement, ce que l’on veut, c’est que l’image disque d’une VM ou d’un LXC existe des deux côtés : sur le ZFS de Morpheus et sur le ZFS de Neo. Comme les deux nœuds parlent ZFS et exposent le même ID datastore, Proxmox peut répliquer ces images disque d’un pool à l’autre, puis basculer la machine sur le nœud qui possède déjà sa copie.

graph LR
    subgraph M["Morpheus (nœud actif)"]
        VMM["LXC 130 — Smarthome
datastore:subvol-130-disk-0"] end subgraph N["Neo (nœud de secours)"] VMN["Copie répliquée
datastore:subvol-130-disk-0"] end UP["LXC 130 redémarré sur Neo ✅"] VMM ==>|réplication ZFS
snapshots incrémentaux
toutes les X min| VMN VMN -.->|en cas de panne
de Morpheus| UP style VMM fill:#dbeafe,stroke:#1e40af,stroke-width:2px,color:#000 style VMN fill:#fef3c7,stroke:#b45309,stroke-width:2px,color:#000 style UP fill:#dcfce7,stroke:#166534,stroke-width:2px,color:#000

Sans cet ID commun, rien de tout cela ne fonctionne :

  • Migration à froid / à chaud : déplacer manuellement un LXC de Morpheus vers Neo pour faire une maintenance, sans toucher à sa configuration.
  • Réplication ZFS native : Proxmox envoie périodiquement les snapshots ZFS incrémentaux de datastore vers l’autre nœud — seuls les blocs modifiés transitent.
  • HA Manager : si Morpheus tombe, le HA Manager redémarre automatiquement les machines sur Neo, à partir de la dernière copie répliquée.
Architecture : C’est ici que réside toute la force d’avoir deux nœuds en ZFS. ZFS sait produire des snapshots incrémentaux et les envoyer (zfs send/zfs receive) de façon efficace. Couplé au storage datastore partagé, cela transforme deux serveurs indépendants en un cluster capable de faire basculer une charge d’un nœud à l’autre — la bascule (réplication + HA) fait l’objet des sections suivantes.

LXC 253 — Technitium DNS secondaire
#

Avant de créer le LXC, il faut s’assurer que le point de montage (mountpoint) du dataset ZFS sur Neo est aligné sur celui de Morpheus (/datastore).

Info : Le mountpoint est le répertoire du système de fichiers où ZFS « branche » le dataset. Par défaut, ZFS hérite du nom du pool et monte rpool/datastore sous /rpool/datastore. Or sur Morpheus, ce même dataset est monté sous /datastore. Si les deux nœuds n’utilisent pas le même chemin, les disques de LXC/VMs (rootfs) ne se retrouveront pas au même endroit après une réplication ou une migration — d’où l’importance d’aligner les deux nœuds.

Étape 1 — Vérifier le mountpoint actuel sur Neo :

# Sur Neo — afficher le point de montage du dataset
zfs get mountpoint rpool/datastore
# NAME              PROPERTY    VALUE              SOURCE
# rpool/datastore   mountpoint  /rpool/datastore   default   ← à corriger

La colonne SOURCE indique default : ZFS a choisi le chemin tout seul (/rpool/datastore), il ne correspond pas à Morpheus.

Étape 2 — Forcer le mountpoint sur /datastore pour l’aligner sur Morpheus :

# Sur Neo — fixer explicitement le point de montage
zfs set mountpoint=/datastore rpool/datastore

ZFS démonte puis remonte immédiatement le dataset au nouvel emplacement — aucun redémarrage requis. La valeur passe alors en SOURCE local, c’est-à-dire définie manuellement et non plus héritée.

Étape 3 — Confirmer l’alignement :

# Sur Neo — vérifier que le chemin est désormais /datastore
zfs get mountpoint rpool/datastore
# NAME              PROPERTY    VALUE         SOURCE
# rpool/datastore   mountpoint  /datastore    local   ✅

Les deux nœuds montent maintenant leur dataset rpool/datastore sous le même chemin /datastore. La réplication et les migrations de LXC/VMs retrouveront leurs disques à l’identique des deux côtés.

Le template est accessible via le NFS iso-neo monté depuis Morpheus. Le chemin correct depuis Neo est /mnt/pve/iso-neo/template/cache/ :

pct create 253 /mnt/pve/iso-neo/template/cache/debian-13-standard_13.1-2_amd64.tar.zst \
  --hostname ns2 \
  --ostype debian \
  --arch amd64 \
  --cores 1 \
  --memory 512 \
  --swap 512 \
  --rootfs datastore:8 \
  --net0 name=eth0,bridge=vmbr0,firewall=1,gw=10.10.20.1,ip=10.10.20.53/24,tag=20,type=veth \
  --onboot 1 \
  --startup order=1 \
  --unprivileged 1 \
  --tags "prod;dns" \
  --password

pct set 253 --features nesting=1
pct start 253

Installation de Technitium sur ns2 :

pct exec 253 -- bash -c "apt update && apt install -y curl && \
  curl -sSL https://download.technitium.com/dns/install.sh | bash"

Rejoindre le cluster Technitium
#

Depuis l’interface de ns2 (http://10.10.20.53:5380) :

Administration → Cluster → Join Cluster
Secondary Node IP  : 10.10.20.53
Primary Node URL   : https://ns1.dns.allfabox.fr:53443/
Primary Node IP    : 10.10.10.53
Certificate        : Ignore Certificate Validation Errors
Username           : admin
Password           : (mot de passe ns1)

ns2 rejoint le cluster et se synchronise automatiquement avec ns1. ✅

État du cluster après migration Neo
#

pvecm status
Name           : MATRIX
Expected votes : 3
Total votes    : 3
Flags          : Quorate Qdevice

Morpheus  10.10.10.5  1 vote  A,V,NMW ✅
Neo       10.10.10.6  1 vote  A,V,NMW ✅
Qdevice   oracle      1 vote          ✅
graph TB
    subgraph MorpheusG["Morpheus — nœud principal"]
        MorpheusNode["Morpheus
10.10.10.5
ZFS mirror 2x NVMe
storage: datastore"] LXC107["LXC 107 — PBS 4.2.1
10.10.10.7"] LXC130["LXC 130 — Smarthome"] end subgraph NeoG["Neo — nœud secondaire"] NeoNode["Neo
10.10.10.6
ZFS single SSD 897 Go
storage: datastore"] LXC253["LXC 253 — ns2
10.10.20.53"] end QDevice["oracle
192.168.0.50
corosync-qnetd
VM Freebox Ultra"] subgraph DNSCluster["DNS Cluster Technitium"] ns1["ns1.dns.allfabox.fr
10.10.10.53 — RPi 3B
Primary ✅"] ns2["ns2.dns.allfabox.fr
10.10.20.53 — LXC 253
Secondary ✅"] end MorpheusNode <-->|corosync| NeoNode MorpheusNode <--> QDevice NeoNode <--> QDevice MorpheusNode --> LXC107 MorpheusNode --> LXC130 NeoNode --> LXC253 LXC253 -.- ns2 ns1 <-->|synchro cluster| ns2 style MorpheusNode fill:#dbeafe,stroke:#1e40af,stroke-width:2px,color:#000 style NeoNode fill:#dbeafe,stroke:#1e40af,stroke-width:2px,color:#000 style QDevice fill:#fef3c7,stroke:#b45309,stroke-width:2px,color:#000 style LXC107 fill:#dcfce7,stroke:#166534,stroke-width:2px,color:#000 style LXC130 fill:#dcfce7,stroke:#166534,stroke-width:2px,color:#000 style LXC253 fill:#dcfce7,stroke:#166534,stroke-width:2px,color:#000 style ns1 fill:#f3e8ff,stroke:#7e22ce,stroke-width:2px,color:#000 style ns2 fill:#f3e8ff,stroke:#7e22ce,stroke-width:2px,color:#000

Post-installation
#

Durcissement SSH sur Neo
#

Après réinstallation, on applique une configuration SSH durcie. Deux points critiques pour la compatibilité Proxmox :

  • PermitRootLogin prohibit-password — root autorisé par clé uniquement (nécessaire pour les migrations, la réplication ZFS et les opérations pvecm entre nœuds)
  • AllowUsers allfab root — root doit être explicitement dans la liste

Attention : PermitRootLogin no + AllowUsers allfab sans root cassera les migrations live, la réplication ZFS et toutes les opérations inter-nœuds de Proxmox.

cat > /etc/ssh/sshd_config << 'EOF'
Port 22
ListenAddress 0.0.0.0
Protocol 2

HostKey /etc/ssh/ssh_host_ed25519_key
AuthorizedKeysFile .ssh/authorized_keys

PubkeyAuthentication yes
AuthenticationMethods publickey

PermitRootLogin prohibit-password

ClientAliveInterval 60
ClientAliveCountMax 100
Compression delayed

SyslogFacility AUTH
LogLevel INFO

MaxAuthTries 3
MaxSessions 3
MaxStartups 5:30:20

AllowUsers allfab root

LoginGraceTime 30

PasswordAuthentication no
PermitEmptyPasswords no
StrictModes yes

MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,umac-128-etm@openssh.com
Ciphers aes256-ctr,aes128-gcm@openssh.com,aes128-ctr,aes192-ctr,aes256-gcm@openssh.com,chacha20-poly1305@openssh.com
KexAlgorithms diffie-hellman-group18-sha512,curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha256,diffie-hellman-group16-sha512

IgnoreRhosts yes
HostbasedAuthentication no
ChallengeResponseAuthentication no
KerberosAuthentication no
GSSAPIAuthentication no
UsePAM yes

X11Forwarding no
PrintMotd no
TCPKeepAlive no

AcceptEnv LANG LC_*
Subsystem sftp internal-sftp
EOF

# Vérifier la syntaxe avant de recharger
sshd -t && echo "Config OK" && systemctl restart ssh

Nettoyage des références à l’ancien PBS de Neo
#

Maintenant que Neo est réinstallé en ZFS et que PBS tourne dans le LXC 107 sur Morpheus, il faut supprimer toutes les références à l’ancien PBS bare metal de Neo.

pct exec 107 -- bash

# Supprimer le sync job
proxmox-backup-manager sync-job remove neo-pbs-sync

# Supprimer le remote
proxmox-backup-manager remote remove neo-pbs

# Vérifier
proxmox-backup-manager sync-job list
proxmox-backup-manager remote list
# Depuis Morpheus — supprimer le storage PVE
pvesm remove local-lvm-backup

L’ancien PBS de Neo n’a plus aucune référence dans l’infrastructure. ✅


Partie 3 — DNS zone allfabox.fr et Split Horizon
#

Création de la zone allfabox.fr sur ns1
#

Dans l’interface Technitium de ns1 (http://10.10.10.53:5380) :

Zones → Add Zone
Zone Name              : allfabox.fr
Type                   : Primary Zone
Catalog Zone           : cluster-catalog.dns.allfabox.fr
Zone Serial            : Use SOA Serial Date Scheme ✅

Configuration de l’app Split Horizon
#

Apps → Split Horizon → Config
{
    "enableAddressTranslation": true,
    "domainGroupMap": {},
    "networkGroupMap": {},
    "networks": {
        "unifi": [
            "10.10.10.0/24",
            "10.10.20.0/24",
            "10.10.30.0/24",
            "10.10.70.0/24",
            "192.168.0.100/32",
            "192.168.0.254/32"
        ]
    },
    "groups": []
}

Enregistrements APP Split Horizon
#

Tous les enregistrements utilisent le même template :

{
    "unifi": ["10.99.99.10"],
    "0.0.0.0/0": ["82.66.24.30"]
}

Liste des enregistrements créés :

@              APP  SplitHorizon.SimpleAddress
*              APP  SplitHorizon.SimpleAddress
dns            APP  SplitHorizon.SimpleAddress
*.dns          APP  SplitHorizon.SimpleAddress
home           APP  SplitHorizon.SimpleAddress
*.home         APP  SplitHorizon.SimpleAddress
garage         APP  SplitHorizon.SimpleAddress
*.garage       APP  SplitHorizon.SimpleAddress
scaleway       APP  SplitHorizon.SimpleAddress
*.scaleway     APP  SplitHorizon.SimpleAddress
garmin         APP  SplitHorizon.SimpleAddress
*.garmin       APP  SplitHorizon.SimpleAddress
hetzner        APP  SplitHorizon.SimpleAddress
*.hetzner      APP  SplitHorizon.SimpleAddress
perfecthomelab CNAME allfab.github.io

Validation du Split Horizon
#

# Depuis morpheus (réseau unifi) → doit retourner 10.99.99.10
dig @10.10.10.53 allfabox.fr
# → 10.99.99.10 ✅

# Depuis l'extérieur → doit retourner 82.66.24.30
dig @1.1.1.1 allfabox.fr
# → 82.66.24.30 ✅

Propagation DNS sur l’infrastructure
#

morpheus     → DNS 10.10.10.53 / 10.10.20.53 ✅
neo          → DNS 10.10.10.53 / 10.10.20.53 ✅
LXC (tous)   → héritent de l'hôte ✅
UCG VLANs    → DNS 10.10.10.53 / 10.10.20.53 ✅
oracle       → DNS via netplan (routes statiques) ✅

Désactivation de ns1 Freebox
#

Une fois la migration validée, l’ancien serveur DNS Freebox (192.168.0.153) est désactivé. ✅


Partie 4 — Réplication ZFS et HA Manager
#

Politique de réplication
#

La réplication Proxmox utilise zfs send/receive pour synchroniser les disques des LXC vers neo. Elle ne réplique que les datasets ZFS — les bind mounts vers les disques hôtes (mergerfs, tank, etc.) ne sont pas répliqués.

Après analyse des mountpoints de chaque LXC, seuls 3 LXC sont candidats à une réplication utile :

ct:110 - frontend  → disque racine uniquement (config Traefik/Authelia)
ct:120 - elephant  → disque racine uniquement (config PostgreSQL)
ct:130 - smarthome → disque racine + données HA

Les autres LXC (142 Nextcloud, 143 Immich, 150 Webapps, etc.) ont tous des bind mounts vers des données volumineuses non réplicables — le job PBS hebdomadaire est plus adapté pour eux.

Configuration des jobs de réplication
#

# LXC 130 - smarthome (toutes les 2h)
pvesr create-local-job 130-0 neo --schedule '*/2:00'

# LXC 110 - frontend (1x/jour à 2h)
# Via l'UI : schedule 02:00

# LXC 120 - elephant (toutes les 2h)
# Via l'UI : schedule */2:00

Vérification :

pvesr list
JobID   Target    Schedule   Enabled
110-0   local/neo    02:00   yes
120-0   local/neo   */2:00   yes
130-0   local/neo   */2:00   yes

Activation du HA Manager
#

Important : activer la HA sur un LXC avant que sa première réplication soit terminée est risqué. Attendre que pvesr status affiche OK pour le LXC concerné.

ha-manager add ct:130 --state started --max_restart 1 --max_relocate 1
ha-manager add ct:110 --state started --max_restart 1 --max_relocate 1
ha-manager add ct:120 --state started --max_restart 1 --max_relocate 1

Test de bascule
#

# Mettre morpheus en maintenance
ha-manager crm-command node-maintenance enable morpheus

# Surveiller la bascule
ha-manager status
# → service ct:130 (neo, started) ✅

# Remettre morpheus en service
ha-manager crm-command node-maintenance disable morpheus

# Vérifier le failback automatique
ha-manager status
# → service ct:130 (morpheus, started) ✅

La bascule et le retour automatique fonctionnent parfaitement. Home Assistant reste accessible pendant toute la durée du test.

État final du HA Manager
#

ha-manager status
quorum      : OK
fencing     : armed (CRM watchdog active)
lrm morpheus: active, watchdog active
lrm neo     : idle, watchdog standby

ct:110 (morpheus, started) ✅  frontend
ct:120 (morpheus, started) ✅  elephant (PostgreSQL)
ct:130 (morpheus, started) ✅  smarthome (Home Assistant)

Architecture finale du cluster MATRIX
#

graph TB
    subgraph MATRIX["CLUSTER MATRIX — HA opérationnel"]
        subgraph MorpheusG["Morpheus — nœud principal"]
            MorpheusNode["Morpheus
10.10.10.5
ZFS mirror 2x NVMe"] LXC107["LXC 107 — PBS
10.10.10.7"] LXC110["LXC 110 — Frontend HA
Traefik/Authelia"] LXC120["LXC 120 — Elephant HA
PostgreSQL/PostGIS"] LXC130["LXC 130 — Smarthome HA
Home Assistant"] end subgraph NeoG["Neo — nœud secondaire"] NeoNode["Neo
10.10.10.6
ZFS single SSD 897 Go"] LXC253["LXC 253 — ns2
10.10.20.53"] end Oracle["oracle
192.168.0.50
QDevice VM Freebox"] end subgraph DNSCluster["DNS Cluster Technitium"] ns1["ns1.dns.allfabox.fr
10.10.10.53 — RPi 3B"] ns2["ns2.dns.allfabox.fr
10.10.20.53 — LXC 253"] end MorpheusNode <-->|corosync + réplication ZFS| NeoNode MorpheusNode <-->|TCP 5403| Oracle NeoNode <-->|TCP 5403| Oracle MorpheusNode --> LXC107 MorpheusNode --> LXC110 MorpheusNode --> LXC120 MorpheusNode --> LXC130 NeoNode --> LXC253 LXC253 -.- ns2 ns1 <-->|synchro cluster| ns2 style MorpheusNode fill:#dbeafe,stroke:#1e40af,stroke-width:2px,color:#000 style NeoNode fill:#dbeafe,stroke:#1e40af,stroke-width:2px,color:#000 style Oracle fill:#fef3c7,stroke:#b45309,stroke-width:2px,color:#000 style LXC107 fill:#dcfce7,stroke:#166534,stroke-width:2px,color:#000 style LXC110 fill:#dcfce7,stroke:#166534,stroke-width:2px,color:#000 style LXC120 fill:#dcfce7,stroke:#166534,stroke-width:2px,color:#000 style LXC130 fill:#dcfce7,stroke:#166534,stroke-width:2px,color:#000 style LXC253 fill:#dcfce7,stroke:#166534,stroke-width:2px,color:#000 style ns1 fill:#f3e8ff,stroke:#7e22ce,stroke-width:2px,color:#000 style ns2 fill:#f3e8ff,stroke:#7e22ce,stroke-width:2px,color:#000

Bilan : est-ce vraiment de la HA ?
#

Oui, et le test le confirme. En cas de panne de morpheus :

morpheus tombe
    ↓ ~30 secondes (détection corosync + QDevice)
HA Manager bascule ct:110, ct:120, ct:130 sur neo
    ↓ ~2 minutes
Traefik, PostgreSQL et Home Assistant opérationnels sur neo 😴
Critère Ce cluster Enterprise
Bascule automatique
RTO ~2-3 min ~1 min
RPO ~2h (réplication) ~0
Coût 0 € $$$

Pour un homelab domotique, le rapport qualité/complexité/coût est imbattable.


Ce qui reste optionnel
#

  1. Scaleway S3 — reconfigurer le backup offsite
  2. Réplication PBSrpool/backups vers neo (données de backup)
  3. DNSSEC sur la zone allfabox.fr
  4. Restriction firewall — limiter la règle Oracle QDevice au port TCP 5403 uniquement
Perfect Homelab - Cet article fait partie d'une série.
Partie 12: Cet article

Articles connexes