Tutoriel

Stack homelab VPS 2026 : 5 services self-hosted

Déploiement10 min de lecture8 étapes

Héberger une application sur un VPS est devenu une routine pour les développeurs. Héberger cinq applications d'un coup — un gestionnaire de fichiers, un coffre-fort de mots de passe, un serveur multimédia, une photothèque et un archiveur de documents — sur le même VPS, avec un seul fichier de composition et un seul certificat SSL, est une autre affaire. Ce guide présente l'architecture complète du stack homelab 2026 : comment dimensionner le serveur, comment structurer le `docker-compose.yml`, comment configurer Caddy pour router chaque sous-domaine, et comment éviter les erreurs les plus courantes au démarrage.

Sommaire· Pourquoi consolider cinq services sur un seul VPS1/8
  1. 01Pourquoi consolider cinq services sur un seul VPS
  2. 02Ce que ce stack apporte concrètement
  3. 03Prérequis : dimensionnement et ports
  4. 04Déploiement pas à pas
  5. 05Caddy, Nginx Proxy Manager ou Traefik : quel reverse proxy pour ce stack
  6. 06Durcissement minimal avant exposition publique
  7. 07Dépannage : erreurs courantes au démarrage
  8. 08Pour aller plus loin

Pourquoi consolider cinq services sur un seul VPS

L'approche « une app, un VPS » a une logique : isolation totale, déploiement indépendant, aucun risque de contention. Elle a aussi un coût réel — cinq serveurs, cinq adresses IP, cinq renouvellements, cinq configurations nginx, cinq certificats TLS à surveiller. Pour un stack personnel ou une petite équipe, ce coût n'est justifié que si les applications ont des charges de pointe très différentes ou des exigences de sécurité incompatibles.

Nextcloud, Vaultwarden, Jellyfin, Immich et Paperless-ngx ont en commun d'être des applications à trafic modéré, utilisées principalement par un ou quelques utilisateurs. Vaultwarden consomme moins de 50 Mo de RAM en mode veille. Paperless-ngx tourne autour de 200 Mo. Immich, le plus gourmand du lot hors transcodage, reste sous 400 Mo au repos. Ces mesures sont documentées dans les projets respectifs sur GitHub et dans les retours de la communauté auto-hébergement.

La consolidation sur un VPS ne supprime pas les risques — elle les concentre. La contrepartie est un seul point d'entrée à durcir, un seul certificat à gérer, et un manifeste Docker Compose versionné qui constitue à lui seul la documentation complète de l'infrastructure.

Ce que ce stack apporte concrètement

  • Souveraineté sur les données — fichiers, mots de passe, photos et documents restent sur votre serveur, sous votre clé de chiffrement, sans dépendance à un fournisseur cloud tiers.
  • Un seul certificat TLS wildcard — Caddy demande et renouvelle automatiquement *.votre-domaine.com via le défi DNS-01, couvrant tous les sous-domaines du stack en une seule configuration.
  • Réseau Docker interne isolé — aucune application n'expose de port public directement ; tout le trafic entrant passe par Caddy sur 80/443, et les services communiquent sur un réseau bridge privé.
  • Volumes nommés et restauration prévisible — chaque service déclare ses données dans un volume Docker nommé (nextcloud_data, vaultwarden_data…), ce qui rend les sauvegardes et les migrations reproductibles par une seule commande rsync.
  • Mises à jour indépendantes — tirer une nouvelle image pour Immich ne redémarre ni Jellyfin ni Paperless-ngx ; docker compose up -d --no-deps immich ne touche que le service concerné.
  • Coût fixe et prévisible — un VPS à ressources fixes élimine les surprises de facturation à l'usage que génèrent les services cloud quand le transcodage Jellyfin s'emballe ou que les tâches OCR de Paperless-ngx s'accumulent.
  • Maillage de services possible — Nextcloud peut utiliser Redis et MariaDB déjà présents dans le Compose ; Immich partage le même réseau que le reverse proxy sans configuration supplémentaire.

Prérequis : dimensionnement et ports

Le plancher réaliste pour ce stack en usage courant est 4 vCPU / 8 Go de RAM / 100 Go de stockage SSD. Ce dimensionnement couvre les empreintes au repos de chaque service et laisse une marge pour le transcodage Jellyfin à la demande et les tâches OCR de Paperless-ngx, qui sont les deux pics de charge non négligeables du stack.

Détail des empreintes mesurées en mode veille (aucune session active, aucune tâche en arrière-plan) :

- Nextcloud (PHP-FPM + cron) : ~300 Mo selon la charge de synchronisation.
- Vaultwarden : < 50 Mo, image Rust très compacte.
- Jellyfin : ~250 Mo sans transcodage actif. En transcodage soft (x264, 1080p) : 1 à 2 vCPU en pointe.
- Immich (server + microservices) : ~350-400 Mo au repos. Les tâches d'apprentissage automatique (détection de visages, classification) consomment jusqu'à 2 Go de RAM selon le volume.
- Paperless-ngx (web + worker) : ~200 Mo. L'OCR Tesseract sur un PDF de 50 pages peut saturer temporairement un vCPU.
- Caddy : < 30 Mo.
- Bases de données (MariaDB pour Nextcloud + Paperless, Redis) : ~200 Mo combinés.

Total estimé au repos : ~1,6 Go sur les 8 Go disponibles. La marge absorbe les pics et permet d'ajouter un service supplémentaire sans redimensionner.

Ports à ouvrir sur le pare-feu : 80/tcp et 443/tcp uniquement. Tous les autres ports restent fermés — les services internes ne sont pas exposés directement.

Déploiement pas à pas

  1. Préparer le VPS

    Connectez-vous en SSH à votre VPS et mettez à jour le système : apt update && apt upgrade -y. Installez Docker et le plugin Compose : curl -fsSL https://get.docker.com | sh. Vérifiez l'installation : docker compose version. Créez un utilisateur non-root dédié et ajoutez-le au groupe docker : adduser deploy && usermod -aG docker deploy. Activez UFW avec les règles minimales : ufw allow 22/tcp && ufw allow 80/tcp && ufw allow 443/tcp && ufw enable.

  2. Configurer le DNS

    Dans votre zone DNS, créez un enregistrement A pour le domaine racine pointant vers l'IP de votre VPS, puis des sous-domaines CNAME ou A pour chaque service : nextcloud.votre-domaine.com, vault.votre-domaine.com, jellyfin.votre-domaine.com, photos.votre-domaine.com et docs.votre-domaine.com. Si vous utilisez le défi DNS-01 de Caddy pour le certificat wildcard, assurez-vous que votre fournisseur DNS dispose d'une API supportée par le module caddy-dns correspondant. Attendez la propagation DNS (quelques minutes à quelques heures selon le TTL configuré).

  3. Créer la structure de dossiers

    Créez l'arborescence du projet sur le VPS : mkdir -p /opt/homelab/{caddy,nextcloud,vaultwarden,jellyfin,immich,paperless}. Ce répertoire contiendra le fichier docker-compose.yml, le Caddyfile et les fichiers d'environnement. Les données persistantes seront stockées dans des volumes Docker nommés, pas dans des bind-mounts, pour simplifier les sauvegardes et éviter les problèmes de permissions.

  4. Écrire le Caddyfile

    Dans /opt/homelab/caddy/Caddyfile, déclarez un bloc par sous-domaine. Exemple pour Nextcloud : nextcloud.votre-domaine.com { reverse_proxy nextcloud:80 }. Répétez le motif pour chaque service en pointant vers le nom de service Docker (vaultwarden, jellyfin, immich-server, paperless-webserver). Caddy obtient et renouvelle les certificats Let's Encrypt automatiquement au premier démarrage. Pour un certificat wildcard, remplacez les blocs individuels par *.votre-domaine.com avec le module DNS de votre fournisseur, configuré via les variables d'environnement de l'image Caddy personnalisée.

  5. Écrire le docker-compose.yml

    Créez /opt/homelab/docker-compose.yml avec un réseau proxy partagé et un réseau internal isolé. Déclarez le service Caddy avec ports: ["80:80", "443:443"] et volumes: ["./caddy/Caddyfile:/etc/caddy/Caddyfile", "caddy_data:/data"]. Pour chaque application, déclarez networks: [proxy, internal] et n'exposez aucun port ports: — seul Caddy expose des ports publics. Utilisez depends_on avec condition: service_healthy pour que Nextcloud n'essaie pas de rejoindre MariaDB avant qu'elle soit prête. Les variables sensibles (mots de passe de bases de données, clés secrètes) passent dans un fichier .env référencé par env_file: .env.

  6. Configurer les variables d'environnement

    Créez /opt/homelab/.env avec les variables requises par chaque service : MYSQL_ROOT_PASSWORD, MYSQL_DATABASE, MYSQL_USER, MYSQL_PASSWORD pour MariaDB, NEXTCLOUD_ADMIN_USER, NEXTCLOUD_ADMIN_PASSWORD, NEXTCLOUD_TRUSTED_DOMAINS pour Nextcloud, VAULTWARDEN_ADMIN_TOKEN pour Vaultwarden. Générez les secrets avec openssl rand -hex 32. Pour Immich, copiez le fichier .env d'exemple depuis le dépôt officiel — il déclare les variables requises et leurs valeurs par défaut. Ne commitez jamais ce fichier dans un dépôt public ; ajoutez .env à votre .gitignore.

  7. Lancer le stack

    Depuis /opt/homelab, lancez docker compose pull pour télécharger toutes les images, puis docker compose up -d pour démarrer l'ensemble. Suivez les logs au démarrage avec docker compose logs -f pour vous assurer que chaque service démarre sans erreur. La première initialisation de Nextcloud et Paperless-ngx peut prendre quelques minutes (migrations de base de données, génération des clés). Caddy obtient les certificats TLS lors du premier accès à chaque sous-domaine — vérifiez que les ports 80 et 443 sont accessibles depuis l'extérieur avant de tester.

  8. Finaliser la configuration de chaque service

    Accédez à chaque interface web pour finaliser la configuration initiale : Nextcloud (nextcloud.votre-domaine.com) pour activer les applications recommandées (Contacts, Calendrier, Talk) ; Immich (photos.votre-domaine.com) pour configurer les bibliothèques et activer les tâches d'apprentissage automatique en arrière-plan ; Paperless-ngx (docs.votre-domaine.com) pour configurer le consommateur de documents et l'OCR ; Jellyfin (jellyfin.votre-domaine.com) pour pointer vers les dossiers de médias montés en volume. Vaultwarden (vault.votre-domaine.com) ne nécessite qu'une création de compte depuis le client Bitwarden — aucune configuration serveur initiale.

Caddy, Nginx Proxy Manager ou Traefik : quel reverse proxy pour ce stack

Faites défiler le tableau

CritèreCaddyNginx Proxy ManagerTraefik
ConfigurationCaddyfile déclaratif, rechargement sans downtimeInterface web, aucun fichier à éditerLabels Docker, recharge automatiquement
SSL automatiqueIntégré, DNS-01 et HTTP-01 natifsLet's Encrypt via l'interface, DNS-01 possibleLet's Encrypt via ACME resolver, DNS-01 via providers
WildcardNatif via module caddy-dnsPossible mais demande configuration manuelleNatif via certificateResolvers
Courbe d'apprentissageFaible — Caddyfile lisible en 10 minutesTrès faible — tout se fait en clicsMoyenne — documentation volumineuse
Adapté à ce stackOui — configuration versionnée, rechargement en ligneOui pour débuter, moins idéal pour versionnerOui pour les stacks plus complexes, surcoût de config ici

Durcissement minimal avant exposition publique

Quatre mesures à appliquer avant de rendre le stack accessible depuis l'extérieur :

1. Désactivez la page d'inscription ouverte de Vaultwarden en posant SIGNUPS_ALLOWED=false dans le .env une fois votre compte créé.
2. Ajoutez un en-tête X-Robots-Tag: noindex dans le Caddyfile pour Vaultwarden et l'interface d'administration de Paperless-ngx — ces pages n'ont pas à être indexées.
3. Activez la rotation des journaux Docker (log-opts dans /etc/docker/daemon.json) pour éviter que les logs de Jellyfin ou de Paperless-ngx ne saturent le disque.
4. Planifiez un docker compose pull && docker compose up -d hebdomadaire via cron pour maintenir les images à jour — les applications self-hosted publient régulièrement des correctifs de sécurité. Vérifiez les changelogs avant de mettre à jour Immich, qui peut introduire des migrations de base de données non réversibles.

Dépannage : erreurs courantes au démarrage

Error response from daemon: network proxy declared as external, but could not be found — Ce message apparaît quand le réseau Docker externe déclaré dans docker-compose.yml n'existe pas encore. Créez-le manuellement avant le premier docker compose up : docker network create proxy. Ou passez le réseau en interne au Compose (retirez external: true) pour que Compose le crée lui-même.

nextcloud.votre-domaine.com redirected you too many times — Nextcloud détecte la requête HTTPS comme HTTP car Caddy la retransmet en HTTP sur le réseau interne. Ajoutez NEXTCLOUD_TRUSTED_PROXIES avec le sous-réseau Docker (ex. 172.16.0.0/12) et OVERWRITEPROTOCOL=https dans le .env. Sans ces variables, Nextcloud ne fait pas confiance aux en-têtes X-Forwarded-Proto transmis par Caddy et tente de rediriger vers HTTPS indéfiniment.

Immich cannot connect to database: connection refused — Immich démarre avant que PostgreSQL soit prêt. Ajoutez depends_on avec condition: service_healthy sur le service immich-server et vérifiez que le service database déclare un healthcheck valide (ex. pg_isready -U immich). Sans healthcheck, Docker Compose considère le service « démarré » dès que le conteneur est lancé, pas dès qu'il accepte des connexions.

Paperless-ngx worker exited with error: celery worker unhealthy — La base Redis n'est pas accessible. Vérifiez que le service Redis est bien dans le même réseau que Paperless et que la variable PAPERLESS_REDIS pointe vers le nom de service Compose (redis://redis:6379), pas vers localhost — dans Docker Compose, localhost dans un conteneur pointe vers le conteneur lui-même, pas vers un autre service.

Caddy ne renouvelle pas le certificat wildcard — Si vous utilisez le défi DNS-01, vérifiez que les variables d'environnement de l'API DNS (token, zone ID) sont bien transmises au service Caddy dans le Compose. Un token expiré ou une permission DNS insuffisante fait échouer silencieusement le renouvellement 30 jours avant l'expiration — Caddy enregistre l'erreur dans ses logs mais ne bloque pas le trafic jusqu'à l'expiration effective.

Pour aller plus loin

Ce stack couvre les cinq services les plus demandés dans les configurations homelab 2026. Chacun dispose d'un guide dédié sur ce blog si vous souhaitez approfondir un aspect particulier : sauvegarde Nextcloud, gestion des albums Immich, transcodage matériel Jellyfin, règles de rétention Paperless-ngx ou synchronisation multi-appareils Vaultwarden.

Pour aller au-delà de ce stack, les prochaines briques habituellement ajoutées sont Uptime Kuma (monitoring des services internes) et Ntfy ou Apprise (notifications push). Ces services sont suffisamment légers pour s'ajouter au même Compose sans impacter le dimensionnement.

Si la gestion manuelle des mises à jour et des sauvegardes devient une charge, Coolify et Dokploy offrent des interfaces qui automatisent ces tâches tout en conservant l'architecture Docker Compose sous-jacente — voir le guide de migration Heroku/Vercel vers VPS pour le contexte.

Un VPS avec accès root pour votre stack homelab

ServOrbit.com propose des VPS cloud à partir de 99 DH/mois, avec IPv4 dédiée, choix d'OS (Ubuntu, Debian, AlmaLinux), réseau haute disponibilité et snapshots. Déployez l'intégralité de ce stack en une seule commande `docker compose up -d`.

Besoin d'aide ?

Parcourez notre centre d'aide et notre FAQ, ou contactez notre équipe — rappel, WhatsApp ou e-mail. Support en français, anglais et arabe.

Écrire sur WhatsApps'ouvre dans un nouvel onglet