# Déployer un projet Symfony Exemple : déployer depuis GitHub un projet Symfony sur {{SITE}}, avec sa base `{{CLIENT}}_app`. Avec HestiaCP, PHP-FPM, le cron et SSH tournent **tous** sous {{CLIENT}}. Il n'y a donc plus de cron de permissions sur `var/cache`, plus d'ACL et plus de `chmod 777`. > [!NOTE] Prérequis > - Le site {{SITE}} existe, avec SSL (chapitre 7). > - La base `{{CLIENT}}_app` existe (chapitre 8). > - La boîte `noreply` existe (chapitre 9). ## Se connecter en tant que {{CLIENT}} Depuis votre ordinateur : ```bash ssh -p {{SSH_PORT}} {{CLIENT}}@{{IP}} ``` Toutes les commandes de ce chapitre se lancent **en {{CLIENT}}**, sauf mention contraire. ## Créer une clé de déploiement GitHub ```bash ssh-keygen -t ed25519 -f ~/.ssh/github_deploy -N "" -C "deploy@{{SITE}}" cat >> ~/.ssh/config << 'EOF' Host github.com IdentityFile ~/.ssh/github_deploy IdentitiesOnly yes EOF chmod 600 ~/.ssh/config cat ~/.ssh/github_deploy.pub ``` Sur GitHub, dans le dépôt : **Settings › Deploy keys › Add deploy key**. Collez la clé affichée et laissez « Allow write access » **décoché**. > [!CHECK] > `ssh -T git@github.com` répond `Hi /! You've successfully authenticated…` (tapez `yes` à la première connexion). ## Cloner le projet Le dossier `public_html` contient une page d'accueil HestiaCP par défaut : videz-le, puis clonez le projet dedans. ```bash cd ~/web/{{SITE}}/public_html rm -f index.html robots.txt # Remplacez COMPTE/PROJET par votre dépôt GitHub git clone git@github.com:COMPTE/PROJET.git . ls ``` > [!CHECK] > Vous voyez `bin/`, `config/`, `public/`, `src/`, `composer.json`… > [!WARNING] Le fichier .htaccess de Symfony > Apache a besoin de `public/.htaccess` pour router les URL vers `index.php`. S'il n'existe pas dans votre dépôt, ajoutez-le **sur votre poste** avec `composer require symfony/apache-pack`, puis commitez-le. ## Configurer l'environnement de production Générez un secret : ```bash php -r 'echo bin2hex(random_bytes(16)), PHP_EOL;' ``` Relevez la version exacte de MariaDB : ```bash mariadb --version ``` Créez `.env.local` avec vos valeurs. `serverVersion` reprend la version affichée, par exemple `11.8.3-MariaDB` : ```bash cat > .env.local << 'EOF' APP_ENV=prod APP_DEBUG=0 APP_SECRET=collez_le_secret_ici DATABASE_URL="mysql://{{CLIENT}}_app:MOT_DE_PASSE_BDD@127.0.0.1:3306/{{CLIENT}}_app?serverVersion=11.8.3-MariaDB&charset=utf8mb4" MAILER_DSN=smtp://noreply%40{{DOMAINE}}:MOT_DE_PASSE_NOREPLY@mail.{{DOMAINE}}:587 EOF chmod 600 .env.local ``` ## Installer les dépendances et la base ```bash composer install --no-dev --optimize-autoloader php bin/console doctrine:migrations:migrate --no-interaction php bin/console cache:clear ``` > [!CHECK] > `php bin/console about` affiche `Environment: prod` et `Debug: false`. ## Pointer le site sur le dossier public/ À faire **avec {{USER}}** (dans une autre session SSH). Le dernier argument `yes` est indispensable : sans lui, PHP n'aurait plus accès à `vendor/`, `var/` ni `config/`, et le site planterait. ```bash sudo v-change-web-domain-docroot {{CLIENT}} {{SITE}} {{SITE}} public yes ``` > [!CHECK] > `curl -sI https://{{SITE}} | head -1` renvoie `HTTP/2 200`, et la page d'accueil de l'application s'affiche dans le navigateur. > [!TIP] > Dans le panel, c'est **Modifier le domaine › Options avancées › Racine de document personnalisée**, avec **Pointer vers** = {{SITE}} et **Répertoire** = `public`. ## Créer le script de déploiement En {{CLIENT}}, créez `~/deploy-{{SITE}}.sh`. Il utilise des chemins complets, car les alias (`composer`, `php`) ne fonctionnent pas dans un script. ```bash cat > ~/deploy-{{SITE}}.sh << 'EOF' #!/bin/bash set -euo pipefail PHP=/usr/bin/php8.4 COMPOSER="$PHP $HOME/.composer/composer" cd "$HOME/web/{{SITE}}/public_html" git pull --ff-only $COMPOSER install --no-dev --optimize-autoloader --no-interaction $PHP bin/console doctrine:migrations:migrate --no-interaction --allow-no-migration $PHP bin/console cache:clear echo "Déploiement terminé : $(git log -1 --format='%h %s')" EOF chmod 700 ~/deploy-{{SITE}}.sh ``` Pour déployer une nouvelle version, depuis votre ordinateur : ```bash ssh -p {{SSH_PORT}} {{CLIENT}}@{{IP}} ./deploy-{{SITE}}.sh ``` > [!NOTE] > OPcache vérifie la date des fichiers : le nouveau code est pris en compte en quelques secondes, sans redémarrer PHP-FPM. ## Ajouter les tâches planifiées À faire avec {{USER}}. Les `*` doivent être entre guillemets. Exemple : une commande toutes les 5 minutes, et le worker Messenger, relancé toutes les 5 minutes pendant 4 min 50 s. ```bash sudo v-add-cron-job {{CLIENT}} '*/5' '*' '*' '*' '*' "/usr/bin/php8.4 /home/{{CLIENT}}/web/{{SITE}}/public_html/bin/console app:ma-commande" sudo v-add-cron-job {{CLIENT}} '*/5' '*' '*' '*' '*' "/usr/bin/php8.4 /home/{{CLIENT}}/web/{{SITE}}/public_html/bin/console messenger:consume async --time-limit=290 --quiet" sudo v-list-cron-jobs {{CLIENT}} ``` ## Connaître les limites de PHP-FPM Pour la sécurité, HestiaCP désactive certaines fonctions dans le PHP **web** (PHP-FPM) : `exec`, `system`, `shell_exec`, `passthru`, `proc_open`, `popen`. Tout ce qui lance un processus depuis une page web échouera, par exemple le composant Process ou le transport mail `sendmail://`. Faites ces traitements en console (cron, Messenger), où ces fonctions restent disponibles. Les chemins accessibles à PHP-FPM (`open_basedir`) se limitent à `public_html/`, `private/`, `~/tmp` et `~/.composer`. Gardez `var/` (cache, logs) **dans** le projet. Pour les fichiers envoyés par les utilisateurs, `public_html/public/uploads` ou `private/` conviennent. > [!TIP] Journaux > Erreurs Symfony : `~/web/{{SITE}}/public_html/var/log/prod.log`. Erreurs Apache/PHP : `~/web/{{SITE}}/logs/`.