Aller au contenu
Perfect Homelab [E13] : Cluster DNS Technitium — deux instances redondantes (RPi + LXC)
  1. Posts/

Perfect Homelab [E13] : Cluster DNS Technitium — deux instances redondantes (RPi + LXC)

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

Perfect Homelab

Introduction
#

Le DNS, c’est l’annuaire téléphonique de notre réseau. Quand il tombe, tout tombe : plus de résolution de noms, plus d’accès aux services par leur nom de domaine, et souvent plus d’accès Internet du tout. Dans un homelab qui héberge une trentaine de services derrière des noms de domaine internes, un DNS qui flanche transforme une soirée détente en session de dépannage.

Avant d’en arriver là, j’ai testé à peu près tout ce que l’écosystème « tout-en-un » propose. Pi-hole d’abord, pour son blocage publicitaire réputé. AdGuard Home ensuite, plus moderne et plus complet côté filtrage. Puis dnsmasq, léger et efficace, mais dont la configuration se fait fichier par fichier. Je n’ai volontairement pas touché à Bind9 : il reste la référence, mais tout se configure à la main dans des fichiers de zone à la syntaxe… disons austère. Je voulais quelque chose de plus ergonomique.

J’ai même — histoire de rire — installé un Windows Server 2025 avec sa console de gestion DNS graphique, juste pour voir. Spoiler : ce n’était pas la réponse à mes prières pour un homelab Linux.

Ce qui m’a convaincu avec Technitium DNS Server, c’est le trio gagnant : installation en une commande, interface web réellement ergonomique, et surtout la capacité à mettre deux instances en cluster. C’est exactement ce que nous allons construire ici.

Dans cet article, nous allons déployer deux serveurs DNS Technitium redondants : ns1 sur un Raspberry Pi 3 Model B posé dans le réseau 010-SERVERS, et ns2 dans un conteneur LXC Debian 13 sur le nœud Proxmox Neo. Les deux nœuds se synchronisent automatiquement : nous configurons une zone une fois, elle apparaît sur les deux. Si l’un tombe, l’autre prend le relais sans que nos clients ne s’en aperçoivent.

Info : Cet article s’appuie sur la version Technitium DNS Server 15.2, installée via le script officiel. Les captures d’écran et chemins d’interface correspondent à cette version. Les épisodes [E11] et [E12] avaient posé les bases (ns1 sur RPi, migration ZFS de Neo) — nous consolidons ici le cluster complet.

Table des matières
#


Architecture réseau
#

Nos deux serveurs DNS vivent dans deux VLANs différents. Ce n’est pas un hasard : répartir la redondance sur deux segments et deux matériels distincts, c’est éviter qu’une seule panne (un switch, un nœud Proxmox) ne prive tout le réseau de résolution.
Nœud Réseau / VLAN Adresse IP Matériel Rôle
ns1 010-SERVERS (VLAN 10) 10.10.10.53 Raspberry Pi 3B v1.2 Nœud primaire
ns2 020-VM-LXC (VLAN 20) 10.10.20.53 LXC Debian 13 sur Neo Nœud secondaire

Le choix des adresses en .53 est un clin d’œil : 53 est le port historique du DNS. Cela rend l’inventaire réseau immédiatement lisible.

Architecture : ns1 tourne sur du matériel physique dédié (RPi), alimenté indépendamment du cluster Proxmox. Même si le cluster Perfect-Homelab est entièrement à l’arrêt (maintenance, coupure), ns1 continue de résoudre les noms. C’est notre filet de sécurité DNS.

Flux réseau typique d’une requête cliente :

  1. Un client du homelab interroge son DNS primaire 10.10.10.53 (ns1).
  2. ns1 répond depuis sa zone locale allfabox.fr ou depuis son cache.
  3. Si la réponse n’est pas locale, ns1 fait suivre (forward) vers un résolveur amont.
  4. Si ns1 est injoignable, le client bascule sur son DNS secondaire 10.10.20.53 (ns2).
  5. ns2, synchronisé avec ns1, répond de manière identique.

Vue d’ensemble de l’architecture
#

Un seul diagramme pour visualiser les deux nœuds, leur synchronisation et le trajet des requêtes clientes.
graph TB
    subgraph Clients["Clients du homelab"]
        C1["Postes & serveurs
VLAN 10 / 20 / 30…"] end subgraph DNSCluster["Cluster DNS Technitium"] NS1["ns1.dns.allfabox.fr
10.10.10.53
RPi 3B — Primary"] NS2["ns2.dns.allfabox.fr
10.10.20.53
LXC Debian 13 — Secondary"] end UP["Résolveurs amont
DoH / DoT"] C1 -->|"DNS primaire :53"| NS1 C1 -.->|"Fallback :53"| NS2 NS1 <-->|"Synchro cluster
zones + config"| NS2 NS1 -->|Forward| UP NS2 -->|Forward| UP style NS1 fill:#065f46,stroke:#34d399,stroke-width:2px,color:#fff style NS2 fill:#1e3a8a,stroke:#60a5fa,stroke-width:2px,color:#fff style C1 fill:#4c1d95,stroke:#a78bfa,stroke-width:2px,color:#fff style UP fill:#4b5563,stroke:#9ca3af,stroke-width:2px,color:#fff
Service Rôle Port(s) Plateforme
Technitium ns1 Serveur DNS primaire + interface d’admin 53 (DNS), 5380 (web) Raspberry Pi OS
Technitium ns2 Serveur DNS secondaire (cluster) 53 (DNS), 5380 (web) Debian 13 (LXC)

Le flux de synchronisation entre les deux nœuds, une fois le cluster monté :

sequenceDiagram
    participant Admin
    participant NS1 as ns1 (Primary)
    participant NS2 as ns2 (Secondary)
    Admin->>NS1: Crée / modifie une zone
    NS1->>NS1: Enregistre la modification
    NS1-->>NS2: Réplique la zone et la config
    Note over NS2: ns2 est à jour automatiquement
    Admin->>NS2: Ouvre l'interface web
    NS2-->>Admin: Affiche la même zone

Prérequis techniques
#

Info : Technitium DNS Server tourne sur .NET et est distribué pour Linux, Windows, macOS et Raspberry Pi. Le script d’installation gère toutes les dépendances, y compris le runtime .NET.

Nous aurons besoin de :

  • Un Raspberry Pi 3 Model B (ou plus récent) sous Raspberry Pi OS 64 bits à jour
  • Un nœud Proxmox VE capable de créer un conteneur LXC (ici : Neo)
  • Un template Debian 13 disponible dans notre stockage Proxmox
  • Un accès root (ou sudo) sur les deux machines
  • Deux adresses IP fixes réservées : 10.10.10.53 et 10.10.20.53

Compétences mobilisées :

DNS
Proxmox
LXC
Linux
Réseau / VLAN
Raspberry Pi

Configuration minimale par nœud :

Ressource ns1 (RPi 3B) ns2 (LXC)
CPU 4 cœurs ARM (1,2 GHz) 1 vCPU
RAM 1 Go 512 Mo
Disque 16 Go (carte SD) 8 Go
OS Raspberry Pi OS 64 bits Debian 13
Astuce : Un Raspberry Pi 3B est largement suffisant pour un DNS de homelab. La résolution DNS est peu gourmande, et Technitium met en cache les réponses. La carte SD est le maillon faible : privilégions une carte de qualité (endurance) ou, mieux, un boot sur SSD USB.

Préparation de ns1 — Raspberry Pi 3B
#

On commence par le nœud le plus important : le primaire physique. L’objectif est un système propre, à jour, avec une IP fixe et le bon hostname.

Nous nous connectons en SSH sur le Raspberry Pi, puis nous mettons le système à jour :

sudo apt update && sudo apt full-upgrade -y

Nous définissons le hostname ns1 et corrigeons le fichier /etc/hosts :

# Nomme la machine ns1
sudo hostnamectl set-hostname ns1

# Remplace l'ancien nom d'hôte dans /etc/hosts
sudo sed -i 's/raspberrypi/ns1/g' /etc/hosts

Nous nous assurons que l’adresse 10.10.10.53 est bien fixe. Le plus robuste est de la réserver côté DHCP (bail statique sur l’adresse MAC du RPi) : le Pi obtient toujours la même IP sans configuration locale fragile. Si nous préférons une IP statique locale, nous la configurons selon notre distribution (dhcpcd.conf ou NetworkManager selon la version de Raspberry Pi OS).

Attention : Un serveur DNS doit avoir une adresse IP stable. Si son IP change, tous les clients qui le pointent en dur perdent la résolution. Réservation DHCP ou IP statique, mais jamais une IP dynamique flottante.

Nous vérifions enfin que le port 53 n’est pas déjà occupé par un résolveur local (systemd-resolved par exemple) :

sudo ss -tulpn | grep ':53'

Si systemd-resolved écoute sur le port 53, il faudra le désactiver ou le reconfigurer avant d’installer Technitium — nous y reviendrons dans le Troubleshooting.

Astuce : Bonne nouvelle, en partant d’une image officielle Raspberry Pi OS (flashée avec Raspberry Pi Imager) pour ns1, et de l’image Debian 13 du template LXC Proxmox pour ns2, le port 53 n’est pas occupé par défaut. Ces distributions n’activent pas le résolveur stub de systemd-resolved sur le port 53, contrairement à Ubuntu où c’est le comportement par défaut. La vérification ss -tulpn | grep ':53' ci-dessus reste néanmoins le bon réflexe pour confirmer que le champ est libre avant l’installation.

Préparation de ns2 — LXC Debian 13 sur Proxmox
#

Le nœud secondaire vit dans un conteneur LXC léger sur le nœud Proxmox Neo. Un conteneur, c’est quelques secondes de création, une empreinte mémoire minime et des snapshots faciles.

Depuis le shell du nœud Proxmox Neo, nous créons le conteneur 253 :

pct create 253 iso-morpheus:vztmpl/debian-13-standard_13.6-1_amd64.tar.zst \
  --hostname ns2 \
  --net0 name=eth0,bridge=vmbr0,ip=10.10.20.53/24,gw=10.10.20.1,tag=20 \
  --storage datastore \
  --rootfs datastore:8 \
  --memory 512 \
  --cores 1 \
  --unprivileged 0 \
  --onboot 1 \
  --tags prod,ns2 \
  --features nesting=1 \
  --password

Décryptons les options clés :

Option Rôle
--hostname ns2 Nom d’hôte du conteneur
--net0 …,ip=10.10.20.53/24,gw=10.10.20.1,tag=20 IP fixe dans le VLAN 20 (tag 802.1Q)
--rootfs datastore:8 Disque racine de 8 Go
--memory 512 --cores 1 512 Mo de RAM, 1 vCPU
--unprivileged 0 Conteneur privilégié
--onboot 1 Démarre automatiquement avec le nœud
--features nesting=1 Autorise l’imbrication (utile pour .NET / cgroups)
--password Demande interactivement le mot de passe root
Attention : --unprivileged 0 crée un conteneur privilégié : le root du conteneur correspond au root de l’hôte. C’est plus simple pour un service système comme un DNS, mais cela réduit l’isolation. Pour un serveur exposé, préférons un conteneur non-privilégié avec mapping UID/GID. Ici, ns2 n’est joignable que sur le réseau interne.
Info : Le tag tag=20 place l’interface directement dans le VLAN 20 au niveau du bridge Proxmox. Assurons-nous que vmbr0 est bien configuré en VLAN-aware et que le VLAN 20 est trunké jusqu’au nœud Neo.

Nous démarrons le conteneur et ouvrons une console :

pct start 253
pct enter 253

Une fois dans le conteneur, nous le mettons à jour et installons curl :

apt update && apt full-upgrade -y
apt install -y curl

Installation de Technitium DNS
#

C’est ici que Technitium montre sa première force : une seule commande, sur les deux machines, quel que soit le matériel. Le script détecte l’architecture (ARM sur le RPi, x86-64 sur le LXC) et installe le runtime .NET adéquat.

Sur ns1 (Raspberry Pi) et sur ns2 (LXC), nous lançons la même commande :

curl -sSL https://download.technitium.com/dns/install.sh | sudo bash

Le script télécharge Technitium DNS Server 15.2, installe .NET si besoin, crée un service systemd et le démarre. En fin d’exécution, il affiche l’URL d’administration.

À la fin de l’installation, nous vérifions que le service tourne :

systemctl status dns

Nous devons voir le service active (running).

graph TD
    A["curl … install.sh | sudo bash"] --> B{Détection
architecture} B -->|ARM64| C["Installe .NET ARM"] B -->|x86-64| D["Installe .NET x64"] C --> E["Télécharge Technitium 15.2"] D --> E E --> F["Crée le service systemd 'dns'"] F --> G["Démarre et écoute :53 + :5380"] style A fill:#1e3a8a,stroke:#60a5fa,stroke-width:2px,color:#fff style G fill:#14532d,stroke:#4ade80,stroke-width:2px,color:#fff

Nous ouvrons maintenant l’interface web de chaque nœud dans notre navigateur :

  • ns1 : http://10.10.10.53:5380
  • ns2 : http://10.10.20.53:5380

Au premier lancement, Technitium nous invite à créer le compte administrateur (admin) et à définir son mot de passe.

Écran de création du compte admin Technitium
Placeholder — Premier lancement : création du compte administrateur sur ns1.
Astuce : Utilisons le même mot de passe admin sur les deux nœuds au début, cela simplifie la mise en cluster. Nous pourrons les différencier ensuite si nous le souhaitons.

Nommer chaque serveur
#

Avant de créer le cluster, nous donnons à chaque nœud son nom de domaine complet. Sur ns1, nous allons dans Settings → General :

DNS Server Domain Name : ns1.dns.allfabox.fr

Et sur ns2 :

DNS Server Domain Name : ns2.dns.allfabox.fr
Réglage du nom de domaine du serveur DNS
Placeholder — Settings → General : nom de domaine de chaque nœud.

Mise en cluster des deux instances
#

C’est le cœur de l’article. Technitium propose un mécanisme de cluster natif où le nœud primaire réplique ses zones et une partie de sa configuration vers les nœuds secondaires. Une modification faite une fois se propage partout.

Le principe : ns1 est le primaire, ns2 le secondaire. Nous déclarons le cluster sur le primaire, puis nous y rattachons le secondaire.

Sur ns1 (http://10.10.10.53:5380), nous nous rendons dans Settings → Cluster (ou Administration → Cluster selon la disposition de la version 15.2) et renseignons :

Cluster Domain  : dns.allfabox.fr
Primary Node    : ns1.dns.allfabox.fr  (10.10.10.53)

Nous générons ensuite le jeton de cluster (cluster token) sur le primaire — c’est le secret qui autorise un secondaire à rejoindre le groupe.

Configuration du nœud primaire du cluster
Placeholder — ns1 : déclaration du cluster et génération du jeton.

Sur ns2 (http://10.10.20.53:5380), nous rejoignons le cluster en pointant vers le primaire :

Cluster Domain     : dns.allfabox.fr
Primary Node IP    : 10.10.10.53
Cluster Token      : <jeton copié depuis ns1>

Nous validons. ns2 contacte ns1, s’authentifie avec le jeton, et récupère la configuration et les zones existantes.

ns2 rejoint le cluster
Placeholder — ns2 : jonction au cluster via le jeton du primaire.

Le déroulé complet de la mise en cluster :

sequenceDiagram
    participant Admin
    participant NS1 as ns1 (Primary · 10.10.10.53)
    participant NS2 as ns2 (Secondary · 10.10.20.53)
    Admin->>NS1: Déclare le cluster dns.allfabox.fr
    NS1-->>Admin: Génère le cluster token
    Admin->>NS2: Rejoint le cluster (IP primaire + token)
    NS2->>NS1: Authentification via token
    NS1-->>NS2: Réplique config + zones
    Note over NS1,NS2: Cluster actif — synchronisation continue
Succès : Une fois le cluster actif, créons une zone de test sur ns1. Elle doit apparaître sur ns2 en quelques secondes, sans intervention. C’est la preuve que la réplication fonctionne.

Créer la zone locale allfabox.fr
#

Sur ns1, nous allons dans Zones → Add Zone, créons une zone Primary nommée allfabox.fr, et ajoutons nos enregistrements internes (par exemple les A des services du homelab). Grâce au cluster, ces enregistrements se propagent immédiatement sur ns2.

Info : Pensons à ajouter les enregistrements ns1 et ns2 eux-mêmes dans la zone dns.allfabox.fr (A → 10.10.10.53 et A → 10.10.20.53) pour que les FQDN des serveurs se résolvent correctement.

Vérification et tests
#

Un cluster DNS ne vaut que s’il résiste réellement à la panne d’un nœud. On vérifie d’abord la résolution, puis on simule une coupure.

Test de résolution sur chaque nœud (depuis n’importe quelle machine du réseau) :

# Résolution d'un nom public via ns1
dig @10.10.10.53 google.fr +short

# Même requête via ns2
dig @10.10.20.53 google.fr +short

# Résolution d'un enregistrement local (zone allfabox.fr)
dig @10.10.10.53 ns1.dns.allfabox.fr +short
dig @10.10.20.53 ns1.dns.allfabox.fr +short

Les deux nœuds doivent renvoyer des réponses cohérentes. La résolution du nom local ns1.dns.allfabox.fr doit fonctionner identiquement sur les deux serveurs — c’est la validation concrète du cluster.

Test de synchronisation : nous ajoutons un enregistrement A test.allfabox.fr → 10.10.10.99 sur ns1, puis nous interrogeons ns2 :

dig @10.10.20.53 test.allfabox.fr +short
# Doit renvoyer 10.10.10.99 sans l'avoir créé sur ns2

Test de bascule : nous arrêtons le service DNS sur ns1 et vérifions que ns2 répond toujours :

# Sur ns1
sudo systemctl stop dns

# Depuis un client — ns2 doit continuer à répondre
dig @10.10.20.53 google.fr +short

# Puis on relance ns1
sudo systemctl start dns
Succès : Si ns2 répond alors que ns1 est arrêté, notre redondance est opérationnelle. N’oublions pas de distribuer les deux adresses (10.10.10.53 primaire, 10.10.20.53 secondaire) à nos clients via le DHCP.

Maintenance et monitoring
#

Un DNS bien géré se fait oublier. Quelques réflexes suffisent à garder le cluster en bonne santé.

Mise à jour de Technitium — la même commande qu’à l’installation met à jour vers la dernière version, sur chaque nœud :

curl -sSL https://download.technitium.com/dns/install.sh | sudo bash
Astuce : Mettons à jour un nœud à la fois. Pendant que ns2 redémarre pour sa mise à jour, ns1 continue de résoudre. Nous obtenons des mises à jour sans coupure de service.

Surveiller le service :

systemctl status dns
journalctl -u dns -f

Sauvegarde — Technitium permet d’exporter toute sa configuration (zones, réglages, listes) depuis Settings → Backup/Restore. Planifions un export régulier du primaire ns1.

Le tableau de bord web offre déjà un excellent monitoring visuel : requêtes totales, taux de cache, clients, requêtes bloquées. Nous pouvons d’ailleurs remonter ces métriques dans un dashboard homelab — voir l’article dédié au widget Homepage pour Technitium.

Tableau de bord Technitium
Placeholder — Dashboard Technitium : requêtes, cache et clients en temps réel.

Troubleshooting
#

Les problèmes les plus fréquents à l’installation d’un DNS Linux tournent tous autour du port 53. Voici comment les diagnostiquer.
Symptôme : Le service dns ne démarre pas, ou l’installation échoue avec une erreur « address already in use » sur le port 53.

Cause : Un résolveur local (systemd-resolved) occupe déjà le port 53. C’est le comportement par défaut sur Ubuntu. En revanche, avec les images officielles Raspberry Pi OS et le template Debian 13 utilisés ici, le port 53 est normalement libre — si nous rencontrons ce symptôme, c’est probablement qu’un systemd-resolved a été activé manuellement ou hérité d’une configuration antérieure.

Solution :

# Vérifier qui écoute sur le port 53
sudo ss -tulpn | grep ':53'

# Si systemd-resolved est en cause, le désactiver
sudo systemctl disable --now systemd-resolved

# Restaurer un /etc/resolv.conf classique
sudo rm /etc/resolv.conf
echo "nameserver 127.0.0.1" | sudo tee /etc/resolv.conf

# Relancer Technitium
sudo systemctl restart dns
Prévention : Vérifions toujours l’occupation du port 53 (ss -tulpn | grep ':53') avant de lancer l’installation. Cela nous évite de chercher pendant vingt minutes pourquoi le service refuse de démarrer.

Arbre de décision pour un DNS qui ne répond pas :

flowchart TD
    A["Le DNS ne répond pas"] --> B{"systemctl status dns
= running ?"} B -->|Non| C{"Port 53 occupé ?"} C -->|Oui| D["Désactiver systemd-resolved"] C -->|Non| E["Lire journalctl -u dns"] B -->|Oui| F{"dig @IP local
répond ?"} F -->|Non| G["Vérifier pare-feu / VLAN"] F -->|Oui| H["Vérifier la route
client → serveur"] style A fill:#7f1d1d,stroke:#f87171,stroke-width:2px,color:#fff style D fill:#14532d,stroke:#4ade80,stroke-width:2px,color:#fff style H fill:#14532d,stroke:#4ade80,stroke-width:2px,color:#fff

FAQ

Le secondaire ne se synchronise pas ? Vérifions que ns2 peut joindre ns1 sur le réseau (ping 10.10.10.53 depuis ns2). La communication inter-VLAN 20 → 10 doit être autorisée par notre pare-feu. Vérifions aussi que le jeton de cluster est correct.
Faut-il ouvrir le port 5380 entre les nœuds ? La synchronisation de cluster passe par l’API de Technitium. Assurons-nous que le flux nécessaire entre ns2 et ns1 est autorisé par les règles de pare-feu inter-zones.

Optimisations et bonnes pratiques
#

Le cluster fonctionne. Quelques réglages supplémentaires le rendent plus rapide, plus sûr et plus privé.
  • Chiffrer les requêtes amont : configurons les forwarders de Technitium en DNS-over-HTTPS (DoH) ou DNS-over-TLS (DoT). Nos résolutions sortantes ne transitent plus en clair.
  • Restreindre l’interface d’admin : limitons l’accès au port 5380 aux VLANs d’administration via le pare-feu. L’interface web ne devrait pas être joignable depuis les VLANs clients ou IoT.
  • Blocage publicitaire : Technitium intègre un système de listes de blocage (comme Pi-hole). Activons quelques listes réputées dans Settings → Blocking — configurées une fois sur le primaire, elles se répliquent sur le secondaire.
  • Cache prefetch : activons le rafraîchissement anticipé du cache pour servir des réponses fraîches sans latence sur les domaines les plus demandés.
  • Sauvegarde régulière : automatisons l’export de configuration du primaire et stockons-le hors de la carte SD du RPi.
Attention : Ne pointons jamais tous nos clients uniquement sur le primaire ns1. L’intérêt du cluster est perdu si le secondaire n’est pas distribué. Configurons notre DHCP pour annoncer 10.10.10.53 et 10.10.20.53.

Conclusion
#

En une poignée de commandes et quelques clics, nous avons transformé deux petites machines en un cluster DNS redondant, synchronisé et administrable depuis une interface unique. Fini le point de défaillance unique sur la résolution de noms.

Ce que nous avons accompli :

  • Déployé ns1 sur Raspberry Pi 3B dans le VLAN SERVERS (10.10.10.53)
  • Déployé ns2 dans un LXC Debian 13 sur Proxmox Neo (10.10.20.53)
  • Installé Technitium DNS 15.2 en une commande sur les deux nœuds
  • Mis les deux instances en cluster avec réplication automatique des zones
  • Validé la redondance en simulant la panne du primaire
Astuce : Prochaine étape naturelle : le Split Horizon. Technitium peut renvoyer une réponse différente selon que la requête vient de l’intérieur ou de l’extérieur du réseau — parfait pour pointer un service vers son IP interne en LAN et vers Traefik en externe. Un excellent sujet pour un futur épisode.

Ressources utiles :

Perfect Homelab - Cet article fait partie d'une série.
Partie 13: Cet article

Articles connexes