# Deploiement VPS-1

Cette procedure sert a mettre Classeo en ligne sur une petite machine Ubuntu 24.04 pour :
- valider le comportement en production
- faire une demo
- heberger un seul tenant

Elle est volontairement minimale :
- serveur unique
- Docker Compose
- pas de Mercure
- pas de Meilisearch
- pas de RabbitMQ
- Messenger stocke sa file async en base via Doctrine

Le dossier `deploy/vps/` contient deja les fichiers necessaires :
- `deploy/vps/.env.example`
- `deploy/vps/generate-env.sh`
- `deploy/vps/Caddyfile`
- `deploy/vps/generate-jwt.sh`
- `deploy/vps/postgres/01-create-tenant-db.sh`
- `deploy/vps/generate-demo-data.sh`

## 1. Prerequis

Il faut :
- un VPS Ubuntu 24.04
- un acces SSH
- un nom de domaine ou sous-domaine pointe vers le VPS
- les ports `80` et `443` accessibles depuis Internet

Exemple recommande :
- domaine final : `demo.example.com`
- tenant : `demo`
- domaine de base : `example.com`

Dans ce cas :
- `APP_DOMAIN=demo.example.com`
- `PUBLIC_BASE_DOMAIN=example.com`
- `TENANT_SUBDOMAIN=demo`

## 2. Connexion SSH

Chez OVH, l'utilisateur initial est generalement `ubuntu`.

```bash
ssh ubuntu@IP_DU_VPS
```

Si tu veux passer root pour l'installation :

```bash
sudo -i
```

## 3. Preparation du serveur

Les commandes suivantes installent Git, Docker Engine et le plugin Compose.

```bash
sudo apt update
sudo apt install -y ca-certificates curl git gnupg

sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo usermod -aG docker "$USER"
```

Reconnecte ensuite ta session SSH, puis verifie :

```bash
docker --version
docker compose version
git --version
```

## 4. Ajouter du swap

Sur un `VPS-1`, le swap aide surtout pendant les builds Docker.

```bash
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
free -h
```

## 5. Configurer Git en SSH

Sur le VPS, genere une cle SSH dediee :

```bash
mkdir -p ~/.ssh
chmod 700 ~/.ssh
ssh-keygen -t ed25519 -C "vps-classeo" -f ~/.ssh/id_ed25519 -N ""
ssh-keyscan -H git.roukmoute.fr >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
```

Le serveur Git ecoute en SSH sur le port `2222`, pas sur `22`.
Ajoute donc cette configuration :

```bash
cat >> ~/.ssh/config <<'EOF'
Host git.roukmoute.fr
    HostName git.roukmoute.fr
    User git
    Port 2222
    IdentityFile ~/.ssh/id_ed25519
EOF
chmod 600 ~/.ssh/config
```

Affiche ensuite la cle publique :

```bash
cat ~/.ssh/id_ed25519.pub
```

Ajoute cette cle dans ton compte Gitea :
- `https://git.roukmoute.fr`
- `Settings`
- `SSH / GPG Keys`
- `Add Key`

Teste ensuite la connexion :

```bash
ssh -T git@git.roukmoute.fr
```

## 6. Cloner le projet

```bash
sudo mkdir -p /srv/classeo
sudo chown -R "$USER":"$USER" /srv/classeo
git clone git@git.roukmoute.fr:Roukmoute/Classeo.git /srv/classeo
cd /srv/classeo
```

Sans fichier `~/.ssh/config`, la variante equivalente est :

```bash
git clone ssh://git@git.roukmoute.fr:2222/Roukmoute/Classeo.git /srv/classeo
```

Si tu veux juste depanner rapidement en HTTPS, le depot public repond aussi sur :

```bash
git clone https://git.roukmoute.fr/Roukmoute/Classeo.git /srv/classeo
```

## 7. Configurer le DNS

Avant de lancer la stack, cree un enregistrement DNS de type `A` :
- `demo.example.com` -> `IPV4_DU_VPS`

Attends que le domaine reponde correctement :

```bash
dig +short demo.example.com
```

Le resultat doit renvoyer l'IPv4 du VPS.

## 8. Preparer le fichier d'environnement

Le plus simple est d'utiliser le generateur interactif :

```bash
./deploy/vps/generate-env.sh
```

Il pose les questions utiles, genere les secrets, derive les regex et ecrit `deploy/vps/.env`.

Si tu preferes toujours partir du template a la main :

Depuis la racine du repo :

```bash
cp deploy/vps/.env.example deploy/vps/.env
```

Edite ensuite `deploy/vps/.env` :

```bash
nano deploy/vps/.env
```

Valeurs a adapter au minimum :

```env
APP_DOMAIN=demo.example.com
PUBLIC_BASE_DOMAIN=example.com

TENANT_ID=remplacer-par-un-uuid
TENANT_SUBDOMAIN=demo

POSTGRES_PASSWORD=mot-de-passe-base
APP_SECRET=secret-app
JWT_PASSPHRASE=passphrase-jwt

TRUSTED_HOSTS='^(.+\.)?example\.com$'
CORS_ALLOW_ORIGIN='^https://([\w-]+\.)?example\.com$'
ADMIN_ALERT_EMAIL=admin@example.com
```

Tu peux generer les secrets ainsi :

```bash
uuidgen
openssl rand -hex 32
openssl rand -base64 48
```

Pour une simple demo, les valeurs Turnstile de test peuvent rester telles quelles dans `.env`.

## 9. Charger les variables dans le shell

Certaines commandes plus bas utilisent les variables du fichier `.env`.
Charge-les une fois dans ton shell courant :

```bash
set -a
. deploy/vps/.env
set +a
```

## 10. Generer les cles JWT

Les cles JWT ne sont pas versionnees. Il faut donc les generer sur le serveur avant le premier build.

```bash
./deploy/vps/generate-jwt.sh
```

Verifie qu'elles existent :

```bash
ls -l backend/config/jwt
```

## 11. Lancer la stack

```bash
docker compose --env-file deploy/vps/.env -f compose.prod.yaml up -d --build
```

Services demarres :
- `caddy`
- `php`
- `frontend`
- `worker`
- `db`
- `redis`

Suivre les logs au premier demarrage :

```bash
docker compose --env-file deploy/vps/.env -f compose.prod.yaml logs -f caddy php frontend worker
```

## 12. Executer les migrations

Migrations de la base master :

```bash
docker compose --env-file deploy/vps/.env -f compose.prod.yaml exec php \
  php bin/console doctrine:migrations:migrate --no-interaction
```

Migrations de la base tenant :

```bash
docker compose --env-file deploy/vps/.env -f compose.prod.yaml exec php \
  php bin/console tenant:migrate "${TENANT_SUBDOMAIN}"
```

Le tenant PostgreSQL est cree automatiquement au premier demarrage via `deploy/vps/postgres/01-create-tenant-db.sh`.

## 13. Generer un jeu de donnees de demo

Pour peupler rapidement l'application avec des comptes et des donnees realistes :
- direction
- vie scolaire
- secretariat
- professeurs
- eleves
- parents
- matieres
- classes
- affectations
- emploi du temps

Le plus simple est d'utiliser le wrapper VPS :

```bash
./deploy/vps/generate-demo-data.sh
```

Le script lit `deploy/vps/.env`, reprend `TENANT_SUBDOMAIN` par defaut, puis execute la commande Symfony dans le conteneur `php`.

Exemples :

```bash
./deploy/vps/generate-demo-data.sh --password 'Demo2026!'
./deploy/vps/generate-demo-data.sh --school 'College de demo'
./deploy/vps/generate-demo-data.sh --tenant demo --zone B --period-type trimester
./deploy/vps/generate-demo-data.sh --target master
```

La commande utilise un mot de passe commun pour tous les comptes, avec une valeur par defaut si tu n'en fournis pas, et affiche tous les comptes crees.
Elle est relancable sans dupliquer les donnees.

Alternative sans wrapper :

```bash
docker compose --env-file deploy/vps/.env -f compose.prod.yaml exec php \
  php bin/console app:dev:generate-demo-data --tenant="${TENANT_SUBDOMAIN}"
```

Si tu veux juste creer un compte unique de verification, la commande unitaire existe toujours :

```bash
docker compose --env-file deploy/vps/.env -f compose.prod.yaml exec php \
  php bin/console app:dev:create-test-user \
  --tenant="${TENANT_SUBDOMAIN}" \
  --role=ADMIN \
  --email=demo-admin@example.com \
  --password='ChangeMe123!'
```

## 14. Verifications

Verifier les conteneurs :

```bash
docker compose --env-file deploy/vps/.env -f compose.prod.yaml ps
```

Verifier l'application :

```bash
curl -I "https://${APP_DOMAIN}"
curl -I "https://${APP_DOMAIN}/api/docs"
```

A ouvrir dans le navigateur :
- `https://demo.example.com`
- `https://demo.example.com/api/docs`

## 15. Mise a jour ulterieure

Pour redeployer sur la meme machine :

```bash
cd /srv/classeo
git pull

set -a
. deploy/vps/.env
set +a

docker compose --env-file deploy/vps/.env -f compose.prod.yaml up -d --build

docker compose --env-file deploy/vps/.env -f compose.prod.yaml exec php \
  php bin/console doctrine:migrations:migrate --no-interaction

docker compose --env-file deploy/vps/.env -f compose.prod.yaml exec php \
  php bin/console tenant:migrate "${TENANT_SUBDOMAIN}"

# Optionnel: remettre un jeu de demo complet a jour
./deploy/vps/generate-demo-data.sh
```

## 16. Reinstallation sur une nouvelle machine

Si tu veux remettre la meme instance sur un autre VPS, conserve au minimum :
- `deploy/vps/.env`
- `backend/config/jwt/private.pem`
- `backend/config/jwt/public.pem`

Si tu veux aussi conserver les donnees, il faut en plus sauvegarder PostgreSQL et les volumes Docker.

## 17. Depannage rapide

Si `docker compose up` se fait tuer pendant le build :
- verifie le swap avec `free -h`
- relance le build apres activation du swap

Si le domaine ne repond pas en HTTPS :
- verifie que le DNS pointe bien vers le VPS
- verifie que les ports `80` et `443` sont ouverts
- regarde les logs `caddy`

Si le frontend repond mais pas l'API :
- verifie `https://TON_DOMAINE/api/docs`
- regarde les logs `php`
- regarde les logs `worker`

## Resume ultra-court

```bash
ssh ubuntu@IP_DU_VPS
sudo apt update && sudo apt install -y ca-certificates curl git gnupg
# installer Docker
# cloner le repo
cp deploy/vps/.env.example deploy/vps/.env
set -a && . deploy/vps/.env && set +a
./deploy/vps/generate-jwt.sh
docker compose --env-file deploy/vps/.env -f compose.prod.yaml up -d --build
docker compose --env-file deploy/vps/.env -f compose.prod.yaml exec php php bin/console doctrine:migrations:migrate --no-interaction
docker compose --env-file deploy/vps/.env -f compose.prod.yaml exec php php bin/console tenant:migrate "${TENANT_SUBDOMAIN}"
```
