Home Server : architecture et retour d'expérience d'un développeur
Un soir de 2022, ma box est tombée. Rien de dramatique en soi, juste une vingtaine de minutes d’interruption. Le problème, c’est ce que cette coupure a révélé : en un instant, je me suis retrouvé privé de ma musique, de mes documents et de mes prises de notes. Tout était chez Google, Spotify ou Dropbox. Je ne possédais plus rien en local, je ne contrôlais plus rien.
J’avais déjà tenté l’aventure du serveur perso avant le COVID, mais sans méthode : du distro hopping compulsif, des configs bancales et des nuits entières à passer au peigne fin des paquets orphelins. Résultat, je finissais toujours par tout abandonner.
Cette fois, j’ai abordé le problème autrement. Plutôt que de foncer tête baissée sur des outils, j’ai d’abord posé mes contraintes. Cet article retrace la construction de cette infrastructure, les choix d’architecture qui en ont découlé, et ce que cette aventure m’a réellement appris sur le terrain.
Pourquoi ce projet ?
Cette panne d’internet a été l’étincelle, mais le problème venait de plus loin. Une vraie saturation vis-à-vis du cloud : les scandales de données, les CGU modifiées en douce, cette impression désagréable de dépendre de services qui peuvent fermer du jour au lendemain. J’avais simplement envie de réintroduire du local, du physique, du matériel qui m’appartient et fonctionne sans connexion.
C’était aussi l’occasion de franchir un cap technique. En entreprise, le réseau, les conteneurs, la sécurité ou le monitoring font partie du décor. Mais lire la doc ne suffira jamais : rien ne vaut la pratique sur une machine qui tourne H24 avec du vrai trafic dessus (domotique, stockage, serveurs de jeu). Mon homelab est devenu mon bac à sable ultime, en conditions réelles.
Et puis, soyons honnêtes : mon installation était un champ de ruines. Des années de bidouille avaient accumulé des configs bancales, des scripts fantômes et des paquets oubliés après un test d’un soir. Il fallait tout raser pour reconstruire proprement, documenter et enfin avoir un système maintenable.
Architecture globale
L’infrastructure repose sur une machine unique. Tout accès distant passe d’abord par le VPN, puis par un reverse proxy, avant d’atteindre les services conteneurisés. Aucun port n’est ouvert directement sur Internet saut celui du VPN.
graph LR
%% Noeuds principaux
Utilisateur -->|"WireGuard"| VPN
VPN -->|"réseau interne"| ReverseProxy
%% Liens vers les conteneurs (sous-graphes)
ReverseProxy -->|"HTTP(S)"| Services
ReverseProxy -->|"HTTP(S)"| Monitoring
%% Structure du groupe Services
subgraph Services ["Services"]
direction TB
Nextcloud
Jellyfin
HomeAssistant
AdGuard
Minecraft
Mumble
end
%% Structure du groupe Monitoring
subgraph Monitoring ["Monitoring"]
direction TB
Prometheus
Grafana
Loki
end
Ce schéma est volontairement simple. Il n’y a pas de haute disponibilité, pas de cluster, pas de réplication automatique. C’est un choix assumé, j’y reviens plus loin.
Le matériel
Le serveur est un Beelink MINI-S12 Pro. Un mini-PC à processeur Intel N100, silencieux, compact, et remarquablement sobre en énergie.
| Composant | Détail |
|---|---|
| CPU | Intel N100 (4 cœurs, faible consommation) |
| RAM | 16 Go |
| Stockage | SSD 512 Go (système + données) |
| Consommation | ~10–15 W en charge |
Pas d’ECC, pas de RAID, pas de redondance. Ce n’est pas du matériel de datacenter, et c’est très bien ainsi. Pour une dizaine de conteneurs et quelques utilisateurs simultanés, le N100 ne bronche pas.
La seule limite qui commencera à se faire sentir, c’est le stockage, notamment pour Jellyfin, qui grossit avec la médiathèque. Une évolution matérielle est probable à terme, mais elle n’est pas urgente.
Les choix techniques
Debian
Le serveur tourne sous Debian 13. Stable, prévisible, supportée jusqu’en 2035.
Pendant des années, j’ai utilisé Fedora ou Arch sur mes machines personnelles, convaincu qu’être toujours à la dernière version était une bonne pratique de sécurité.
En réalité, les rolling releases m’ont surtout apporté des régressions inattendues : un noyau qui casse un driver réseau, une mise à jour qui change le comportement d’un service système.
Debian stable est ennuyeuse. C’est exactement ce qu’il faut.
Docker Compose
J’ai tranché pour Docker et Compose. Pas par méconnaissance du reste, mais pour l’écosystème : c’est ultra-documenté, éprouvé, et le ticket d’entrée est imbattable quand on veut avancer vite.
L’immense force de Compose, c’est la clarté. Chaque service a son propre dossier, son docker-compose.yml, ses secrets isolés dans un .env, et le tout est versionné dans un repo Git local. Si la machine explose demain ? Je réinjecte mon dépôt, un coup de docker compose up -d dans chaque dossier, et tout repart exactement comme avant.
Évidemment, Docker n’est pas parfait. Le daemon qui tourne historiquement en root, la surface d’attaque, la gestion des secrets un peu rustique sans Swarm… ce sont des vrais sujets. Je surveille Podman de près, qui corrige pas mal de ces défauts.
Sur un projet plus critique, la question se poserait sérieusement. Mais ici, j’ai privilégié l’efficacité et la simplicité brute.
Voici à quoi ressemble un service typique :
services:
nextcloud:
image: nextcloud:stable
container_name: nextcloud
volumes:
- /srv/data/nextcloud:/var/www/html/data
ports:
- "8080:80"
restart: unless-stopped
La configuration est séparée des données persistantes. Les secrets ne sont jamais dans le fichier Compose, ils passent par .env.
Le restart: unless-stopped assure que le service redémarre automatiquement après un reboot.
WireGuard + Caddy
L’accès distant passe par WireGuard, avec wg-easy pour gérer les pairs sans se battre avec des fichiers de configuration à la main. Aucun service n’est exposé directement. Tout transite par le VPN.
Côté reverse proxy, j’ai choisi Caddy après avoir longuement hésité avec Traefik. Traefik est excellent sur le papier, mais sa configuration correcte en Docker Compose, labels, middlewares, providers, s’est révélée pénible à déboguer.
Caddy, lui, génère automatiquement les certificats HTTPS via Let’s Encrypt et se configure en quelques dizaines de lignes au total. Je n’y touche presque plus.
Fail2Ban complète le dispositif en bloquant les IP qui multiplient les tentatives d’authentification sur SSH et Caddy.
graph LR
Internet -->|toutes les requêtes| Fail2Ban
Fail2Ban -->|IP autorisées| WireGuard
WireGuard -->|réseau interne| Caddy
Caddy -->|:8080| Nextcloud
Caddy -->|:8096| Jellyfin
Caddy -->|:8123| HomeAssistant
Caddy -->|...| PointsSuspensions["..."]
Les services déployés
Une dizaine de conteneurs tournent en permanence. Voici les principaux :
| Service | Rôle |
|---|---|
| Nextcloud | Stockage et synchronisation de fichiers |
| Jellyfin | Serveur multimédia personnel |
| Home Assistant | Domotique : capteurs Zigbee, automatisations ESP32 |
| AdGuard Home | Filtrage DNS, blocage publicitaire sur le réseau |
| Minecraft | Serveur de jeu pour quelques amis |
| Mumble | Serveur vocal léger, utilisé en local |
Chaque conteneur a ses volumes dédiés, configuration d’un côté, données persistantes de l’autre. Cette isolation garantit qu’un problème sur un service n’affecte pas les autres : redémarrer Jellyfin ne touche pas Nextcloud, mettre à jour Home Assistant ne risque pas de corrompre les données AdGuard.
Home Assistant mérite une mention particulière. Ce qui a commencé comme un test avec deux capteurs de CO2 s’est progressivement étendu : capteurs Zigbee, automatisations ESP32 faites maison.
C’est le service qui a le plus évolué, et celui dont l’arrêt se remarque le plus vite.
Monitoring
Superviser l’infrastructure, c’est la partie qu’on néglige jusqu’au jour où quelque chose tombe sans qu’on sache depuis combien de temps. J’utilise trois outils en stack :
Prometheus collecte les métriques système et conteneurs. CPU, RAM, disque, réseau, état des services. Il scrape les exporters et stocke les séries temporelles localement.
Grafana consomme ces métriques et les affiche dans des dashboards personnalisés.
Loki agrège les logs de l’ensemble des conteneurs. C’est surtout utile pour le serveur Minecraft. Retrouver la cause d’un crash ou d’une lenteur en quelques secondes plutôt qu’en épluchant des fichiers .log à la main.
Ce trio n’est pas léger à mettre en place, mais une fois opérationnel, il change complètement la façon dont on interagit avec l’infrastructure.
On passe d’une gestion réactive (“quelque chose est cassé, qu’est-ce que c’est ?”) à une gestion proactive (“le disque est à 80 %, il faut nettoyer avant la semaine prochaine”).
Ce que j’ai écarté et pourquoi
Avec un seul serveur et une dizaine de conteneurs, la tentation de surcharger la stack est réelle. Voici ce que j’ai consciemment mis de côté :
Kubernetes : K3s, K8s, peu importe la déclinaison. L’orchestration de pods, la gestion du réseau overlay, les ConfigMaps, les Secrets Kubernetes… tout ça a du sens quand on gère des dizaines de services sur plusieurs nœuds. Pour un serveur unique, c’est ajouter dix couches de complexité pour résoudre des problèmes qu’on n’a pas. Un docker compose up suffit.
Ansible, Puppet, Chef : l’automatisation de configuration est séduisante sur le papier. En pratique, pour une seule machine, des scripts bash bien commentés et des services systemd font exactement le même travail sans la surcharge cognitive. J’expérimente Ansible en parallèle pour monter en compétence, mais je ne l’utilise pas en production ici.
Traefik : je l’ai mentionné plus haut. Excellent outil, mais Caddy résout le même problème avec moins de configuration.
Chaque outil supplémentaire est une chose à maintenir, à mettre à jour, à déboguer. Un home server qu’on oublie pendant trois semaines et qui tourne toujours est bien plus précieux qu’une stack impressionnante qui demande une attention constante.
Ce que j’envisage pour la suite
Rien d’urgent, mais quelques pistes que je garde en tête :
| Domaine | Piste envisagée |
|---|---|
| OS | Migrer vers NixOS pour déclarer tout le système de manière reproductible |
| Sauvegardes | Mettre en place des sauvegardes externalisées avec restic ou Borg vers un stockage distant |
| CI/CD | Automatiser les déploiements via Forgejo Actions ou GitHub Actions |
| Résilience | Ajouter une réplication des volumes critiques et un basculement manuel documenté |
| Infrastructure as code | Expérimenter Terraform pour décrire les conteneurs, réseaux et volumes |
NixOS est probablement la piste qui m’intéresse le plus.
L’idée de décrire l’intégralité du système dans un fichier versionné et de pouvoir rejouer cette configuration sur n’importe quelle machine est exactement dans la continuité de ce que j’ai construit ici.
Ce que trois ans m’ont appris
Les choix ennuyeux sont souvent les bons.
Debian plutôt qu’Arch. Docker plutôt que Kubernetes. Caddy plutôt que Traefik.
À chaque fois, j’ai choisi la solution qui demande le moins d’attention quotidienne et à chaque fois, c’était la bonne décision.
La documentation est le vrai produit.
Le code, les configs, les scripts : tout ça peut se reconstruire. Ce qui prend du temps, c’est de se souvenir pourquoi on a fait tel choix six mois plus tôt.
Aujourd’hui, chaque service a son propre README.md qui explique l’installation, les dépendances, et les pièges connus.
Et j’ai appris qu’un home server n’est jamais vraiment “terminé” mais qu’il peut atteindre un état où on n’a plus besoin de s’en préoccuper en permanence.
La prochaine panne internet peut venir. Ma musique jouera quand même.