Guide de déploiement

Déployer Symfony sur VPS : guide complet 2024

Déployer sur un VPS Cloud →

Tutoriel

Déployer Symfony sur VPS : guide complet 2024

Développement8 min de lecture16 étapes

Un VPS vous donne le contrôle total que Symfony mérite : PHP 8.3, extensions natives, workers asynchrones et accès root complet. Ce guide couvre l'installation de PHP 8.3, le déploiement automatisé avec Deployer PHP, la configuration nginx et Supervisor pour les queues, ainsi que le durcissement de sécurité. En fin d'article, découvrez comment le Marketplace ServOrbit automatise tout ce socle en quelques clics.

Sommaire· Pourquoi Symfony sur VPS plutôt que sur mutualisé ?1/10
  1. 01Pourquoi Symfony sur VPS plutôt que sur mutualisé ?
  2. 02Ce que le VPS débloque pour Symfony
  3. 03Prérequis chiffrés — ressources et logiciels
  4. 04Installer PHP 8.3 et Symfony CLI sur VPS Ubuntu
  5. 05Déployer une app Symfony en production avec Deployer PHP
  6. 06Configuration nginx pour Symfony
  7. 07Variables d'environnement et sécurité
  8. 08Queues asynchrones avec Symfony Messenger et Supervisor
  9. 09Dépannage — les 4 erreurs les plus fréquentes
  10. 10Déployer depuis le Marketplace ServOrbit

Pourquoi Symfony sur VPS plutôt que sur mutualisé ?

Un hébergement mutualisé impose la version PHP du serveur, désactive les extensions jugées « dangereuses » et interdit l'installation de processus persistants. Symfony 7 requiert PHP 8.2 au minimum — une contrainte que de nombreux mutualisés ne satisfont pas encore. Sur VPS, vous choisissez PHP 8.3 dès le premier jour, activez OPcache avec une configuration fine, et installez ext-redis, ext-intl ou ext-amqp selon vos besoins.

Les workers asynchrones (Symfony Messenger) exigent un processus qui tourne en fond, géré par Supervisor ou systemd. Sur mutualisé, ce processus est tout simplement impossible. Sur VPS, il démarre en une commande et redémarre automatiquement après un crash. Pour une application Symfony qui traite des emails transactionnels, des notifications push ou de l'import de fichiers, c'est une différence non négociable.

Ce que le VPS débloque pour Symfony

  • Accès root complet — installez n'importe quelle extension PHP, configurez OPcache à la ligne près et modifiez php.ini sans ticket support
  • PHP 8.3 natif — profitez des typed class constants, de la syntaxe #[Override] et des performances du JIT amélioré sans attendre la migration du serveur partagé
  • Supervisor et workers persistants — faites tourner messenger:consume en continu, avec redémarrage automatique et rotation des logs, pour traiter vos queues sans cron hacké
  • Redis en local — installez Redis sur le même VPS pour les sessions, le cache Doctrine et les transports Messenger, éliminant ainsi la latence réseau vers un service externe
  • Multi-version PHP via ondrej/php — maintenez PHP 8.1 pour une app legacy et PHP 8.3 pour la nouvelle, sur le même hôte, avec des pools FPM séparés
  • Xdebug et profiling en staging — activez Blackfire ou Xdebug sur l'environnement de recette sans impacter la prod, dans le même datacenter
  • Déploiements atomiques avec Deployer — zéro downtime grâce aux symlinks, rollback en une commande, hooks dep deploy intégrés dans votre pipeline CI/CD

Prérequis chiffrés — ressources et logiciels

Système d'exploitation : Ubuntu 24.04 LTS ou Debian 12. Ces deux distributions bénéficient des dépôts ondrej/php et d'un support long terme compatible avec les cycles de maintenance de Symfony.

PHP : version 8.3 recommandée (minimum 8.2 pour Symfony 7). Extensions requises : php8.3-cli, php8.3-fpm, php8.3-mbstring, php8.3-xml, php8.3-curl, php8.3-zip, php8.3-intl, php8.3-opcache. Ajoutez php8.3-redis si vous utilisez Redis, php8.3-pgsql pour PostgreSQL.

Composer : version 2.x obligatoire. Composer 1.x ne supporte pas les contraintes de packages modernes.

Base de données : MySQL 8.0+ ou PostgreSQL 16+. Pour une app Symfony standard, 1 Go de RAM suffit pour MySQL ; PostgreSQL recommande 2 Go pour les plans de requête optimaux.

Nginx : 1.24+ depuis les dépôts officiels Ubuntu ou nginx.org.

RAM minimale :
- 1 Go : développement ou app légère sans queues
- 2 Go : production avec Symfony Messenger et un transport Redis
- 4 Go : workers multiples, Redis, sessions haute fréquence

Ports à ouvrir : 80 (HTTP), 443 (HTTPS), 22 (SSH). Fermez tout le reste.

Installer PHP 8.3 et Symfony CLI sur VPS Ubuntu

  1. Mettre à jour le système et installer les dépendances préalables

    apt update && apt upgrade -y && apt install -y curl git unzip software-properties-common

  2. Ajouter le dépôt ondrej/php pour obtenir PHP 8.3 sur Ubuntu 24.04

    add-apt-repository ppa:ondrej/php && apt update

  3. Installer PHP 8.3-FPM et les extensions requises par Symfony

    apt install -y php8.3-fpm php8.3-cli php8.3-mbstring php8.3-xml php8.3-curl php8.3-zip php8.3-intl php8.3-opcache php8.3-redis php8.3-mysql

  4. Vérifier la version installée et l'état du service FPM

    php --version && systemctl status php8.3-fpm

  5. Installer Composer 2.x globalement

    curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer && composer --version

  6. Installer la Symfony CLI pour créer des projets et vérifier les prérequis

    curl -1sLf 'https://dl.cloudsmith.io/public/symfony/stable/setup.deb.sh' | bash && apt install -y symfony-cli

  7. Vérifier que tous les prérequis Symfony sont satisfaits

    symfony check:requirements

  8. Installer nginx et Redis

    apt install -y nginx redis-server && systemctl enable --now nginx redis-server

Déployer une app Symfony en production avec Deployer PHP

  1. Dans votre projet Symfony local, ajouter Deployer comme dépendance de développement

    composer require deployer/deployer --dev

  2. Initialiser la configuration Deployer (choisir le recette `symfony` à la question)

    ./vendor/bin/dep init

  3. Éditer `deploy.php` à la racine du projet — adapter host, chemin de déploiement et branches

    require 'recipe/symfony.php';
    set('repository', '[email protected]:votre-org/votre-app.git');
    host('votre-vps.example.com')
    ->set('remote_user', 'deploy')
    ->set('deploy_path', '/var/www/symfony-app');

  4. Sur le VPS, créer l'utilisateur de déploiement et lui donner accès à nginx

    useradd -m -s /bin/bash deploy && usermod -aG www-data deploy

  5. Créer le fichier `.env.local` sur le VPS dans `{{deploy_path}}/shared/` — il sera partagé entre toutes les releases

    APP_ENV=prod
    APP_DEBUG=false
    APP_SECRET=<secret-aleatoire-32-chars>
    DATABASE_URL=mysql://user:[email protected]:3306/symfony_db

  6. Lancer le premier déploiement depuis votre machine locale

    ./vendor/bin/dep deploy production

  7. Vérifier que le symlink `current/` pointe bien vers la dernière release

    ls -la /var/www/symfony-app/

  8. En cas de problème, effectuer un rollback immédiat vers la release précédente

    ./vendor/bin/dep rollback production

Configuration nginx pour Symfony

Créez le fichier /etc/nginx/sites-available/symfony-app avec ce bloc server minimal, puis activez-le avec un symlink vers sites-enabled/.

server {
    listen 80;
    server_name votre-domaine.com;
    root /var/www/symfony-app/current/public;
    index index.php;

    location / {
        try_files $uri /index.php$is_args$args;
    }

    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT $realpath_root;
    }

    location ~ /\.ht {
        deny all;
    }
}

Activez le site et testez la configuration avant de recharger nginx :
ln -s /etc/nginx/sites-available/symfony-app /etc/nginx/sites-enabled/ && nginx -t && systemctl reload nginx

Pour HTTPS, utilisez Certbot : certbot --nginx -d votre-domaine.com. Certbot modifie automatiquement le bloc server pour rediriger HTTP vers HTTPS et configurer les certificats Let's Encrypt.

Variables d'environnement et sécurité

Symfony lit .env, puis .env.local, puis .env.prod.local. En production, toute valeur sensible doit être dans .env.local — jamais commitée dans le dépôt git.

Variables essentielles en production :

APP_ENV=prod
APP_DEBUG=false
APP_SECRET=<64-chars-hex-aléatoire>
DATABASE_URL="mysql://dbuser:[email protected]:3306/symfony_prod"
MAILER_DSN=smtp://user:[email protected]:587
MESSENGER_TRANSPORT_DSN=redis://127.0.0.1:6379/messages

APP_SECRET doit être généré aléatoirement : openssl rand -hex 32. Ne jamais réutiliser la valeur par défaut du projet.

APP_DEBUG=false est critique : en mode debug, Symfony expose les traces de pile complètes, les variables de template et les requêtes SQL dans le navigateur — une fuite d'information sévère en production.

Pour les projets utilisant Symfony Secrets Vault (.env.vault), les secrets chiffrés peuvent être committés sans risque ; seule la clé de déchiffrement (SYMFONY_DECRYPTION_SECRET) reste dans .env.local.

Queues asynchrones avec Symfony Messenger et Supervisor

Symfony Messenger permet de différer les tâches lourdes (envoi d'email, génération PDF, webhooks) dans une queue traitée de façon asynchrone. Sur VPS, Supervisor garantit que le worker tourne en permanence et redémarre après un crash.

Installez Supervisor :
apt install -y supervisor

Créez /etc/supervisor/conf.d/symfony-messenger.conf :

[program:symfony-messenger]
command=/var/www/symfony-app/current/bin/console messenger:consume async --time-limit=3600
user=deploy
autostart=true
autorestart=true
startretries=3
redirect_stderr=true
stdout_logfile=/var/log/supervisor/symfony-messenger.log
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=5

L'option --time-limit=3600 force le worker à se relancer toutes les heures, libérant la mémoire accumulée. Supervisor s'occupe du redémarrage automatique.

Activez et démarrez le worker :
supervisorctl reread && supervisorctl update && supervisorctl start symfony-messenger

Pour surveiller l'état : supervisorctl status symfony-messenger

Côté Symfony, configurez le transport Redis dans config/packages/messenger.yaml :

framework:
    messenger:
        transports:
            async:
                dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
                retry_strategy:
                    max_retries: 3
                    delay: 1000

Hardening en 3 commandes. Bloquez l'accès à .git/ dans nginx (ajoutez location ~ /\.git { deny all; } à votre bloc server). Installez fail2ban pour bloquer les scans SSH et les tentatives de connexion répétées : apt install -y fail2ban. Restreignez les permissions du répertoire de déploiement : chmod 750 /var/www/symfony-app && chown -R deploy:www-data /var/www/symfony-app. Enfin, configurez le cache OPcache dans /etc/php/8.3/fpm/conf.d/10-opcache.ini : opcache.enable=1, opcache.memory_consumption=256, opcache.validate_timestamps=0 (désactivez la validation en prod pour les performances maximales — invalidez manuellement après chaque déploiement avec cachetool opcache:reset).

Dépannage — les 4 erreurs les plus fréquentes

1. The environment variable "APP_SECRET" is not set.
APP_SECRET est absent du fichier .env.local sur le serveur. Vérifiez que le fichier existe dans {{deploy_path}}/shared/ et qu'il contient bien cette variable. Deployer crée un symlink vers ce fichier partagé à chaque release — si le symlink est cassé, Symfony ne lit pas .env.local.

2. Erreur 500 silencieuse — logs vides
Avec APP_DEBUG=false, Symfony n'affiche rien dans le navigateur et écrit dans var/log/prod.log. Lisez ce fichier en temps réel : tail -f /var/www/symfony-app/current/var/log/prod.log. Une permission refusée sur var/cache/ ou var/log/ est la cause la plus fréquente — corrigez avec chown -R deploy:www-data var/ depuis le répertoire de la release courante.

3. Connection refused sur la base de données
DATABASE_URL pointe vers 127.0.0.1 mais MySQL écoute sur localhost (socket Unix) — ou l'inverse. Testez la connexion directement : mysql -u dbuser -p -h 127.0.0.1 symfony_db. Si MySQL n'écoute pas sur TCP, ajoutez bind-address = 127.0.0.1 dans /etc/mysql/mysql.conf.d/mysqld.cnf et redémarrez.

4. There are no commands defined in the "cache" namespace
Ce message trompeur signifie souvent que Symfony ne peut pas écrire dans var/cache/. Le processus PHP-FPM tourne sous www-data, mais le répertoire appartient à deploy sans permissions d'écriture pour le groupe. Solution : chmod -R 775 var/cache var/log && chown -R deploy:www-data var/.

Déployer depuis le Marketplace ServOrbit

Si vous préférez éviter les heures de configuration manuelle, le template symfony-stack du Marketplace ServOrbit installe et configure automatiquement tout le socle décrit dans ce guide : PHP 8.3-FPM, Composer, nginx optimisé pour Symfony, Redis, Supervisor et les permissions correctes. Le VPS est opérationnel en moins de 5 minutes, avec un accès SSH root immédiat pour personnaliser votre déploiement.

Le template configure également les variables d'environnement essentielles via un formulaire guidé au moment de la commande — APP_SECRET généré aléatoirement, DATABASE_URL pré-remplie avec les credentials MySQL créés pour votre instance.

Vous gardez un contrôle total : le VPS vous appartient, il n'y a aucun lock-in, et vous pouvez utiliser Deployer PHP exactement comme décrit ci-dessus dès la première connexion SSH.

Symfony opérationnel en 5 minutes

Commandez un VPS pré-configuré avec PHP 8.3, nginx, Redis et Supervisor — le stack Symfony complet installé et sécurisé, sans configuration manuelle.

Besoin d'aide ?

Parcourez notre centre d'aide et notre FAQ, ou contactez notre équipe — rappel, WhatsApp ou e-mail. Support en français, anglais et arabe.

Écrire sur WhatsApps'ouvre dans un nouvel onglet