# 05 — Applications déployées > Détails de chaque application protégée par SSO. --- ## 📋 Vue d'ensemble | App | Image Docker | SSO via | Port interne | URL | |---|---|---|---|---| | Gitea | `gitea/gitea:1.22` | OIDC natif | 3000 (HTTP), 22 (SSH) | git.seizeconsulting.com | | n8n | `n8nio/n8n:latest` | OAuth2-Proxy | 5678 | n8n.seizeconsulting.com | | Portainer | `portainer/portainer-ce:latest` | OAuth2-Proxy | 9000 | portainer.seizeconsulting.com | | Code Server | `lscr.io/linuxserver/code-server:latest` | OAuth2-Proxy | 8443 | code.seizeconsulting.com | | Uptime Kuma | `louislam/uptime-kuma:1` | OAuth2-Proxy | 3001 | status.seizeconsulting.com | --- ## 🐙 Gitea ### Spécificité : SSO OIDC natif Contrairement aux autres, Gitea **ne passe PAS par OAuth2-Proxy**. Il a sa propre intégration OIDC. ### docker-compose.yml (résumé) Voir `configs/gitea/docker-compose.yml.template`. ```yaml services: gitea: image: gitea/gitea:1.22 container_name: gitea environment: USER_UID: 1000 USER_GID: 1000 GITEA__database__DB_TYPE: postgres GITEA__database__HOST: postgres:5432 GITEA__database__NAME: gitea GITEA__database__USER: gitea GITEA__database__PASSWD: ${GITEA_DB_PASSWORD} GITEA__server__DOMAIN: git.seizeconsulting.com GITEA__server__ROOT_URL: https://git.seizeconsulting.com/ GITEA__server__SSH_DOMAIN: git.seizeconsulting.com # Auto-registration via OIDC GITEA__oauth2_client__ENABLE_AUTO_REGISTRATION: "true" GITEA__oauth2_client__USERNAME: preferred_username GITEA__oauth2_client__ACCOUNT_LINKING: auto # Désactiver le register manuel (SSO uniquement) GITEA__service__DISABLE_REGISTRATION: "true" volumes: - ./data:/data - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro ports: - "22:22" # SSH Git labels: - "traefik.enable=true" - "traefik.http.routers.gitea.rule=Host(`git.seizeconsulting.com`)" - "traefik.http.routers.gitea.entrypoints=websecure" - "traefik.http.routers.gitea.tls.certresolver=letsencrypt" - "traefik.http.services.gitea.loadbalancer.server.port=3000" networks: - web - backend ``` ### Configuration SSO côté Gitea (après premier login) 1. Aller sur `https://git.seizeconsulting.com` → setup initial 2. Créer un compte admin Gitea (local, sera utilisé pour configurer le reste) 3. Site Administration → Authentication Sources → Add : - Type : **OAuth2** - Authentication Name : `Zitadel` - OAuth2 Provider : **OpenID Connect** - Client ID : `` - Client Secret : `` - OpenID Connect Auto Discovery URL : `https://sso.seizeconsulting.com/.well-known/openid-configuration` - Skip Local 2FA : ✅ (Zitadel gère MFA) 4. **Save** ### Configuration côté Zitadel Créer une app dans Projects → Infra Seize → Applications : - Type : Web - Authentication Method : Basic - Grant Type : Authorization Code - Redirect URL : `https://git.seizeconsulting.com/user/oauth2/Zitadel/callback` - Post-logout Redirect : `https://git.seizeconsulting.com/` - Token Settings : JWT + User profile info dans ID Token ### Caractéristiques - ✅ **Auto-registration** : à la 1ère connexion via SSO, le compte Gitea est auto-créé - ✅ **Username = trigramme** (lu depuis `preferred_username` Zitadel) - ❌ **Registration manuelle désactivée** : SSO obligatoire pour les nouveaux users ### Rôles RBAC Gitea n'utilise **pas** les rôles Zitadel directement. Les permissions Gitea sont gérées en interne (organizations, teams, repos). Pour l'instant, **tous les users ont accès en lecture** sur les repos publics. À configurer plus tard : créer des **organizations** par BU et donner accès en fonction. --- ## ⚙️ n8n ### docker-compose.yml (résumé) ```yaml services: n8n: image: n8nio/n8n:latest container_name: n8n environment: DB_TYPE: postgresdb DB_POSTGRESDB_HOST: postgres DB_POSTGRESDB_PORT: 5432 DB_POSTGRESDB_DATABASE: n8n DB_POSTGRESDB_USER: n8n DB_POSTGRESDB_PASSWORD: ${N8N_DB_PASSWORD} N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY} N8N_HOST: n8n.seizeconsulting.com N8N_PORT: 5678 N8N_PROTOCOL: https WEBHOOK_URL: https://n8n.seizeconsulting.com/ # ⚠️ Pas de labels Traefik ici : c'est OAuth2-Proxy qui est exposé networks: - web - backend ``` ### Particularités - ⚠️ **N8N_ENCRYPTION_KEY** : critique pour décrypter les workflows et credentials. **À sauvegarder absolument**. - L'auth n8n native est désactivée car OAuth2-Proxy fait l'auth en amont. - Les **workflows** sont stockés dans Postgres (base `n8n`). ### Limitation RBAC n8n CE (Community Edition) **ne supporte pas le RBAC granulaire** : - Tous les users authentifiés ont accès à TOUS les workflows - Pas de notion de "team" ou "project" en CE → C'est pourquoi le RBAC se fait **côté intranet** (cacher la carte aux non-autorisés). Voir [DECISIONS.md D7](../DECISIONS.md). Pour vrai RBAC : - Soit migrer vers **Activepieces** (gratuit, multi-tenant natif) - Soit acheter **n8n Enterprise** (~12k€/an) --- ## 🐳 Portainer ### docker-compose.yml (résumé) ```yaml services: portainer: image: portainer/portainer-ce:latest container_name: portainer volumes: - /var/run/docker.sock:/var/run/docker.sock # ⚠️ Accès complet à Docker ! - ./data:/data networks: - web ``` ### Particularités - ⚠️ **Accès au socket Docker** : Portainer a un contrôle **total** sur tous les conteneurs du serveur. À protéger absolument derrière SSO. - Auth Portainer native = créée au premier login, à protéger. - **RBAC interne** dans Portainer CE = très limité. ### Limitation RBAC Portainer CE : - 1 seul utilisateur admin - Pas d'organisations/teams → RBAC sur l'intranet uniquement. Si besoin de vrai RBAC : **Portainer Business** (~1800€/an) ou migration vers **Komodo**. --- ## 💻 Code Server ### docker-compose.yml (résumé) ```yaml services: code-server: image: lscr.io/linuxserver/code-server:latest container_name: code-server environment: PUID: 1000 PGID: 1000 TZ: Europe/Paris PASSWORD: ${CODE_PASSWORD} # Fallback si SSO down SUDO_PASSWORD: ${CODE_PASSWORD} DEFAULT_WORKSPACE: /config/workspace volumes: - ./config:/config networks: - web ``` ### Particularités - VS Code dans le navigateur - L'OAuth2-Proxy gère l'auth en amont, mais Code Server a aussi son propre mdp en fallback (`CODE_PASSWORD`) - Workspaces partagés dans `./config/workspace/` ### Limitation RBAC Pas de notion de "team" ou "workspace par user" en local. Tout user accède au même workspace. → Pour vrai RBAC : **OpenVSCode Server** (multi-user natif). --- ## 📈 Uptime Kuma ### docker-compose.yml (résumé) ```yaml services: uptime-kuma: image: louislam/uptime-kuma:1 container_name: uptime-kuma volumes: - ./data:/app/data networks: - web ``` ### Particularités - Outil de monitoring (HTTP/TCP/Ping checks) - Statuspages publiques possibles (mais on les laisse derrière SSO ici) - 1 seul user admin ### Configuration recommandée Une fois SSO en place, **désactiver le compte admin local** ou changer le mdp en quelque chose de très long (le SSO suffit). ### Limitation RBAC Pareil que les autres : 1 seul user, pas de RBAC. → Pour vrai RBAC : **Gatus** (config-as-code, multi-tenant). --- ## 🏠 Intranet (page d'accueil) ### docker-compose.yml ```yaml services: intranet: image: nginx:alpine container_name: intranet restart: unless-stopped volumes: - ./index.html:/usr/share/nginx/html/index.html:ro - ./logo.png:/usr/share/nginx/html/logo.png:ro - ./roles-mapping.json:/usr/share/nginx/html/roles-mapping.json:ro - ./nginx-rbac.conf:/etc/nginx/nginx.conf:ro networks: - web ``` ### Caractéristiques - Simple nginx avec un HTML statique - **Filtrage RBAC côté JavaScript** (voir [07-rbac-intranet.md](./07-rbac-intranet.md)) - Nginx fait du `sub_filter` pour injecter l'email user dans l'HTML - L'HTML cache les cartes selon le rôle ### Fichiers critiques | Fichier | Usage | |---|---| | `index.html` | Le HTML avec les cartes et le JavaScript RBAC | | `roles-mapping.json` | Mapping `email → role` (généré par script Python) | | `nginx-rbac.conf` | Config nginx avec `sub_filter` pour injecter `__USER_EMAIL__` | | `logo.png` | Logo Seize | --- ## 🗄️ PostgreSQL (principal) ### docker-compose.yml ```yaml services: postgres: image: postgres:16-alpine container_name: postgres environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: postgres volumes: - ./data:/var/lib/postgresql/data networks: - backend healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 10s timeout: 5s retries: 5 ``` ### Particularités - Postgres **mutualisé** entre Gitea et n8n (databases séparées dans la même instance) - Pas exposé publiquement (réseau `backend` uniquement) - ⚠️ **Postgres Zitadel est séparé** (dans son propre docker-compose) ### Databases hébergées | Database | Owner | Service | |---|---|---| | postgres | postgres | (admin) | | gitea | gitea | Gitea | | n8n | n8n | n8n | | authentik | authentik | Authentik (obsolète) | --- ## 📦 Volumes critiques par app | App | Volume | Quoi | |---|---|---| | Gitea | `./data` | Repos, config, attachments | | Portainer | `./data` | Compose stacks, snapshots | | Code Server | `./config` | Workspace, settings, plugins | | Uptime Kuma | `./data` | Monitors, history, statuspages | | Postgres | `./data` | Toutes les DBs (sauf Zitadel) | | Zitadel | `./postgres-data` + `./machinekey` | Auth complète | --- ## 🔄 Ajouter une nouvelle app — checklist Voir [OPERATIONS.md](../OPERATIONS.md) section "Ajouter un nouvel outil". 1. ✅ DNS record A `.seizeconsulting.com` 2. ✅ Créer `~/docker//` avec docker-compose.yml 3. ✅ Créer l'app dans Zitadel (Project Infra Seize) 4. ✅ Récupérer Client ID + Secret 5. ✅ Créer OAuth2-Proxy dédié `~/docker/oauth2-proxy-/` 6. ✅ Tester le login 7. ✅ Ajouter la carte dans `~/docker/intranet/index.html` avec `data-app=""` 8. ✅ Ajouter la ligne dans la matrice RBAC du JavaScript 9. ✅ Restart intranet 10. ✅ Tester avec différents profils