# 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`

## 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. Creer un utilisateur de demo

Optionnel, mais pratique pour une verification complete.

```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}"
```

## 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}"
```
