--- title: Architecture VPS Docker url: https://blog.guigpap.com/fr/infrastructure/architecture-vps/ url_md: https://blog.guigpap.com/fr/infrastructure/architecture-vps.md category: infrastructure date: '2026-01-19' maturite: production techno: - docker - caddy - crowdsec application: - infrastructure - operations --- # Architecture VPS Docker > Vue d'ensemble de l'infrastructure Docker multi-stack sur Hostinger KVM (7 stacks, réseau webproxy, tunnel SSH dédié) ## 1. Quoi ? — Définition et contexte Une **architecture multi-stack Docker** désigne une organisation où plusieurs groupes de services (stacks) coexistent sur un même serveur, chacun défini par son propre fichier `docker-compose.yaml`. Chaque stack est autonome mais peut communiquer avec les autres via un réseau Docker partagé. Cette infrastructure tourne sur un VPS Hostinger KVM 4 : - **16 GB RAM** / **4 vCPU** / **Debian 13** - **7 stacks Docker** interconnectées - **1 reverse proxy** (Caddy) comme point d'entrée HTTP - **1 tunnel SSH dédié** comme point d'entrée hors HTTP (pour TimeTrackr) > **Note - Stack Docker** > > Une **stack** est un ensemble cohérent de containers qui remplissent une fonction (sécurité, automatisation, ERP, …). Docker Compose démarre, arrête et gère tous les containers d'une stack comme une unité. ### Vue d'ensemble des 7 stacks | Stack | Services | Fonction | RAM ordre de grandeur | |-------|----------|----------|----------------------| | [security-stack](/fr/infrastructure/security-stack/) | Caddy, CrowdSec, Trivy | Reverse proxy + WAF + scanner CVE | ~500 MB | | [n8n-stack](/fr/infrastructure/n8n-queue-mode/) | N8N main + 5 workers, PostgreSQL, Redis | Automatisation queue mode | ~2 GB | | [ai-stack](/fr/infrastructure/ai-stack/) | Qdrant, CLI Ollama, Claude Redis, MCP Gateway, N8N MCP | IA, vecteurs, MCP | ~4 GB | | [odoo-stack](/fr/infrastructure/odoo-18-setup/) | Odoo 18, PostgreSQL | ERP (DB `guig_db`) | ~1.5 GB | | [monitoring-stack](/fr/infrastructure/monitoring-stack/) | Prometheus, Grafana, Alertmanager, OTEL Collector, exporters | Observabilité + telemetry | ~1.5 GB | | [notify-stack](/fr/infrastructure/notify-stack/) | DIUN, ntfy | Notifications + détection updates | ~200 MB | | [timetrackr-stack](/fr/infrastructure/timetrackr-stack/) | PostgreSQL 17 (tunnel SSH dédié) | Buffer time tracking | ~150 MB | ### Topologie réseau ```mermaid flowchart TB Internet([Internet]) SSHClient(["TimeTrackr.exe · poste utilisateur"]) subgraph Edge["Points d'entrée"] direction TB Caddy["Caddy · :80, :443, :443/udp"] SSH["sshd · :22 · timetrackr-tunnel restreint"] end Internet -->|HTTPS / HTTP3| Caddy SSHClient -->|SSH key + ForceCommand| SSH subgraph WP["réseau webproxy (partagé)"] direction TB Sec["security-stack · CrowdSec, Trivy"] N8NMain["n8n-stack · N8N main + 5 workers"] AI["ai-stack · CLI Ollama, MCP Gateway"] Odoo["odoo-stack · :8069, DB guig_db"] Mon["monitoring-stack · Grafana, Prometheus"] NT["notify-stack · ntfy"] end subgraph Isolated["Réseaux isolés"] direction TB AIBack["mcp-backend · gateway ↔ n8n-mcp"] Qdrant["ai-internal · Qdrant, Claude Redis"] TT["timetrackr-internal · PG 17"] end Caddy --> Sec Caddy --> N8NMain Caddy --> Odoo Caddy --> Mon Caddy --> NT AI --- AIBack AI --- Qdrant SSH -->|"forward 5433"| TT ``` Trois familles de réseaux Docker se côtoient : - **`webproxy`** — bridge partagé, point de routage de Caddy. - **Réseaux internes par stack** (`n8n-internal`, `odoo-internal`, `monitoring`, `ai-internal`) — communication intra-stack. - **Réseaux isolés** (`mcp-backend`, `timetrackr-internal`, `crowdsec-internal`) — surfaces réduites pour les composants sensibles (MCP gateway, base TimeTrackr, API CrowdSec). --- ## 2. Pourquoi ? — Enjeux et motivations ### Pourquoi Docker Compose plutôt que Kubernetes ? 1. **Simplicité opérationnelle** — Kubernetes introduit etcd, control plane, ingress controllers, inadaptés à un serveur unique. Docker Compose démarre une stack en une commande. 2. **Contraintes de ressources** — L'overhead Kubernetes (2-4 GB RAM pour le control plane) consommerait 15-25 % du VPS. Docker Compose n'a pas cet overhead. 3. **Pas de besoin de scaling horizontal** — Pas d'auto-scaling, pas de répartition multi-nœuds. Le scaling vertical (plus de RAM/CPU) suffit. 4. **Courbe d'apprentissage** — Compose est maîtrisé, Kubernetes serait un investissement disproportionné pour ce cas d'usage. > **Tip - Quand Kubernetes devient pertinent** > > Quand on a besoin de : haute disponibilité multi-nœuds, auto-scaling sur la charge, déploiements blue-green automatisés, ou gestion de plusieurs serveurs comme un cluster. ### Problèmes résolus par l'approche multi-stack | Problème | Solution | |----------|----------| | **Isolation des pannes** | Une stack défaillante n'impacte pas les autres | | **Déploiement indépendant** | Mise à jour d'un service sans redémarrer tout le système | | **Versions divergentes** | Chaque stack gère ses dépendances (PG 15 pour N8N/Odoo, PG 17 pour TimeTrackr) | | **Sécurité par segmentation** | Surfaces minimales : MCP backend isolé, base TimeTrackr hors webproxy | | **Observabilité** | Stack dédiée qui scrape toutes les autres | --- ## 3. Comment ? — Mise en œuvre technique ### Structure du dépôt ``` stacks_vps/ ├── security-stack/ # Caddy + CrowdSec + Trivy ├── n8n-stack/ # N8N en mode queue, 5 workers ├── ai-stack/ # Qdrant + CLI Ollama + MCP Gateway + N8N MCP ├── odoo-stack/ # Odoo 18 ERP (DB guig_db) ├── monitoring-stack/ # Prometheus + Grafana + OTEL ├── notify-stack/ # DIUN + ntfy ├── timetrackr-stack/ # PostgreSQL 17 + tunnel SSH (hors webproxy) ├── workflows/ # Documentation des workflows N8N ├── docs-external/ # 📦 Submodule : docs CLI externes ├── n8n-exports/ # 📦 Submodule : exports workflows N8N ├── blog/ # 📦 Submodule : ce blog (Astro) └── scripts/ # deploy-all.sh, backup-databases.sh, … ``` > **Caution - Submodules Git** > > `docs-external/`, `n8n-exports/` et `blog/` sont des submodules. Après un clone : `git submodule update --init --recursive` (ou `./scripts/setup-dev.sh`). ### Réseau Docker partagé Toutes les stacks **HTTP** se branchent sur le réseau externe `webproxy` : ```yaml networks: webproxy: external: true ``` Ce réseau bridge permet à Caddy d'atteindre n'importe quel container par son nom (`n8n:5678`, `odoo:8069`, `grafana:3000`, `ntfy:80`, …). **Exception : `timetrackr-stack`** ne touche pas `webproxy`. Sa base PostgreSQL est exposée uniquement sur `127.0.0.1:5433`, et l'accès passe par un user SSH dédié (`timetrackr-tunnel`) avec `ForceCommand /bin/false` et `PermitOpen localhost:5433`. Voir [TimeTrackr Stack](/fr/infrastructure/timetrackr-stack/) pour le détail. ### Commandes de déploiement ```bash # Créer le réseau partagé (une seule fois) docker network create webproxy # Démarrer toutes les stacks ./scripts/deploy-all.sh start # Status ./scripts/deploy-all.sh status # Logs d'une stack ./scripts/deploy-all.sh logs n8n-stack # Redémarrer ./scripts/deploy-all.sh restart odoo-stack # Pull + redémarrage ./scripts/deploy-all.sh pull ``` ### Ordre de démarrage recommandé 1. **security-stack** — Le reverse proxy doit être prêt avant les autres pour terminer les handshakes TLS. 2. **monitoring-stack** — Pour capter l'historique de scrape dès le boot des autres. 3. **ai-stack**, **n8n-stack**, **odoo-stack**, **notify-stack** — Dans n'importe quel ordre. 4. **timetrackr-stack** — Indépendante (n'a pas besoin de webproxy). ### Sauvegardes Le script `scripts/backup-databases.sh` (cron quotidien 03:00) produit : - `pg_dump` de la base N8N (`n8n`). - `pg_dump` de la base Odoo (`guig_db`) + archive du filestore. - `pg_dump` de la base TimeTrackr (`timetrackr_db`). - Sauvegarde de la `N8N_ENCRYPTION_KEY` (sans elle, les credentials sont irrécupérables). Rotation locale (7 jours) et push GDrive (30 jours) via `rclone`. Échec → alerte au [Notification Hub](/fr/workflows/notification-hub/). --- ## 4. Et si ? — Perspectives et limites ### Limites actuelles | Limite | Impact | Mitigation | |--------|--------|------------| | **Serveur unique** | SPOF physique | Backups quotidiens GDrive + monitoring + alertes | | **Pas de HA native** | Downtime au pull/restart | Fenêtres planifiées, self-restart pattern pour n8n-stack | | **Scaling vertical uniquement** | Plafond matériel KVM 4 | Migration vers KVM 8 ou multi-nœuds possible | | **AI stack la plus gourmande** | ~4 GB sur 16 disponibles | Sub-processus CLI court-vivants, pas de modèle local | ### Scénarios d'évolution **Si je dois répliquer ce setup pour un autre client** : - Les stacks deviennent des modèles, packagés en namespaces Kubernetes (ou Compose templates). - Helm charts pour les variations par client (DB names, secrets, domaines). **Si les besoins IA explosent** : - L'ai-stack devient externalisable vers un cloud GPU (l'interface API Ollama-compatible facilite le swap). - Garder Qdrant local pour la latence RAG, pousser CLI Ollama vers un host dédié. **Si 16 GB devient insuffisant** : - Upgrade KVM 8 (32 GB) — solution la plus simple. - Ou déporter monitoring + notify sur un second serveur, le webproxy peut s'étendre en overlay multi-host. **Si la souveraineté SSH doit être renforcée** : - Migration du tunnel TimeTrackr vers WireGuard (`wg.guigpap.com`). - Permet d'ouvrir d'autres services privés (admin Postgres, Redis interne) sans multiplier les bouncers SSH. > **Note - Architecture pérenne** > > Ce setup couvre les besoins actuels et prévisibles à 12-18 mois. Sa modularité permet une évolution progressive (par stack) sans refonte complète. --- ## Pages liées ### Infrastructure - [Security Stack](/fr/infrastructure/security-stack/) — Caddy + CrowdSec + Trivy + llms.txt - [N8N en mode Queue](/fr/infrastructure/n8n-queue-mode/) — Automatisation scalable - [AI Stack](/fr/infrastructure/ai-stack/) — Qdrant + CLI Ollama + MCP Gateway - [Odoo 18 sur Docker](/fr/infrastructure/odoo-18-setup/) — Configuration ERP, modules custom - [Monitoring Stack](/fr/infrastructure/monitoring-stack/) — Prometheus + Grafana + Telemetry → Odoo - [Notify Stack](/fr/infrastructure/notify-stack/) — DIUN + ntfy - [TimeTrackr Stack](/fr/infrastructure/timetrackr-stack/) — PostgreSQL 17 + tunnel SSH - [Pourquoi Odoo](/fr/infrastructure/why-odoo/) — Choix de l'ERP ### Workflows orchestrant ces stacks - [Telegram Orchestrator](/fr/workflows/telegram-orchestrator/) — Hub de contrôle - [Docker Updates](/fr/workflows/docker-updates/) — Auto-update via DIUN + approbation - [Notification Hub](/fr/workflows/notification-hub/) — Routage centralisé - [Claude Code Telemetry](/fr/workflows/claude-code-telemetry/) — Sessions → Odoo via Prometheus - [GitHub-Odoo Sync](/fr/workflows/github-odoo-sync/) — Issues / PRs / commits → tâches Odoo - [TimeTrackr → Odoo](/fr/workflows/timetrackr/) — Timesheets via webhooks ### Référence - [Glossaire](/fr/reference/glossary/) — Définitions des termes techniques ## Metadonnees agent - Cet article est issu du blog GuiGPaP Lab. - Contexte global du blog: https://blog.guigpap.com/llms.txt - Contact auteur: https://odoo.guigpap.com/mon-cv - Licence: CC-BY-SA 4.0