feat: Infrastructure multi-tenant avec isolation par sous-domaine

Une application SaaS éducative nécessite une séparation stricte des données
entre établissements scolaires. L'architecture multi-tenant par sous-domaine
(ecole-alpha.classeo.local) permet cette isolation tout en utilisant une
base de code unique.

Le choix d'une résolution basée sur les sous-domaines plutôt que sur des
headers ou tokens facilite le routage au niveau infrastructure (reverse proxy)
et offre une UX plus naturelle où chaque école accède à "son" URL dédiée.
This commit is contained in:
2026-01-30 23:34:10 +01:00
parent 6da5996340
commit 1fd256346a
71 changed files with 14390 additions and 37 deletions

182
docs/DEPLOYMENT.md Normal file
View File

@@ -0,0 +1,182 @@
# Déploiement en Production
## Architecture Multi-tenant
Classeo utilise une architecture multi-tenant où chaque école a son propre sous-domaine :
- `ecole-alpha.classeo.fr`
- `ecole-beta.classeo.fr`
## Différences Dev vs Prod
| Aspect | Dev | Prod |
|--------|-----|------|
| Domaine | `classeo.local` | `classeo.fr` |
| Frontend | `:5174` | même domaine |
| API | `:18000/api` | `/api` (même domaine) |
| HTTPS | Non | Oui (obligatoire) |
| Reverse proxy | Non | Oui |
| Base de données | Une seule (SQLite/PostgreSQL) | Une par tenant |
## Configuration Reverse Proxy
En production, un reverse proxy route les requêtes sur le même domaine :
- `ecole-alpha.classeo.fr/` → Frontend (SvelteKit)
- `ecole-alpha.classeo.fr/api` → Backend (FrankenPHP)
### Option recommandée : Caddy (intégré à FrankenPHP)
```caddyfile
# Caddyfile pour production
*.classeo.fr {
# Certificats SSL automatiques via Let's Encrypt
tls {
dns cloudflare {env.CLOUDFLARE_API_TOKEN}
}
# API routes
handle /api/* {
reverse_proxy php:8000
}
# Frontend
handle {
reverse_proxy frontend:3000
}
}
```
### Alternative : nginx
```nginx
server {
listen 443 ssl http2;
server_name ~^(?<subdomain>.+)\.classeo\.fr$;
ssl_certificate /etc/letsencrypt/live/classeo.fr/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/classeo.fr/privkey.pem;
location /api {
proxy_pass http://php:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location / {
proxy_pass http://frontend:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
```
## Variables d'environnement Production
### Backend (.env.prod)
```env
APP_ENV=prod
APP_DEBUG=0
APP_SECRET=<générer-une-clé-sécurisée>
TRUSTED_HOSTS=^(.+\.)?classeo\.fr$
TRUSTED_PROXIES=REMOTE_ADDR
TENANT_BASE_DOMAIN=classeo.fr
DATABASE_URL=postgresql://user:password@db-host:5432/classeo_master
REDIS_URL=redis://redis-host:6379
MESSENGER_TRANSPORT_DSN=amqp://user:password@rabbitmq-host:5672/%2f/messages
# JWT
JWT_PASSPHRASE=<générer-une-passphrase-sécurisée>
```
### Frontend
```env
PUBLIC_API_URL=https://classeo.fr/api
PUBLIC_BASE_DOMAIN=classeo.fr
PUBLIC_MERCURE_URL=https://classeo.fr/.well-known/mercure
```
## Certificats SSL
### Wildcard avec Let's Encrypt + Cloudflare DNS
Pour les sous-domaines dynamiques, un certificat wildcard est nécessaire :
```bash
# Avec certbot et Cloudflare DNS
certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /etc/cloudflare.ini \
-d classeo.fr \
-d "*.classeo.fr"
```
### Avec Caddy (automatique)
Caddy gère automatiquement les certificats wildcard si vous configurez un provider DNS.
## Base de données par tenant
Chaque tenant a sa propre base de données PostgreSQL :
- `classeo_tenant_alpha`
- `classeo_tenant_beta`
### Création d'un nouveau tenant
```bash
# 1. Créer la base de données
php bin/console tenant:database:create classeo_tenant_<nom>
# 2. Exécuter les migrations
php bin/console tenant:migrate <subdomain>
# 3. Ajouter le tenant au registry (ou en base master)
```
## Options de déploiement
### 1. VPS simple (petit volume)
- Un serveur avec Docker Compose
- Convient pour < 50 écoles
- Coût : ~20-50€/mois
### 2. Docker Swarm (moyen volume)
- Plusieurs serveurs avec orchestration
- Scaling horizontal
- Convient pour 50-500 écoles
### 3. Kubernetes (grand volume)
- Orchestration avancée
- Auto-scaling
- Convient pour 500+ écoles
- Coût plus élevé, complexité accrue
## Checklist de mise en production
- [ ] Configurer le domaine DNS (wildcard `*.classeo.fr`)
- [ ] Obtenir certificat SSL wildcard
- [ ] Configurer le reverse proxy (Caddy ou nginx)
- [ ] Configurer les variables d'environnement prod
- [ ] Générer les clés JWT de production
- [ ] Configurer la base de données master
- [ ] Créer les bases de données tenant
- [ ] Configurer les backups automatiques
- [ ] Configurer le monitoring (logs, métriques)
- [ ] Tester le déploiement sur un environnement staging
- [ ] Configurer CI/CD pour les déploiements automatiques
## TODO
- [ ] Créer un `compose.prod.yaml` pour la production
- [ ] Script de création automatique de tenant
- [ ] Interface admin pour gérer les tenants
- [ ] Monitoring et alerting