# Mise en production sur backmapension.bouillot.dev

Cette procédure concerne un hébergement PHP avec MySQL, sans Docker. L’administration sera sur **https://backmapension.bouillot.dev/plateforme** et, par exemple, la pension `demo` sur **https://demo.bouillot.dev**. Le nom de domaine de base à configurer dans le CRM est donc **`bouillot.dev`**, sans `backmapension`, sans protocole et sans chemin.

## 1. Vérifier les possibilités de l’hébergement

Il faut PHP 8.2 minimum (8.3 conseillé), MySQL 8 ou MariaDB 10.11, des bases InnoDB, et les extensions PHP `pdo_mysql`, `ctype`, `fileinfo`, `gd`, `iconv`, `mbstring`, `session`, `sodium`, `dom`, `xml` et `zip`. Le panneau de l’hébergeur permet généralement de choisir la version PHP et les extensions.

Il faut pouvoir créer des sous-domaines pointant vers le **même dossier `public/`**, utiliser HTTPS sur chacun, disposer d’un dossier privé persistant accessible en écriture à PHP et exécuter ponctuellement les commandes PHP de cette procédure via SSH ou une console de l’hébergeur. Si aucune console n’est proposée, demander à l’hébergeur comment exécuter `bin/console` ; aucun formulaire public de création de super administrateur n’est prévu.

L’offre doit autoriser une base pour le registre global **plus une base par pension**. Chaque base a un utilisateur limité à cette base. Le CRM ne crée pas les bases lui-même sur cet hébergement.

## 2. Préparer le domaine et HTTPS

Dans le panneau d’hébergement, créer `backmapension.bouillot.dev`. Le faire pointer vers le dossier `public/` du projet, pas vers la racine du projet.

Dans le DNS de `bouillot.dev`, ajouter l’enregistrement indiqué par l’hébergeur pour `backmapension` : un enregistrement A vers son IP ou un CNAME vers son adresse de serveur, selon sa documentation. Ne pas modifier les autres enregistrements existants.

Pour les pensions, utiliser soit un sous-domaine générique `*.bouillot.dev` pris en charge à la fois par le DNS et le panneau d’hébergement, soit créer chaque sous-domaine individuellement. Un DNS générique seul ne suffit pas : le serveur doit aussi accepter ces noms et les diriger vers `public/`.

Activer le certificat HTTPS de `backmapension.bouillot.dev`. Prévoir aussi HTTPS pour chaque pension, ou un certificat générique couvrant `*.bouillot.dev`. Activer la redirection HTTP vers HTTPS dans le panneau. Vérifier HTTPS avant la première connexion : la production refuse les accès non sécurisés.

## 3. Préparer les bases MySQL

Dans le panneau de l’hébergeur :

1. Créer une base vide pour le registre, par exemple `crm_registre`, et son utilisateur. L’hébergeur peut imposer un préfixe ; conserver le nom exact qu’il donne.
2. Noter le serveur MySQL exact, le port, le nom de base, l’utilisateur et son mot de passe.
3. Pour la première pension, créer une **autre base vide** et un **autre utilisateur** limité à cette base. Garder ses accès pour l’étape 7.

Les utilisateurs doivent pouvoir créer les tables et utiliser `SELECT`, `INSERT`, `UPDATE`, `DELETE`, `ALTER` et `INDEX` dans leur propre base. Il n’est pas nécessaire de leur donner accès aux bases d’autres pensions ni les droits globaux de créer des bases ou utilisateurs. Ne pas utiliser une base contenant un autre site.

## 4. Envoyer le projet

Dans un dossier privé de l’hébergement, par exemple `crm-pension`, envoyer `bin/`, `config/`, `deploy/`, `public/`, `src/`, `templates/`, `composer.json` et `composer.lock`. Créer le dossier `var/` vide. Conserver le fichier caché **`public/.htaccess`** dans le transfert FTP/SFTP.

Ne pas envoyer `.git/`, `.idea/`, `.env.platform`, vos secrets locaux, les caches ou les données de test. Ne pas copier les données réelles avant d’avoir préparé leur import volontaire à l’étape 8.

Depuis le terminal de l’hébergement, dans le dossier du projet :

```sh
composer install --no-dev --optimize-autoloader
composer check-platform-reqs --no-dev
```

Si Composer est absent sur l’hébergement, préparer `vendor/` sur une machine compatible avec sa version de PHP puis transférer ce dossier également. Faire vérifier les extensions et la compatibilité par la console de l’hébergeur ; une installation locale réussie ne garantit pas que toutes ses extensions sont présentes.

PHP doit pouvoir écrire dans `var/` pour les caches, sessions et pièces privées. Utiliser les droits et le propriétaire recommandés par l’hébergeur, sans permissions `777`. Seul `public/` doit être exposé sur le web. Si le panneau impose une racine web fixe, demander comment utiliser un sous-dossier comme racine ; ne pas exposer tout le projet pour contourner cette contrainte.

Sur Apache, le fichier `public/.htaccess` dirige les routes vers Symfony et demande `mod_rewrite` ainsi que l’autorisation des directives de réécriture. Sur Nginx, faire configurer l’équivalent par l’hébergeur. Si les pages `/plateforme` renvoient une erreur 404 du serveur, vérifier cette réécriture et la racine web.

Les références techniques sont la [procédure officielle de déploiement Symfony](https://symfony.com/doc/7.4/deployment.html) et la [documentation Apache sur les routes et HTTPS](https://httpd.apache.org/docs/2.4/rewrite/remapping.html).

## 5. Configurer la production

Copier `deploy/platform.mysql.example.php` vers **`var/platform-config.php`**. Ce fichier est privé, exclu de Git et doit avoir les permissions `0600` lorsque PHP utilise le même propriétaire. Sinon, adapter l’accès avec l’hébergeur pour que seul le propriétaire et PHP puissent le lire.

Générer deux secrets différents, chacun avec cette commande :

```sh
php -r 'echo bin2hex(random_bytes(32)), PHP_EOL;'
```

Renseigner le fichier privé :

```php
<?php
return [
    'APP_ENV' => 'prod',
    'APP_SECRET' => 'VOTRE_PREMIERE_CLE_ALEATOIRE',
    'PLATFORM_MODE' => '1',
    'PLATFORM_DOMAIN' => 'bouillot.dev',
    'PLATFORM_ENCRYPTION_KEY' => 'VOTRE_SECONDE_CLE_ALEATOIRE',
    'PLATFORM_DATABASE_URL' => 'mysql://UTILISATEUR_ENCODE:MOT_DE_PASSE_ENCODE@SERVEUR_MYSQL:3306/NOM_BASE_REGISTRE',
    'TENANT_BACKEND' => 'mysql',
    'MYSQL_SSL_CA' => '',
    'TRUSTED_PROXIES' => '',
];
```

Remplacer toutes les valeurs en majuscules. Utiliser les accès du **registre**, et non ceux de la première pension. Encoder uniquement les parties utilisateur et mot de passe de l’URL avec `rawurlencode` pour que leurs caractères spéciaux ne cassent pas l’URL. Ne pas utiliser un encodeur de mots de passe sur un site tiers. Si le mot de passe contient une apostrophe ou un antislash, respecter aussi l’échappement PHP dans le fichier.

Si l’hébergeur impose une connexion MySQL chiffrée, ajouter son certificat CA à l’URL avec `?ssl_ca=/chemin/absolu/ca.pem` et renseigner aussi `MYSQL_SSL_CA` pour les pensions. Demander le certificat et le chemin à l’hébergeur ; ne pas désactiver la vérification TLS.

Le fichier est chargé automatiquement par le web et la console quand `PLATFORM_MODE` n’est pas déjà défini dans l’environnement. Ne pas ajouter le préfixe `PLATFORM_MODE=1` aux commandes de cette procédure : ce préfixe désactive le chargement du fichier privé. Si vous utilisez plutôt les variables d’environnement de l’hébergement, définir l’ensemble des valeurs ci-dessus dans ce mécanisme et conserver une seule méthode cohérente.

Avec un accès HTTPS direct, laisser `TRUSTED_PROXIES` vide. Si l’hébergeur termine HTTPS sur un proxy et PHP considère la requête comme HTTP, demander les adresses exactes de ses proxys et les renseigner séparées par des virgules. Ne pas mettre `*` ou une plage qui couvre tout Internet.

Conserver une copie privée et sûre de ce fichier. La clé de chiffrement doit rester identique lors des mises à jour.

## 6. Créer votre compte et ouvrir l’administration

Depuis le terminal de l’hébergement, dans le dossier du projet :

```sh
php bin/console cache:clear --env=prod
php bin/console app:platform:create-admin
```

La seconde commande demande votre e-mail, votre nom et un mot de passe provisoire d’au moins douze caractères, avec confirmation masquée.

Ouvrir **https://backmapension.bouillot.dev/plateforme**. Se connecter, choisir un nouveau mot de passe, puis scanner le QR avec une application d’authentification. Conserver les dix codes de secours ; ils sont affichés une seule fois.

En cas de difficulté, les journaux se trouvent dans `var/log/` ou dans les journaux PHP proposés par l’hébergeur. Ne pas passer le site public en mode développement pour afficher les erreurs aux visiteurs.

## 7. Créer la première pension

Dans l’administration, cliquer sur **Créer une pension**. Renseigner son nom, son sous-domaine, le responsable, son e-mail et son mot de passe provisoire. Dans la section MySQL, saisir les accès à la **base vide dédiée à cette pension**, créée à l’étape 3.

Par exemple, le sous-domaine `demo` donne **https://demo.bouillot.dev**. Le CRM initialise les tables et le compte du responsable. Il ne crée pas le DNS, le sous-domaine ou le certificat : s’ils ne sont pas génériques, les ajouter dans le panneau de l’hébergeur avant d’ouvrir cette pension.

Le responsable doit changer son mot de passe à sa première connexion. Il peut ensuite ajouter les membres du personnel depuis son CRM. Le sous-domaine `backmapension` est réservé à votre administration globale.

## 8. Importer vos données actuelles, si souhaité

Avant de remplir la pension cible, arrêter temporairement les saisies locales et sauvegarder `var/data/pension.json` avec les dossiers `pension.json.documents` et `pension.json.photos`, s’ils existent.

Envoyer le JSON et ses dossiers côte à côte dans un dossier **privé** du serveur, par exemple `var/import/`. Ne pas les mettre dans `public/`. Depuis le projet, remplacer `ma-pension` par le sous-domaine réel de la pension cible :

```sh
php bin/console app:tenant:transfer import ma-pension "$PWD/var/import/pension.json"
```

Le transfert préserve la source et copie ses pièces. Il refuse une pension déjà remplie. Vérifier les fiches, réservations, comptes et documents dans le CRM après l’import. Conserver votre sauvegarde d’origine et retirer ensuite la copie d’import du serveur lorsqu’elle n’est plus utile.

## 9. Vérifier et sauvegarder

Vérifier votre connexion globale, la connexion du responsable et le refus d’accès sans connexion. Créer une deuxième pension de test si votre offre le permet et vérifier que ses fiches sont séparées. Contrôler sur mobile l’affichage, un téléchargement de document et une photo de chien.

Pour exporter toutes les pensions et un instantané du registre :

```sh
php bin/console app:platform:maintain --backup-directory="$PWD/var/backups"
```

Les ZIP contiennent les données et les pièces. Programmer cette commande dans le planificateur de l’hébergeur si disponible, avec le chemin absolu vers PHP et le projet. Prévoir une rétention pour ne pas saturer le disque et copier les sauvegardes vers un stockage privé distinct. Sauvegarder également la base du registre via les outils MySQL de l’hébergeur et votre configuration secrète.

Tester une restauration vers une pension neuve avant de compter sur les sauvegardes. Pour les commandes de restauration et la récupération d’un accès administrateur, voir [PLATFORM.md](PLATFORM.md).

Cette procédure prépare le déploiement ; aucun DNS, certificat, compte d’hébergement ou site en ligne n’a été modifié par le CRM.
