12 jours pour une infra complète
De zéro à 21 rôles Ansible, 15 services, observabilité full-stack. Le plaisir d automatiser from scratch, couche par couche.
Le point de départ
Un VPS Ubuntu vierge. Pas de panel, pas de cPanel, pas de Cloudways. Une IP, un accès root, et l’envie de construire toute la couche d’infra à la main. Pas par masochisme - par conviction que comprendre chaque brique est la seule façon de debugger à 3h du matin quand quelque chose casse.
J’ai déjà utilisé des PaaS. Vercel, Railway, Render. C’est pratique tant que ça marche. Le jour où il faut un truc spécifique - un VPN, une base Postgres avec des extensions custom, un registry Docker privé - on se retrouve à contourner les limites de la plateforme plutôt qu’à résoudre son problème.
Douze jours. Soixante-quatorze commits. Un make deploy qui prend une machine nue et la transforme en infrastructure de production.
J1 : le hardening
Le premier jour, je n’ai rien installé d’utile. Que de la sécurité. C’est contre-intuitif quand on a envie de déployer des apps, mais c’est la discipline de base.
Changement du port SSH. Désactivation de l’authentification par mot de passe. Clé Ed25519 uniquement. Fail2ban avec des règles agressives - trois tentatives, ban de 24 heures. UFW avec une politique deny-all en entrée, ouverture sélective des ports 80, 443 et le port SSH custom.
# roles/hardening/tasks/main.yml
- name: Disable password authentication
lineinfile:
path: /etc/ssh/sshd_config
regexp: '^#?PasswordAuthentication'
line: 'PasswordAuthentication no'
notify: restart sshd
- name: Set SSH port
lineinfile:
path: /etc/ssh/sshd_config
regexp: '^#?Port'
line: 'Port {{ ssh_port }}'
notify: restart sshd
Unattended upgrades pour les patchs de sécurité automatiques. Logwatch pour un email quotidien avec le résumé de l’activité système. Rien de glamour, mais c’est la fondation sur laquelle tout le reste repose.
J2 : le reverse proxy et le monitoring
Traefik en reverse proxy. J’ai hésité avec Nginx, mais Traefik a un avantage décisif : la découverte automatique des conteneurs Docker via les labels. On ajoute un conteneur avec les bons labels, Traefik génère la config, le certificat Let’s Encrypt, et le routage. Zéro fichier de config à modifier.
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.app.rule=Host(`app.mondomaine.fr`)'
- 'traefik.http.routers.app.tls.certresolver=letsencrypt'
Le monitoring est arrivé le même jour. Prometheus pour la collecte, Grafana pour la visualisation. Node Exporter sur la machine hôte, cAdvisor pour les métriques Docker. J’ai un dashboard qui me montre la CPU, la RAM, le disque, le réseau, et les métriques par conteneur.
La tentation était de passer trois jours à peaufiner les dashboards. Je me suis forcé à m’arrêter quand j’avais cinq panels essentiels et des alertes sur le disque à 90%.
J3 : le SSO
Authentik. Un système d’authentification centralisé pour tous les services. Un seul login pour Grafana, le registry, Portainer, et tout ce qui viendra après.
L’installation d’Authentik est étonnamment complexe pour un outil qui promet de simplifier l’authentification. Il faut une base PostgreSQL dédiée, un Redis, un worker, et un serveur. Quatre conteneurs pour un SSO. Mais une fois en place, c’est de la magie : OAuth2/OIDC proxy devant n’importe quel service, avec des politiques d’accès granulaires.
Le rôle Ansible pour Authentik fait 180 lignes. C’est le plus gros de tout le projet. La moitié de ces lignes gère les secrets - mots de passe générés, clés API, tokens JWT.
J4 : la base de données
PostgreSQL sur la machine hôte (pas dans Docker - pour la performance et la gestion fine du PITR). WAL-G pour le Point-In-Time Recovery vers Scaleway S3. Un pg-provisioner en self-service permet de créer des bases à la volée pour les nouvelles apps.
Tests de validation à chaque deploy : smoke tests pour chaque rôle, vérification que les services répondent, dashboards SLO fonctionnels.
J5 : le registry et le tracing
Un registry Docker privé. Pas Docker Hub, pas GitHub Container Registry - un registry à moi, sur mon infra, derrière le SSO. Pour les images de mes projets perso, je ne veux pas dépendre d’un service tiers qui peut changer ses limites de stockage.
Le tracing distribué avec Tempo et Grafana Alloy. Chaque requête HTTP traversant Traefik génère une trace distribuée. On peut suivre une requête depuis le browser jusqu’à la base de données, en passant par le reverse proxy et l’application. RUM et Web Vitals complètent le tableau côté client. C’est overkill pour un homelab, mais c’est exactement le genre de pratique SRE que je veux maîtriser.
J6 : le SSH avancé
Au-delà du hardening de base du jour 1, j’ai ajouté une couche supplémentaire. SSH uniquement via le VPN WireGuard, avec un fallback rate-limited sur un port non-standard (62222). Healthchecks sur chaque conteneur, no-new-privileges partout, limites de ressources CPU/mémoire.
J7 : les backups
La règle du 3-2-1 : trois copies, deux supports différents, une copie hors site. En pratique : les données sur le VPS, PostgreSQL PITR (Point-In-Time Recovery) via WAL-G, et une copie S3 sur Scaleway.
Le backup tourne en timer systemd à 3h du matin :
- WAL-G pour le PITR PostgreSQL
- Restic pour les volumes Docker critiques, vers Scaleway S3
- Rétention : 7 quotidiens, 4 hebdomadaires, 6 mensuels
- Notification Ntfy (self-hosted) en cas d’échec
Le test de restauration fait partie du workflow - sans test, un backup ne vaut rien.
J8 : le VPN
WireGuard. Plus simple qu’OpenVPN, plus rapide, et le module est dans le noyau Linux depuis la 5.6. Configuration en cinq minutes : une paire de clés, une interface, un peer.
[Interface]
PrivateKey = <cle_serveur>
Address = 10.0.0.1/24
ListenPort = 51820
[Peer]
PublicKey = <cle_client>
AllowedIPs = 10.0.0.2/32
Le VPN me donne accès à tous les services internes depuis n’importe où. Prometheus, Grafana, Portainer, le registry - tout est accessible via le tunnel sans être exposé sur Internet. C’est la dernière couche de la défense en profondeur.
La philosophie
Un seul make deploy prend une machine Ubuntu vierge et la transforme en infrastructure complète. Vingt et un rôles Ansible, quinze services, observabilité full-stack. C’est reproductible, versionné, et testable.
L’infrastructure as code, ce n’est pas juste un buzzword. C’est la différence entre “je sais que ça marche parce que je l’ai configuré à la main il y a six mois” et “je sais que ça marche parce que je peux le reconstruire en 30 minutes depuis un commit git”.
Chaque rôle est idempotent. On peut relancer make deploy dix fois, le résultat est le même. Pas de “j’ai oublié cette étape manuelle”. Pas de “il faut se connecter en SSH et modifier ce fichier”. Tout est dans le dépôt git.
Ce que j’en retiens
Douze jours de travail méthodique. La tentation de tout faire le premier jour et de debugger ensuite est forte. La discipline de construire couche par couche, en testant chaque brique avant de passer à la suivante, est contre-intuitive mais payante.
Le homelab n’est pas de la production. Mais les pratiques SRE - monitoring, alerting, backup testé, défense en profondeur - s’appliquent à n’importe quelle échelle. J’ai appris plus en douze jours sur mon VPS qu’en six mois à utiliser des PaaS.
Le make deploy tourne maintenant en cinq minutes. Soixante-quatorze commits de satisfaction automatisée.