seize-infra-doc/INSTALL.md
Hedi Kalboussi 1e90a85359 Documentation initiale infra Seize — passation J7
- 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
2026-06-05 17:49:43 +00:00

523 lines
14 KiB
Markdown

# INSTALL — Déploiement from scratch sur un nouveau serveur
> Procédure complète pour reproduire l'infrastructure Seize sur un nouveau serveur.
⏱️ **Temps total estimé** : 4-6h pour un sysadmin expérimenté.
---
## 📋 Prérequis
### Côté infrastructure
- [ ] **Serveur Linux** : 4 vCPU, 8 Go RAM minimum (16 Go recommandé), 80 Go disque
- [ ] **OS** : Debian 13 (Trixie) ou Ubuntu 22.04+
- [ ] **IP publique fixe** (chez Scaleway ou autre)
- [ ] **Ports ouverts** : 22 (SSH), 80 (HTTP), 443 (HTTPS)
### Côté domaine
- [ ] Un **domaine** que vous contrôlez (ex: `seizeconsulting.com`)
- [ ] Accès à la **zone DNS** pour ajouter des records A
### Côté tiers
- [ ] Compte **Furious Squad** avec droits admin (pour créer un compte API)
- [ ] (Optionnel) Compte **Microsoft 365** avec admin pour le SMTP
### Côté local
- [ ] Un **PC** avec SSH et SCP (Windows PowerShell, Linux, ou macOS)
- [ ] Un **gestionnaire de mots de passe** (Bitwarden, KeePass, 1Password)
---
## 🌐 Étape 0 — Configuration DNS
⏱️ **15 min** (mais propagation peut prendre 1h+)
Chez votre registrar (Scaleway, OVH, Gandi, etc.), ajouter les records A suivants :
| Record | Type | Valeur |
|---|---|---|
| `@` (ou `seizeconsulting.com`) | A | `<IP_DU_SERVEUR>` |
| `sso` | A | `<IP_DU_SERVEUR>` |
| `intranet` | A | `<IP_DU_SERVEUR>` |
| `git` | A | `<IP_DU_SERVEUR>` |
| `n8n` | A | `<IP_DU_SERVEUR>` |
| `portainer` | A | `<IP_DU_SERVEUR>` |
| `code` | A | `<IP_DU_SERVEUR>` |
| `status` | A | `<IP_DU_SERVEUR>` |
| `traefik` | A | `<IP_DU_SERVEUR>` |
**Vérification** :
```bash
nslookup sso.seizeconsulting.com
```
→ Doit retourner l'IP du serveur.
---
## 🐧 Étape 1 — Préparation du serveur
⏱️ **20 min**
### 1.1 — Connexion SSH initiale
```bash
ssh root@<IP_DU_SERVEUR>
```
### 1.2 — Créer un user non-root
```bash
adduser admin
usermod -aG sudo admin
mkdir -p /home/admin/.ssh
cp ~/.ssh/authorized_keys /home/admin/.ssh/
chown -R admin:admin /home/admin/.ssh
chmod 600 /home/admin/.ssh/authorized_keys
```
### 1.3 — Hardening SSH
Éditer `/etc/ssh/sshd_config` :
```
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
```
Restart : `systemctl restart sshd`
### 1.4 — Reconnexion en tant que l'utilisateur non-root
```bash
exit
ssh admin@<IP_DU_SERVEUR>
```
### 1.5 — Mise à jour système
```bash
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl wget git vim htop unzip
```
---
## 🐳 Étape 2 — Installation Docker
⏱️ **10 min**
```bash
# Installation Docker depuis le repo officiel
curl -fsSL https://get.docker.com | sudo sh
# Ajouter l'utilisateur au groupe docker
sudo usermod -aG docker $USER
# Se relogger pour prendre en compte le groupe
exit
ssh admin@<IP_DU_SERVEUR>
# Vérification
docker --version
docker compose version
```
→ Tu dois voir : Docker version 27.x ou plus récent, Docker Compose v2.x
---
## 🌐 Étape 3 — Création des réseaux Docker
⏱️ **2 min**
```bash
docker network create web
docker network create backend
```
→ Ces réseaux seront partagés entre tous les services.
---
## 🛡️ Étape 4 — Installation Traefik
⏱️ **30 min**
Voir [docs/02-traefik-setup.md](./docs/02-traefik-setup.md) pour les détails.
### Résumé
```bash
mkdir -p ~/docker/traefik/letsencrypt
cd ~/docker/traefik
# Copier le docker-compose.yml depuis configs/traefik/
# Copier traefik.yml et dynamic.yml depuis configs/traefik/
# Adapter les emails Let's Encrypt
docker compose up -d
```
**Vérification** :
```bash
docker logs traefik
# Doit afficher "Server is up"
```
Visiter `https://traefik.seizeconsulting.com` → doit afficher la page de login basic auth.
---
## 🔐 Étape 5 — Installation Zitadel
⏱️ **45 min**
Voir [docs/03-zitadel-setup.md](./docs/03-zitadel-setup.md) pour les détails complets.
### Résumé des points clés
1. Créer `~/docker/zitadel/` avec son `docker-compose.yml` et `.env`
2. **Important** : Zitadel a son propre Traefik intégré + Postgres dédié
3. Lancer : `docker compose up -d`
4. Aller sur `https://sso.seizeconsulting.com/ui/console`
5. Créer le user **zitadel-admin** initial via console
6. Configurer les politiques :
- Password complexity (14 chars, maj+min+chiffres+symboles)
- MFA obligatoire
- Lockout après 5 échecs
⚠️ **Sauvegarder le mdp zitadel-admin** immédiatement dans le gestionnaire de mots de passe.
---
## 🗄️ Étape 6 — Installation Postgres (pour Gitea, n8n)
⏱️ **10 min**
```bash
mkdir -p ~/docker/postgres/data
cd ~/docker/postgres
# Copier docker-compose.yml et .env.example depuis configs/postgres/
# Renommer .env.example en .env et générer un mdp fort
cat > .env << EOF
POSTGRES_PASSWORD=$(openssl rand -base64 32 | tr -d '+/=')
EOF
chmod 600 .env
docker compose up -d
# Vérification
docker exec -it postgres psql -U postgres -c "SELECT version();"
```
### Créer les databases pour Gitea et n8n
```bash
docker exec -it postgres psql -U postgres << EOF
CREATE USER gitea WITH PASSWORD 'PWD_GITEA';
CREATE DATABASE gitea OWNER gitea;
CREATE USER n8n WITH PASSWORD 'PWD_N8N';
CREATE DATABASE n8n OWNER n8n;
EOF
```
⚠️ Remplacer `PWD_GITEA` et `PWD_N8N` par des mdp générés (`openssl rand -base64 24`) et les stocker dans le gestionnaire.
---
## 🐙 Étape 7 — Installation Gitea avec SSO Zitadel
⏱️ **45 min**
Voir [docs/05-applications.md](./docs/05-applications.md) section Gitea.
### Étapes principales
1. Créer `~/docker/gitea/` avec son `docker-compose.yml` et `.env`
2. Démarrer Gitea : `docker compose up -d`
3. Aller sur `https://git.seizeconsulting.com` → faire le setup initial
4. **Dans Zitadel** : créer une application "Gitea" dans le project "Infra Seize"
5. Configurer dans Gitea : Settings → Authentication Sources → Add OAuth2
6. **Activer auto-registration** dans `app.ini` :
```ini
[oauth2_client]
ENABLE_AUTO_REGISTRATION = true
USERNAME = preferred_username
```
7. Restart Gitea : `docker compose restart`
---
## 🔐 Étape 8 — Pattern OAuth2-Proxy pour les autres outils
⏱️ **2h** (à répéter pour chaque outil)
Voir [docs/04-oauth2-proxy-pattern.md](./docs/04-oauth2-proxy-pattern.md) pour le pattern complet.
### Outils à protéger via OAuth2-Proxy
- n8n
- Portainer
- Code Server
- Uptime Kuma
- Intranet
### Étapes par outil (exemple : n8n)
1. **Déployer l'outil** (sans SSO) :
```bash
mkdir -p ~/docker/n8n
# Copier docker-compose.yml depuis configs/n8n/
docker compose up -d
```
2. **Créer l'application dans Zitadel** :
- Console Zitadel → Projects → Infra Seize → Applications → New
- Type : Web
- Authentication Method : Basic
- Grant Types : Authorization Code
- Redirect URL : `https://n8n.seizeconsulting.com/oauth2/callback`
- Token Type : JWT
- Cocher : User roles inside ID Token, User profile info, Add user roles to access token
3. **Récupérer Client ID + Client Secret**
4. **Déployer OAuth2-Proxy dédié** :
```bash
mkdir -p ~/docker/oauth2-proxy-n8n
# Copier docker-compose.yml et .env.example depuis configs/oauth2-proxy/
# Adapter les valeurs (host, client_id, client_secret, upstream)
cd ~/docker/oauth2-proxy-n8n
docker compose up -d
```
5. **Tester** : aller sur `https://n8n.seizeconsulting.com` → doit rediriger vers Zitadel login.
---
## 🏠 Étape 9 — Installation Intranet avec RBAC
⏱️ **30 min**
Voir [docs/07-rbac-intranet.md](./docs/07-rbac-intranet.md) pour les détails.
### Étapes
1. **Créer le dossier intranet** :
```bash
mkdir -p ~/docker/intranet
```
2. **Copier les fichiers** depuis `configs/intranet/` :
- `docker-compose.yml`
- `nginx-rbac.conf`
- `index.html.template` (à personnaliser)
- `logo.png` (le logo Seize)
3. **Créer le `roles-mapping.json`** :
Il sera généré plus tard par le script `generate-roles-mapping.py` (cf. Étape 10).
En attendant, créer un mapping vide :
```bash
echo '{}' > roles-mapping.json
```
4. **Déployer OAuth2-Proxy pour l'intranet** : voir Étape 8 mais avec :
- Host : `intranet.seizeconsulting.com`
- Upstream : `http://intranet:80`
5. **Démarrer l'intranet** :
```bash
cd ~/docker/intranet
docker compose up -d
```
6. **Tester** : aller sur `https://intranet.seizeconsulting.com` → login Zitadel → voir les cartes (toutes affichées tant que roles-mapping.json est vide).
---
## 👥 Étape 10 — Import des users depuis Furious Squad
⏱️ **1h**
Voir [docs/06-import-furious.md](./docs/06-import-furious.md) pour la procédure complète.
### Étapes principales
1. **Créer un compte API Furious** :
- Connexion Furious → Configuration → Générer un nouvel utilisateur d'API
- Cocher les permissions : `User > Search` uniquement
- Sauvegarder identifiant + mdp dans le gestionnaire
2. **Créer le service account Zitadel** :
- Console Zitadel → Users → New → Service user
- Nom : `furious-import-service`
- Access Token Type : JWT
- Dans Default settings → IAM Members → ajouter ce service user avec rôle `IAM User Manager`
- Générer une clé : Keys → New → Type JSON → télécharger immédiatement
3. **Préparer l'environnement Python** :
```bash
mkdir -p ~/furious-to-zitadel
cd ~/furious-to-zitadel
python3 -m venv venv
source venv/bin/activate
pip install requests pyjwt cryptography
```
4. **Copier les scripts** depuis `scripts/furious-to-zitadel/` du repo.
5. **Créer le `.env`** :
```env
FURIOUS_USERNAME=<credentials créés à l'étape 1>
FURIOUS_PASSWORD=<credentials créés à l'étape 1>
FURIOUS_API_URL=https://seize-consulting.furious-squad.com/api/v2
```
`chmod 600 .env`
6. **Placer la clé JSON Zitadel** :
- Transférer la clé depuis le PC vers le serveur via SCP
- `chmod 600 zitadelfuriousimportkey.json`
7. **Lancer l'import** :
```bash
# Étape A : Lire les users depuis Furious
./read-all-users.sh
# → Génère furious-users-raw.json
# Étape B : Dry-run (simulation, aucune écriture)
python3 import-furious-to-zitadel.py --mode dry-run
# Étape C : Test sur 3 users
python3 import-furious-to-zitadel.py --mode test
# Étape D : Vérifier dans Zitadel UI que les 3 users sont créés avec metadata
# Étape E : Import production (les 85 restants)
python3 import-furious-to-zitadel.py --mode prod
```
8. **Gérer les doublons** (si users existaient déjà dans Zitadel) :
```bash
# Adapter DUPLICATES dans merge-duplicates.py selon ton cas
python3 merge-duplicates.py
```
9. **Vérifier le CSV** :
```bash
wc -l users-credentials.csv
# Doit être : 1 header + N users
```
---
## 🎭 Étape 11 — Configuration des rôles RBAC
⏱️ **30 min**
Voir [docs/07-rbac-intranet.md](./docs/07-rbac-intranet.md) pour les détails.
### Étapes
1. **Créer les 8 rôles dans Zitadel** :
- Console Zitadel → Projects → Infra Seize → Roles → New
- Créer un par un :
- direction / Direction / hierarchie
- manager / Manager / hierarchie
- expert / Expert / hierarchie
- consultant_senior / Consultant Senior / hierarchie
- consultant_junior / Consultant Junior / hierarchie
- alternant / Alternant / hierarchie
- stagiaire / Stagiaire / hierarchie
- support / Support / hierarchie
2. **Activer "Return user roles during authentication"** :
- Console Zitadel → Projects → Infra Seize → General
- Cocher "Return user roles during authentication"
- Save
3. **Activer "User roles inside ID Token"** sur chaque application :
- Pour chaque app (Intranet, n8n, etc.) : Token Settings
- Auth Token Type : JWT
- Cocher : User roles inside ID Token, Include user's profile info, Add user roles to the access token
4. **Modifier OAuth2-Proxy** pour demander le scope des rôles :
- Pour chaque OAuth2-Proxy : éditer `.env`
- Modifier : `OAUTH2_PROXY_SCOPE=openid email profile urn:zitadel:iam:org:project:roles`
- Restart : `docker compose down && docker compose up -d`
5. **Lancer les scripts d'attribution** :
```bash
cd ~/furious-to-zitadel
source venv/bin/activate
# Générer le mapping email → rôle (pour l'intranet)
python3 generate-roles-mapping.py
# Attribuer les rôles dans Zitadel (87 users)
python3 assign-roles.py
```
6. **Copier le mapping vers l'intranet** :
```bash
cp roles-mapping.json ~/docker/intranet/
```
7. **Restart de l'intranet** :
```bash
cd ~/docker/intranet
docker compose down
docker compose up -d
```
8. **Test final** :
- Login en incognito avec un user (ex: consultant_junior)
- Doit voir uniquement les cartes autorisées (Gitea + Code Server par défaut)
---
## ✅ Étape 12 — Validation finale
⏱️ **30 min**
### Checklist de validation
- [ ] Tous les conteneurs `Up` : `docker ps`
- [ ] Tous les sous-domaines répondent en HTTPS
- [ ] Login Zitadel fonctionne avec MFA
- [ ] Login intranet fonctionne et filtre les cartes
- [ ] Login Gitea fonctionne avec auto-registration
- [ ] Login n8n / Portainer / Code Server / Uptime Kuma fonctionne
- [ ] Le service account Furious peut lire l'API Furious
- [ ] Les scripts Python sont opérationnels
- [ ] Les fichiers sensibles ont `chmod 600`
- [ ] Les `.env` ne sont pas committés sur Git
- [ ] Backup automatique en place (à mettre en place — voir OPERATIONS.md)
---
## 🚨 Points d'attention pendant l'install
### Ne pas oublier
- ✅ Sauvegarder TOUS les secrets dans le gestionnaire de mdp
- ✅ Configurer le firewall (ufw ou iptables) pour limiter aux ports 22/80/443
- ✅ Tester chaque étape avant de passer à la suivante
- ✅ Documenter les écarts par rapport à cette procédure si tu en fais
### Pièges classiques
- ❌ Oublier d'ajouter le record DNS avant de tester le HTTPS (Let's Encrypt échoue)
- ❌ Lancer `docker compose up -d` sans avoir créé le `.env` (erreurs cryptiques)
- ❌ Donner IAM_OWNER au service account (utiliser IAM_USER_MANAGER)
- ❌ Coller un secret dans une conversation IA (gestionnaire de mdp uniquement)
---
## 📚 Pour aller plus loin
Une fois l'install terminée, consulter :
- [OPERATIONS.md](./OPERATIONS.md) pour la maintenance quotidienne
- [docs/09-troubleshooting.md](./docs/09-troubleshooting.md) pour les problèmes fréquents
- [HANDOVER.md](./HANDOVER.md) pour les actions à mener