# ARCHITECTURE โ€” Vue d'ensemble technique > Comprendre comment tout s'imbrique dans l'infra Seize. --- ## ๐Ÿ—๏ธ Vue d'ensemble ``` Internet โ”‚ โ”‚ HTTPS (443) / HTTP (80) โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Traefik (proxy) โ”‚ โ”‚ - Let's Encrypt โ”‚ โ”‚ - Routing par Host โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ–ผ โ–ผ โ–ผ โ–ผ โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” ... โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Zitadel โ”‚ โ”‚ OAuth2-Proxyโ”‚ โ”‚ OAuth2-Proxyโ”‚ โ”‚ Gitea โ”‚ โ”‚ (sso.*) โ”‚ โ”‚ (intranet) โ”‚ โ”‚ (n8n) โ”‚ โ”‚ (git.*) SSO โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ integrรฉ โ”‚ โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ”‚ Auth OIDC โ”‚ Forward proxy โ”‚ Forward proxy โ”‚ โ–ผ โ–ผ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ Intranet โ”‚ โ”‚ n8n โ”‚ โ”‚ โ”‚ (nginx) โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ + RBAC JS โ”‚ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ”‚ โ–ผ โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Postgres โ”‚ โ”‚ Postgres โ”‚ โ”‚ (zitadel)โ”‚ โ”‚ (n8n) โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` --- ## ๐ŸŒ Rรฉseaux Docker | Rรฉseau | Type | Utilisรฉ par | |---|---|---| | `web` | external | Traefik, tous les services exposรฉs publiquement | | `backend` | external | Postgres, Redis, et services backend internes | | `zitadel` | local | Zitadel + son Traefik dรฉdiรฉ + Postgres | | `proxy` | bridge | Rรฉseau auxiliaire (vรฉrifier usage) | โš ๏ธ **Important** : Zitadel a son **propre rรฉseau** + son **propre Traefik** (intรฉgrรฉ dans son docker-compose). Il est totalement isolรฉ du Traefik principal pour des raisons de sรฉcuritรฉ. Le Traefik principal route uniquement vers le Traefik Zitadel sur `sso.seizeconsulting.com`. --- ## ๐Ÿ” Flux d'authentification SSO ### Flux complet pour un user accรฉdant ร  l'intranet ``` 1. User โ†’ https://intranet.seizeconsulting.com โ”‚ โ–ผ 2. Traefik principal โ†’ route vers OAuth2-Proxy "intranet" โ”‚ โ–ผ 3. OAuth2-Proxy vรฉrifie le cookie de session โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ” โ”‚ Pas de โ”‚ โ”‚ session โ”‚ โ–ผ โ”‚ 4. OAuth2-Proxy redirige vers Zitadel (URL : /oauth2/start โ†’ Zitadel login) โ”‚ โ–ผ 5. User saisit ses identifiants Zitadel + MFA โ”‚ โ–ผ 6. Zitadel valide + gรฉnรจre un code OIDC โ”‚ โ–ผ 7. Redirect vers OAuth2-Proxy /oauth2/callback?code=xxx โ”‚ โ–ผ 8. OAuth2-Proxy รฉchange le code contre un token JWT (avec scope : openid email profile urn:zitadel:iam:org:project:roles) โ”‚ โ–ผ 9. OAuth2-Proxy stocke le token + cookie de session โ”‚ โ–ผ 10. OAuth2-Proxy โ†’ forward request vers nginx (intranet) avec headers : - X-Forwarded-User: - X-Forwarded-Email: hedi.kalboussi@seizeconsulting.com - X-Forwarded-Preferred-Username: HKA - Authorization: Bearer โ”‚ โ–ผ 11. nginx lit le header X-Forwarded-Email Substitue __USER_EMAIL__ par la vraie valeur dans index.html (sub_filter) โ”‚ โ–ผ 12. Browser reรงoit l'HTML avec const USER_EMAIL = "hedi.kalboussi@..." โ”‚ โ–ผ 13. JavaScript : - Fetch /roles-mapping.json - Lookup userEmail โ†’ role (ex: "consultant_junior") - Cache les cartes que ce rรดle n'a pas le droit de voir โ”‚ โ–ผ 14. User voit uniquement les cartes autorisรฉes ``` --- ## ๐Ÿ—‚๏ธ Structure des dossiers Docker sur le serveur ``` /home/hedi/docker/ โ”œโ”€โ”€ traefik/ # Reverse proxy principal โ”‚ โ”œโ”€โ”€ docker-compose.yml โ”‚ โ”œโ”€โ”€ traefik.yml # Config statique โ”‚ โ”œโ”€โ”€ dynamic.yml # Config dynamique (middlewares, etc.) โ”‚ โ””โ”€โ”€ letsencrypt/ # Certificats TLS auto โ”‚ โ”œโ”€โ”€ zitadel/ # IDP Zitadel (avec son propre Traefik) โ”‚ โ”œโ”€โ”€ docker-compose.yml # Multi-services (proxy + login + api + db) โ”‚ โ”œโ”€โ”€ .env # Tous les secrets Zitadel โ”‚ โ””โ”€โ”€ machinekey/ # Clรฉs service accounts โ”‚ โ”œโ”€โ”€ postgres/ # Postgres principal (Gitea, n8n, Authentik historique) โ”‚ โ”œโ”€โ”€ docker-compose.yml โ”‚ โ””โ”€โ”€ data/ # Persistance โ”‚ โ”œโ”€โ”€ redis/ # Plus utilisรฉ (Authentik historique) โ”‚ โ”œโ”€โ”€ intranet/ # โญ Page d'accueil avec RBAC โ”‚ โ”œโ”€โ”€ docker-compose.yml โ”‚ โ”œโ”€โ”€ index.html # HTML avec data-app="xxx" + script RBAC โ”‚ โ”œโ”€โ”€ roles-mapping.json # Mapping email โ†’ rรดle (gรฉnรฉrรฉ par script) โ”‚ โ”œโ”€โ”€ nginx-rbac.conf # nginx avec sub_filter pour __USER_EMAIL__ โ”‚ โ””โ”€โ”€ logo.png โ”‚ โ”œโ”€โ”€ gitea/ # Forge Git avec SSO Zitadel intรฉgrรฉ โ”‚ โ”œโ”€โ”€ docker-compose.yml โ”‚ โ”œโ”€โ”€ .env โ”‚ โ””โ”€โ”€ data/ โ”‚ โ”œโ”€โ”€ n8n/ # Workflows โ”‚ โ”œโ”€โ”€ docker-compose.yml โ”‚ โ”œโ”€โ”€ .env โ”‚ โ””โ”€โ”€ data/ โ”‚ โ”œโ”€โ”€ portainer/ # Gestion Docker โ”‚ โ”œโ”€โ”€ docker-compose.yml โ”‚ โ””โ”€โ”€ data/ โ”‚ โ”œโ”€โ”€ code-server/ # VS Code dans le navigateur โ”‚ โ”œโ”€โ”€ docker-compose.yml โ”‚ โ”œโ”€โ”€ .env โ”‚ โ””โ”€โ”€ config/ โ”‚ โ”œโ”€โ”€ uptime-kuma/ # Monitoring โ”‚ โ”œโ”€โ”€ docker-compose.yml โ”‚ โ””โ”€โ”€ data/ โ”‚ โ”œโ”€โ”€ oauth2-proxy/ # โญ OAuth2-Proxy pour l'intranet โ”‚ โ”œโ”€โ”€ docker-compose.yml โ”‚ โ””โ”€โ”€ .env โ”‚ โ”œโ”€โ”€ oauth2-proxy-n8n/ # OAuth2-Proxy pour n8n โ”‚ โ”œโ”€โ”€ docker-compose.yml โ”‚ โ””โ”€โ”€ .env โ”‚ โ”œโ”€โ”€ oauth2-proxy-portainer/ # OAuth2-Proxy pour Portainer โ”‚ โ”œโ”€โ”€ docker-compose.yml โ”‚ โ””โ”€โ”€ .env โ”‚ โ”œโ”€โ”€ oauth2-proxy-code/ # OAuth2-Proxy pour Code Server โ”‚ โ”œโ”€โ”€ docker-compose.yml โ”‚ โ””โ”€โ”€ .env โ”‚ โ”œโ”€โ”€ oauth2-proxy-status/ # OAuth2-Proxy pour Uptime Kuma โ”‚ โ”œโ”€โ”€ docker-compose.yml โ”‚ โ””โ”€โ”€ .env โ”‚ โ”œโ”€โ”€ authentik/ # โŒ Plus utilisรฉ (ร  archiver/supprimer) โ”‚ โ”œโ”€โ”€ whoami/ # Test debug (ร  garder ou supprimer) โ”‚ โ””โ”€โ”€ ctop/ # Outil CLI monitoring conteneurs ``` --- ## ๐ŸŽญ Le pattern "OAuth2-Proxy par outil" ### Pourquoi ce pattern ? Chaque outil (n8n, Portainer, etc.) a son **propre OAuth2-Proxy dรฉdiรฉ**. C'est volontaire : โœ… **Avantages** : - Configuration diffรฉrenciรฉe par outil (scopes, callbacks, etc.) - Pas de SPOF : si un OAuth2-Proxy crash, les autres outils marchent - Plus simple ร  dรฉbugger - Permet d'avoir des secrets/clients OIDC diffรฉrents โŒ **Inconvรฉnients** : - 5 conteneurs OAuth2-Proxy en plus (impact RAM minime) - 5 configurations ร  maintenir ### Anatomie d'un OAuth2-Proxy Pour chaque outil, on a : 1. **Un dossier `~/docker/oauth2-proxy-/`** 2. **Un `docker-compose.yml`** avec labels Traefik routant `.seizeconsulting.com` โ†’ OAuth2-Proxy port 4180 3. **Un `.env`** avec : - `OAUTH2_PROXY_PROVIDER=oidc` - `OAUTH2_PROXY_CLIENT_ID=` - `OAUTH2_PROXY_CLIENT_SECRET=` - `OAUTH2_PROXY_OIDC_ISSUER_URL=https://sso.seizeconsulting.com` - `OAUTH2_PROXY_REDIRECT_URL=https://.seizeconsulting.com/oauth2/callback` - `OAUTH2_PROXY_UPSTREAMS=http://:` - `OAUTH2_PROXY_COOKIE_SECRET=<32_chars_random>` - `OAUTH2_PROXY_SCOPE=openid email profile urn:zitadel:iam:org:project:roles` 4. **Une App crรฉรฉe dans Zitadel** (project "Infra Seize") avec les bons callbacks Dรฉtails complets dans [docs/04-oauth2-proxy-pattern.md](./docs/04-oauth2-proxy-pattern.md). --- ## ๐Ÿงฌ Le bug Traefik historique (ร  connaรฎtre) **Symptรดme initial** : tous les outils SSO รฉtaient dรฉconnectรฉs ร  chaque requรชte. **Cause** : Traefik supprimait par dรฉfaut le header `Cookie` quand il faisait un ForwardAuth vers OAuth2-Proxy. Du coup OAuth2-Proxy ne voyait pas le cookie de session et redirigeait vers login ร  chaque fois. **Fix** : ajouter dans `~/docker/traefik/dynamic.yml` : ```yaml http: middlewares: oauth2-headers: forwardAuth: address: "http://oauth2-proxy:4180/oauth2/auth" authRequestHeaders: - Cookie # โ† LIGNE CRITIQUE - Authorization authResponseHeaders: - X-Auth-Request-User - X-Auth-Request-Email ``` โ†’ Sans `Cookie` dans `authRequestHeaders`, **rien ne fonctionne**. --- ## ๐ŸŽฏ RBAC : architecture choisie (Approche A) ``` 1. Furious Squad (source de vรฉritรฉ RH) โ”‚ โ”‚ API GraphQL-like โ–ผ 2. Scripts Python d'import (~/furious-to-zitadel/) โ”‚ โ–ผ 3. Zitadel : 88 users avec metadata custom โ”‚ โ–ผ 4. Script generate-roles-mapping.py โ†’ gรฉnรจre /docker/intranet/roles-mapping.json โ”‚ โ–ผ 5. Intranet (nginx + sub_filter) โ†’ injecte __USER_EMAIL__ depuis X-Forwarded-Email โ†’ JavaScript lookup dans roles-mapping.json โ†’ cache/affiche les cartes selon rรดle ``` ### Pourquoi Approche A (et pas RBAC complet sur chaque outil) ? Dรฉtails dans [DECISIONS.md](./DECISIONS.md), section "RBAC Approche A". **TL;DR** : 0โ‚ฌ, 2-3h de boulot, suffisant pour Seize (88 employรฉs majoritairement non-techniques). --- ## ๐Ÿ“Š Volumes critiques ร  backuper | Donnรฉes | Volume / Chemin | Criticitรฉ | |---|---|---| | Base PostgreSQL Zitadel | `~/docker/zitadel/.../data/postgres/` | ๐Ÿ”ด Critique | | Base PostgreSQL Gitea/n8n | `~/docker/postgres/data/` | ๐Ÿ”ด Critique | | Donnรฉes Gitea (repos) | `~/docker/gitea/data/` | ๐Ÿ”ด Critique | | Donnรฉes Portainer | `~/docker/portainer/data/` | ๐ŸŸก Important | | Donnรฉes Uptime Kuma | `~/docker/uptime-kuma/data/` | ๐ŸŸก Important | | Donnรฉes n8n | volume Docker `n8n_data` | ๐ŸŸก Important | | Donnรฉes Code Server | `~/docker/code-server/config/` | ๐ŸŸข Rรฉcupรฉrable | | Certificats Let's Encrypt | `~/docker/traefik/letsencrypt/` | ๐ŸŸข Auto-rรฉgรฉnรฉrรฉ | | Scripts d'import + clรฉs | `~/furious-to-zitadel/` | ๐Ÿ”ด Critique | โš ๏ธ **Aucun backup automatique en place** au moment de la passation. ร€ mettre en prioritรฉ. --- ## ๐Ÿ”ง Outils CLI utiles installรฉs | Outil | Usage | |---|---| | `docker` | Gestion conteneurs | | `docker compose` | Orchestration | | `ctop` | Top des conteneurs (consommation ressources) | | `sudo journalctl` | Logs systรจme | | `htop` | Top processus | | `python3` + venv | Pour les scripts d'import | --- ## ๐ŸŒ DNS โ€” Records configurรฉs (chez le registrar) Tous les sous-domaines pointent vers `151.115.148.243` : | Record | Type | Valeur | |---|---|---| | `seizeconsulting.com` | A | 151.115.148.243 | | `sso.seizeconsulting.com` | A | 151.115.148.243 | | `intranet.seizeconsulting.com` | A | 151.115.148.243 | | `git.seizeconsulting.com` | A | 151.115.148.243 | | `n8n.seizeconsulting.com` | A | 151.115.148.243 | | `portainer.seizeconsulting.com` | A | 151.115.148.243 | | `code.seizeconsulting.com` | A | 151.115.148.243 | | `status.seizeconsulting.com` | A | 151.115.148.243 | | `traefik.seizeconsulting.com` | A | 151.115.148.243 | | `app.seizeconsulting.com` | A | 151.115.148.243 | โš ๏ธ **Ne PAS oublier** d'ajouter un record DNS si tu ajoutes un nouvel outil. Sinon Let's Encrypt รฉchoue.