# Déploiement — Sobook / Les Deux-Clefs (OVH mutualisé, via GitHub)

Même principe que **stepone-worktime** : le code voyage par Git, GitHub construit le front et
déploie en SSH sur l'hébergement à chaque `git push`. Un seul domaine sert le site public, l'espace
de gestion et l'API.

| | Valeur |
|---|---|
| Domaine | `https://reservation.les-deux-clefs.ch` (site public `/fr`, `/de`, gestion `/admin`, API `/api`) |
| Dépôt Git | `https://github.com/spinoops/so-book` (privé, branche `master`) |
| Hébergement | OVH **mutualisé Pro ou Performance** (l'offre Perso n'a pas de SSH, indispensable ici) |
| Dossier serveur | `~/les-deux-clefs-reservation` (hors `www`), dossier racine du multisite → `les-deux-clefs-reservation/backend/public` |
| PHP | **8.3** (minimum du projet ; 8.4 fonctionne aussi). CLI : `/usr/local/php8.3/bin/php` |
| Base MySQL | créée dans le Manager (hôte `xxxxx.mysql.db`, nom, utilisateur, mot de passe) |

## Principe clé

- Le **code** (dont les migrations) voyage par **Git**.
- Le **schéma** de la base se reconstruit avec `php artisan migrate --force`.
- Les **données** ne sont copiées du PC vers le serveur **qu'une fois**, à la première mise en
  ligne (import VikBooking déjà fait en local). Ensuite le serveur est la référence.
- Pas de Node.js chez OVH : le front est **construit par GitHub** et copié dans `backend/public`.
- `composer.json` fige la plateforme à **PHP 8.3** (`config.platform.php`) : les dépendances
  choisies en local sont donc garanties compatibles avec le serveur.

## Architecture : un seul domaine

Doc root `backend/public`. `routes/web.php` sert `sitemap.xml`, `robots.txt`, `llms.txt`, puis
renvoie `index.html` (build React) pour toute URL hors `/api` et `/storage`. `public/.htaccess`
transmet l'en-tête `Authorization` (jetons Sanctum) à PHP. Pas de CORS, un seul certificat.

---

## 1. Première mise en ligne (une seule fois)

### A. GitHub (sur le PC) — fait

```bash
git remote add origin https://github.com/spinoops/so-book.git
git push -u origin master
```

### B. Manager OVH (Web Cloud → Hébergements → votre hébergement)

1. **SSH** : onglet *FTP-SSH* → sur l'utilisateur principal, *Modifier* → **SSH : activé**.
   Noter le **serveur SSH** (ex. `ssh.cluster0xx.hosting.ovh.net`) et l'**identifiant** (ex. `lesdeuxc`).
   Le mot de passe SSH = mot de passe FTP (à définir/réinitialiser au besoin).
2. **PHP** : onglet *Informations générales* → *Configuration* → *Modifier la configuration* →
   **PHP 8.3**, mode production. (Par site : un fichier `.ovhconfig` dans le dossier racine, voir §C.)
3. **Base de données** : onglet *Bases de données* → *Créer une base* (MySQL, nom `xxxxx_sobook`
   ou celui proposé). Noter **hôte** (`xxxxx.mysql.db`), **nom**, **utilisateur**, **mot de passe**.
4. **Multisite** : onglet *Multisite* → *Ajouter un domaine ou sous-domaine* →
   `reservation.les-deux-clefs.ch`, **dossier racine** `les-deux-clefs-reservation/backend/public`,
   **SSL activé** (Let's Encrypt), cocher *Créer l'entrée DNS* si la zone DNS est chez OVH.
   Sinon, chez le registrar du domaine : enregistrement **A** `reservation` → IP de l'hébergement
   (affichée dans *Informations générales*) ou **CNAME** vers `cluster0xx.hosting.ovh.net`.
   Le certificat SSL est délivré quelques heures après la propagation DNS.

> Si le Manager refuse un dossier racine hors `www`, utiliser `www/les-deux-clefs-reservation` (`DEPLOY_PATH=www/les-deux-clefs-reservation`)
> et vérifier ensuite que `https://<domaine-principal>/les-deux-clefs-reservation/backend/.env` renvoie bien 403/404.

### C. Sur le serveur (SSH)

```bash
ssh lesdeuxc@ssh.cluster0xx.hosting.ovh.net
PHP=/usr/local/php8.3/bin/php
$PHP -v                                             # PHP 8.3.x
```

**Composer** (absent ou trop ancien sur le mutualisé : on l'installe dans le home) :
```bash
cd ~ && curl -sS https://getcomposer.org/installer | $PHP -- --install-dir=$HOME --filename=composer.phar
$PHP ~/composer.phar --version
```

**Clé de déploiement GitHub** (le dépôt est privé) :
```bash
ssh-keygen -t ed25519 -C "ovh-reservation" -f ~/.ssh/id_ed25519 -N ""
cat ~/.ssh/id_ed25519.pub
#   → GitHub : dépôt so-book → Settings → Deploy keys → Add deploy key (lecture seule)
```

**Installation :**
```bash
mkdir -p ~/les-deux-clefs-reservation && cd ~/les-deux-clefs-reservation
git clone git@github.com:spinoops/so-book.git .
$PHP ~/composer.phar install --no-dev --optimize-autoloader --working-dir=backend

cp backend/.env.production.example backend/.env
nano backend/.env
#   APP_KEY   → reprendre TELLE QUELLE celle de backend/.env du PC (elle chiffre le mot de passe SMTP)
#   DB_HOST / DB_DATABASE / DB_USERNAME / DB_PASSWORD (Manager → Bases de données)
#   MAIL_*    → SMTP de secours (réinitialisation de mot de passe), le SMTP des réglages prime
```

**Version PHP du site** (si le réglage global du Manager ne suffit pas) — fichier
`~/les-deux-clefs-reservation/backend/public/.ovhconfig` :
```ini
app.engine=php
app.engine.version=8.3
http.firewall=none
environment=production
```

**Base de données : reprise de la base locale (données Les Deux-Clefs déjà importées)**

Sur le PC :
```bash
D:\wamp64\bin\mysql\mysql8.0.31\bin\mysqldump.exe -u root --default-character-set=utf8mb4 --single-transaction app_sobook > sobook.sql
```
Envoyer `sobook.sql` par SFTP dans `~/les-deux-clefs-reservation`, puis sur le serveur :
```bash
mysql -h xxxxx.mysql.db -u xxxxx_sobook -p xxxxx_sobook < sobook.sql
$PHP backend/artisan migrate --force                 # contrôle : « Nothing to migrate »
$PHP backend/artisan sobook:rewrite-urls http://localhost:8000 https://reservation.les-deux-clefs.ch
#   (photos des chambres, logo, bandeau : localhost → domaine de prod)
rm sobook.sql
```
> Variante sans reprise de base : `$PHP backend/artisan migrate --force` (tables vides), puis
> refaire l'import VikBooking sur le serveur (`sobook:import-vikbooking`, voir README).
> Le Manager OVH permet aussi d'importer le `.sql` (Bases de données → ⋯ → Importer un fichier).

**Comptes** (les comptes de démo `@baseapp.test` n'existent pas en production) :
```bash
$PHP backend/artisan sobook:create-admin admin@les-deux-clefs.ch "Prénom Nom"     # mot de passe demandé
$PHP backend/artisan sobook:create-admin reception@les-deux-clefs.ch "Réception" --role=gestionnaire
```
Si la base du PC a été importée, **supprimer** ensuite les comptes `admin@baseapp.test` et
`user@baseapp.test` depuis Utilisateurs (mot de passe connu).

**Fichiers et caches :**
```bash
$PHP backend/artisan storage:link             # public/storage → storage/app/public (photos, logo)
$PHP backend/artisan config:cache && $PHP backend/artisan route:cache && $PHP backend/artisan view:cache
chmod -R u+rwX backend/storage backend/bootstrap/cache
```

### D. Fichiers à copier (SFTP, depuis le PC)

| Depuis le PC | Vers le serveur | Contenu |
|---|---|---|
| `backend/storage/app/public/` | `les-deux-clefs-reservation/backend/storage/app/public/` | photos des chambres, logo, bulletin QR (pièce jointe) |

Le build du front (`frontend/dist`) n'est **pas** à copier à la main : la GitHub Action s'en charge (§E).

### E. GitHub Action (déploiement automatique)

Sur le serveur, une paire de clés dédiée à GitHub :
```bash
ssh-keygen -t ed25519 -C "github-actions" -f ~/.ssh/github-actions -N ""
cat ~/.ssh/github-actions.pub >> ~/.ssh/authorized_keys
chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys
cat ~/.ssh/github-actions          # ← clé PRIVÉE, à coller dans le secret DEPLOY_SSH_KEY
```
Sur GitHub, dépôt → Settings → Secrets and variables → Actions :
- **Secrets** : `DEPLOY_HOST` (ex. `ssh.cluster0xx.hosting.ovh.net`), `DEPLOY_USER` (ex. `lesdeuxc`),
  `DEPLOY_SSH_KEY` (clé privée complète, lignes BEGIN/END comprises).
- **Variables** (facultatif, valeurs par défaut sinon) : `SITE_URL=https://reservation.les-deux-clefs.ch`,
  `DEPLOY_PATH=les-deux-clefs-reservation`, `PHP_BIN=/usr/local/php8.3/bin/php`, `COMPOSER_PHAR=composer.phar`.

Onglet **Actions** → « Deploy (OVH) » → *Run workflow* : premier déploiement (build du front + copie
dans `backend/public`). Les exécutions lancées avant la saisie des secrets ont échoué : c'est attendu.

### F. Vérifications

1. `https://reservation.les-deux-clefs.ch/api/health` → `{"status":"ok"}`.
2. `https://reservation.les-deux-clefs.ch/` redirige vers `/fr`, chambres et photos visibles, bascule DE.
3. `/admin` → connexion avec le compte créé ; planning et réservations importées présentes.
4. Réglages → Envoi d'e-mails : renseigner le SMTP de la boîte `info@les-deux-clefs.ch`
   (chez OVH : `ssl0.ovh.net`, port 587, TLS) puis **Tester**.
5. Réglages → Modèles d'e-mails : déposer le bulletin QR (PDF) en pièce jointe.
6. Une réservation test depuis le site, puis l'annuler depuis l'admin (e-mails reçus, facture imprimable).
7. `/sitemap.xml`, `/robots.txt`, `/llms.txt` répondent ; déclarer le sitemap dans la Google Search Console.

---

## 2. À chaque mise à jour (le geste répété)

```bash
git add . && git commit -m "…" && git push
```
La GitHub Action fait le reste : build du front, `git pull`, Composer, `migrate --force`, copie du
build, caches, contrôle de `/api/health`. Suivre l'exécution dans l'onglet Actions.

Manuellement (sans l'Action), en SSH :
```bash
PHP=/usr/local/php8.3/bin/php
cd ~/les-deux-clefs-reservation && git pull --ff-only
$PHP ~/composer.phar install --no-dev --optimize-autoloader --working-dir=backend
$PHP backend/artisan migrate --force
$PHP backend/artisan config:cache && $PHP backend/artisan route:cache && $PHP backend/artisan view:cache
# + copier frontend/dist/* (construit en local avec VITE_API_URL et VITE_SITE_URL = domaine) dans backend/public/
```

## 3. Sauvegardes

OVH conserve des sauvegardes automatiques de la base (Bases de données → ⋯ → Restaurer une
sauvegarde) et des fichiers (FTP-SSH → Restaurer une sauvegarde). Penser à exporter ponctuellement
la base et `backend/storage/app/public` hors de l'hébergement.

## 4. Rappels sécurité

- `APP_DEBUG=false`, `APP_ENV=production`, comptes de démo supprimés.
- Ne jamais committer le `.env` réel ni la base exportée.
- Telescope ne se charge qu'en local (voir `AppServiceProvider`).
- Sur le mutualisé, pas de worker de file d'attente : `QUEUE_CONNECTION=sync` (les e-mails partent
  immédiatement).
