Skip to content

Fondations réseau homelab avec UniFi

Mon homelab a démarré comme beaucoup de labs : la box FAI en routeur, tout le monde sur le même LAN, un Proxmox sur un mini PC, le NAS sur le switch, le Wi‑Fi pour le reste. Ça suffit pour installer GitLab, Jellyfin, des VMs. Le réseau ne pose pas de question tant qu’on n’en pose pas.

Les questions ont commencé quand j’ai empilé trois nœuds Proxmox, un Synology avec les backups et le media, des objets IoT, Home Assistant, un Wi‑Fi invité. Sur un LAN plat, tout voit tout. On peut créer des VLANs dans l’UI, mais sans firewall explicite entre eux, le routage Internal → Internal finit souvent en allow-all. Les VLANs seuls ne filtrent rien.

Chez moi, l’IoT devait joindre HA en MQTT mais pas le NAS ; le lab monte le NFS sur le Synology ; le PC Windows ouvre les partages en SMB ; les invités ne doivent pas toucher GitLab. Impossible à tenir proprement sur un seul subnet.

J’ai arrêté d’ajouter des services et j’ai investi dans le réseau avant de retourner sur k3s et les playbooks Ansible.

Sur le schéma, le LAN plat laisse une prise IoT joindre en théorie le NAS et les VMs. Après segmentation, l’IoT ne passe que par des ALLOW ciblés (Pi-hole, HA) puis des BLOCK vers Trusted et Untrusted ; le lab monte le NAS en NFS (2049), le PC en SMB (445), et Guest reste isolé.

L’anecdote du premier weekend : j’avais une règle ALLOW « IoT → Home Assistant », mais sous le BLOCK « IoT → Untrusted ». À l’époque HA était encore sur le vlan lab (50) : UniFi bloquait tout le vlan 50, donc aussi l’IP de HA. MQTT mort. L’ordre des règles compte autant que l’action. Depuis, j’ai déplacé HA sur le vlan IoT (40). MQTT reste local au vlan, mais la leçon d’ordre reste vraie pour tout ALLOW croisé.

L’ordre d’achat compte autant que le choix technique. Chez moi, la gateway est arrivée avant le re-tag des ports, et le switch manageable avant de multiplier les VLANs Wi‑Fi. Sans ça, on empile des SSIDs sur un LAN plat.

BriqueRôlePourquoi maintenant
UniFi Cloud Gateway FiberRoutage inter-VLAN, firewall zone-based, DHCP/DNS par réseauUn seul endroit pour filtrer et documenter le trafic
USW Flex 2.5GSwitch, ports taggés VLANLe LAN plat ne scale pas quand Main / IoT / Guest partagent le même fil
AP UniFi (déjà en place)Wi‑Fi par réseauInvités et IoT hors du Wi‑Fi « maison »
Synology DS423+NAS sur Trusted (20)Données hors du vlan lab
3× Proxmox (OptiPlex, Firebat, …)Compute sur Untrusted (50)Forge, media, k3s on-demand

Je n’ai pas pris OPNsense : j’avais déjà l’écosystème UniFi, et la CG Fiber tient routage, firewall et API locale. Les tutos homelab tournent souvent autour d’OPNsense ; le principe (segmenter, filtrer, vérifier) est le même. Ce guide part de cette stack déjà en place : plan d’adressage, règles firewall, DNS, NFS/SMB, IoT/HA, export API, pièges que j’ai touchés. Pas d’install UniFi from scratch, pas de renumérotation massive d’IPs, pas de Terraform day 1, pas de k3s. Côté gateway : UniFi Network 10.x, firewall zone-based, policies ordonnées, API Integration pour auditer sans cliquer dans l’UI à chaque fois.

Chez moi, le chemin a été : box FAI en WAN seulement et CG Fiber comme gateway LAN ; switch et câblage avec ports taggés ; réseaux UniFi (Main, Trusted, IoT, Untrusted, Guest) ; DHCP/DNS par réseau via Pi-hole plutôt que tout sur la gateway ; règles firewall user avant les BLOCK larges, avec Reorder dans Internal → Internal ; tests NFS, SMB, MQTT et Guest sur téléphone ; export API régulier pour garder une copie de l’ordre des règles et du DHCP. Un weekend de durcissement et de doc, pas une refonte d’adressage. Si je recommençais, je segmenterais avant la troisième VM « forge », pas après GitLab et Vault.

Tout l’inter-VLAN passe par la gateway. Sur le schéma, les flèches importantes montrent que le trafic transite par la CG (là où on audite), que Wi‑Fi et filaire partagent les mêmes VLANs, et que le NAS n’est pas sur le vlan lab.

En pratique, le NAS et les deux Pi-hole vivent sur Trusted, pendant que Proxmox, GitLab et Vault restent sur Untrusted. Home Assistant est sur IoT, même vlan que les objets. MQTT ne traverse plus le lab.

J’aligne l’id VLAN sur le 3ᵉ octet quand je peux : vlan 20 → 192.168.20.x. En debug (ping, logs UniFi, tcpdump) ça évite de chercher.

VLANNomSubnetRôle
1Default192.168.0.0/24UniFi ; DHCP off
10Main192.168.10.0/24PC Windows, Wi‑Fi quotidien
20Servers-Trusted192.168.20.0/24NAS 192.168.20.20, Pi-hole Zero .20.2, Pi-hole LXC .20.3
40IoT192.168.40.0/24Objets connectés + Home Assistant .40.204
50Servers-Untrusted192.168.50.0/24PVE, GitLab, Vault
60Guest192.168.60.0/24Invités, zone DMZ, isolation réseau

Untrusted (50) chez moi, c’est le lab / compute, pas une « zone sans secrets » : GitLab et Vault y tournent encore. C’est séparé du NAS et des DNS long terme sur vlan 20. Home Assistant est sur IoT (40), avec les objets. MQTT reste local au vlan, sans traverser le lab.

pve03 (forge) et pve02 (media) restent allumés. pve01 (k3s Ansible) je ne lance que quand j’en ai besoin : conso et bruit, pas de cluster 24h pour l’instant. Le schéma relie ces nœuds aux flux utiles : NFS vers le NAS, MQTT sur IoT, DNS vers les Pi-hole Trusted.

Synology vit sur Trusted. J’ai mis deux protocoles et deux règles firewall, pas un gros « allow vers le NAS » : Proxmox (et le reste du lab) monte en NFS pour backups et media, le PC Windows ouvre \\DS423 en SMB, et l’IoT n’a ni l’un ni l’autre.

ClientVLANProtoPort
Proxmox, GitLab, mediastack50NFS2049
PC Windows10SMB445

Deux Pi-hole, tous les deux sur Trusted, avec des rôles distincts. Le Zero filtre le trafic maison ; le LXC sur pve03 porte le split DNS du lab (GitLab, Vault) et unbound. Les deux partagent le vlan 20, mais pas le même job côté clients.

InstanceIPVLANRôle
Pi Zero 2W192.168.20.220Filtrage général (clients Main / IoT / Guest)
LXC sur pve03192.168.20.320Split DNS lab (GitLab, Vault), unbound

Main et lab poussent .20.3 + .20.2 + un fallback public en DHCP. IoT n’a que 192.168.20.2 en primaire et 1.1.1.1 en secours : une prise MQTT n’a pas besoin du split lab. J’ai choisi ce secours public plutôt que deux Pi-hole filtrés synchronisés (Gravity Sync). Si le Pi Zero tombe, les objets gardent du DNS ; ils perdent le filtrage sur le fallback, mais les prises MQTT vers HA continuent. Gravity Sync reste une piste pour aligner les listes. Côté firewall DNS, toujours IP + port 53, jamais « tout le vlan Trusted ».

UniFi Network 10.x expose les zones Internal, DMZ (Guest) et External. Chez moi, presque tout se joue en Internal → Internal : la première règle qui matche gagne. Il existe un catch-all système Allow All Traffic ; les règles user doivent être plus fines et au-dessus des BLOCK larges.

L’ordre ne se change pas depuis la Policy Table globale. Il faut Settings → Policy Engine → Zones → Internal → Internal, puis Reorder en bas de liste. Si Reorder est grisé, décocher les filtres IPv4/IPv6/Built-in dans la vue.

En prod, validé via l’API et des tests :

#NomActionDétail
1IoT DNSALLOWIoT → 192.168.20.2:53
2IoT to HAALLOWIoT → 192.168.40.204 (même vlan ; utile surtout si le trafic passe par la gateway)
3HA to IoTALLOW192.168.40.204 → IoT
4Admin labALLOWMain → Untrusted, tout
5DNS to Pi-holeALLOWMain → .20.2 + .20.3:53
6Main to ServersALLOWMain → Trusted, 445
7Lab to NASALLOWUntrusted → Trusted, 2049
8DNS labALLOWUntrusted → 192.168.20.3:53
9IoTBLOCKIoT → Trusted
10IoT to UntrustedBLOCKIoT → Untrusted

Les lignes 1–3 doivent rester avant 9–10. HA est sur vlan 40 ; les ALLOW IoT↔HA restent explicites si le trafic passe par la gateway, plus Main → HA / edge TLS pour l’UI depuis le PC. Le schéma ci-dessous est l’ordre actuel (pas l’anecdote « HA encore sur 50 »).

Autre erreur vue au début : HA to IoT en BLOCK au lieu d’ALLOW. MQTT IoT→HA peut passer avec allowReturnTraffic, mais dès que HA initie vers un device (certaines intégrations), il faut un ALLOW explicite, même sur un vlan partagé si tu filtres plus tard. IoT to HA chez moi sans filtre port (tout vers .40.204) ; plus tard je pourrai limiter à 1883/8883.

Deux familles de clés existent : cloud sur unifi.ui.com (Site Manager) vs locale sur la gateway (Settings → Integrations). Pour curl depuis le LAN, seule la locale marche sur https://192.168.50.1/proxy/network/.... Un 401 sur l’IP gateway pointe souvent vers la mauvaise clé.

Terminal window
export UNIFY_API_NETWORK_KEY="…" # env locale, jamais dans Git
curl -sk -H "X-API-KEY: $UNIFY_API_NETWORK_KEY" \
"https://192.168.50.1/proxy/network/integration/v1/info"

Chez moi, un script lecture seule exporte VLANs, DNS DHCP par réseau, et policies USER_DEFINED. Utile avant/après chaque changement firewall. On obtient le même résultat avec quelques curl + jq sur l’API Integration.

Les erreurs qui m’ont fait perdre du temps :

SymptômeCause probable
401 sur gatewayClé cloud au lieu de clé locale
IoT ne joint pas HAIoT to HA sous un BLOCK large (ordre) ; ou HA to IoT manquant
HA ne pilote pas IoTHA to IoT en BLOCK
IoT utilise le DNS labDHCP IoT trop large ; garder .20.2 + public
Règle « DNS » ouvre toutPas d’IP en destination, seulement Internal→Internal
Reorder griséFiltres actifs dans la vue Zones

Accès distant (Tailscale, Cloudflare Access), IaC UniFi, Gravity Sync entre Pi-hole, et le détail d’un cluster k3s : d’autres guides. Ici je m’arrête quand le réseau est vérifiable et documenté : VLANs avec un firewall ordonné, NFS et SMB vers le NAS en règles séparées, DNS IoT sur .20.2 avec un fallback public, Home Assistant sur le même vlan que les objets, deux Pi-hole sur Trusted (Zero pour le filtrage maison, LXC pour le split lab), et un export API pour contrôler l’ordre réel des règles plutôt que l’UI seule.