- 6 docs racine (README, HANDOVER, ARCHITECTURE, DECISIONS, INSTALL, OPERATIONS) - 9 docs thématiques dans docs/ - 10 templates docker-compose dans configs/ - 7 scripts Python/Shell d'import Furious vers Zitadel - 2 matrices RBAC Etat infra au 5 juin 2026 : - 88 users Furious importes dans Zitadel - 8 roles RBAC crees et attribues - Intranet filtre les cartes selon role (Approche A) - 7 outils SSO operationnels
10 KiB
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.
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)
- Aller sur
https://git.seizeconsulting.com→ setup initial - Créer un compte admin Gitea (local, sera utilisé pour configurer le reste)
- Site Administration → Authentication Sources → Add :
- Type : OAuth2
- Authentication Name :
Zitadel - OAuth2 Provider : OpenID Connect
- Client ID :
<de Zitadel> - Client Secret :
<de Zitadel> - OpenID Connect Auto Discovery URL :
https://sso.seizeconsulting.com/.well-known/openid-configuration - Skip Local 2FA : ✅ (Zitadel gère MFA)
- 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_usernameZitadel) - ❌ 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é)
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.
Pour vrai RBAC :
- Soit migrer vers Activepieces (gratuit, multi-tenant natif)
- Soit acheter n8n Enterprise (~12k€/an)
🐳 Portainer
docker-compose.yml (résumé)
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é)
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é)
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
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)
- Nginx fait du
sub_filterpour 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
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
backenduniquement) - ⚠️ 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 section "Ajouter un nouvel outil".
- ✅ DNS record A
<app>.seizeconsulting.com - ✅ Créer
~/docker/<app>/avec docker-compose.yml - ✅ Créer l'app dans Zitadel (Project Infra Seize)
- ✅ Récupérer Client ID + Secret
- ✅ Créer OAuth2-Proxy dédié
~/docker/oauth2-proxy-<app>/ - ✅ Tester le login
- ✅ Ajouter la carte dans
~/docker/intranet/index.htmlavecdata-app="<app>" - ✅ Ajouter la ligne dans la matrice RBAC du JavaScript
- ✅ Restart intranet
- ✅ Tester avec différents profils