Homelab auto-hébergé

Pourquoi
Je voulais héberger mes propres services plutôt que de les laisser chez des tiers, et avoir un terrain de jeu permanent pour l'administration Linux, les conteneurs et le réseau. Tout tourne sur une machine chez moi, pas sur un VPS loué.
La machine
Un mini PC Beelink SER5 : un Ryzen 5 5500U (12 threads), environ 26 Go de RAM, un NVMe pour le système en LVM et un SSD SATA de 2 To pour les données. Ubuntu comme système.
Le système et la plupart des configs de conteneurs vivent sur le NVMe. Les gros volumes (Nextcloud, la médiathèque) sont sur le SSD SATA, en ext4. Au début, les données passaient par des volumes Podman sur le NVMe. Je les ai migrées vers un montage natif sur le SATA après quelques impasses : mergerfs ne s'entend pas avec les namespaces des conteneurs rootless, et Nextcloud ignore les liens symboliques qui sortent de son dossier de données. La migration complète a réglé au passage un bug d'envoi de gros fichiers (erreur EXDEV renvoyée en 403).
Conteneurs et services
Tout tourne en Podman rootless. Les principaux :
- Caddy en reverse proxy, seul point d'entrée public sur les ports 80 et 443.
- Nextcloud avec sa base PostgreSQL.
- Un serveur de streaming qui lit la médiathèque de Nextcloud en lecture seule.
- Crafty Controller pour gérer un serveur Minecraft Forge 1.20.1 modé.
- Uptime Kuma, Dozzle, Netdata et un dashboard Homer pour la supervision et les logs.
- Watchtower pour les mises à jour automatiques des images, en excluant Nextcloud et Crafty par label.
Le démarrage au boot est orchestré par un script qui lance chaque service
dans l'ordre. Quelques contournements en cours de route, par exemple Homer
qui a besoin de mem_swappiness: -1 à cause d'un bug crun sur cgroups v2.
Réseau et accès
Le VPN privé est monté avec Headscale, l'implémentation open source du serveur de coordination Tailscale, auto-hébergée. Les services internes ne sont joignables que sur le VPN : chacun a son sous-domaine servi par Caddy, lié à l'adresse du VPN et pas à l'interface publique.
Un seul service est exposé publiquement, derrière Caddy. Le reste est fermé.
Le pare-feu ufw est en deny incoming par défaut : SSH seulement sur
l'interface du VPN, 80 et 443 en public, tout le reste réservé au VPN. Le
port du serveur Minecraft n'est accessible que sur le VPN, vérifié fermé
côté public.
Sécurité
Plusieurs couches : ufw pour le filtrage, fail2ban avec des jails pour SSH, Caddy et la récidive, CrowdSec pour la protection collaborative, ClamAV avec sa base tenue à jour, et rkhunter plus chkrootkit pour les rootkits.
Un script de scan maison tourne en cron : un mode léger tous les jours sur
les fichiers modifiés dans les dernières 24 heures, un mode complet le
dimanche sur tout le système hors médiathèque. Il est écrit pour ne pas se
saborder : verrou flock contre les exécutions concurrentes, redémarrage
automatique de clamd s'il se bloque, résolution dynamique du conteneur
Nextcloud, détection de rkhunter par code de sortie plutôt que par texte, et
nettoyage des codes couleur dans la sortie. Il contrôle aussi l'état de ufw,
fail2ban, CrowdSec, Caddy et du VPN, puis envoie un signe de vie à Uptime
Kuma.
Sauvegardes
Restic, lancé en root chaque nuit par cron, vers un dépôt local. Il sauvegarde les configs système (Caddy, Headscale, fail2ban, ufw, ClamAV), les scripts, les crontabs et un dump PostgreSQL de Nextcloud. La médiathèque est exclue : c'est volumineux et facile à récupérer. Rétention de sept sauvegardes quotidiennes et quatre hebdomadaires.
Bilan
Ce projet couvre l'administration Linux au quotidien, les conteneurs rootless, un réseau maillé en VPN, le durcissement d'un serveur exposé, la supervision et des sauvegardes réellement testées. Et beaucoup de débogage concret : namespaces de conteneurs, cgroups v2, contexte d'exécution des tâches cron, questions de permissions entre l'hôte et les conteneurs.