Type Nom Valeur TTL
A @ 203.0.113.42 3600
A www 203.0.113.42 3600dig +short mon-domaine.com
# doit renvoyer 203.0.113.422. Proteggere l'accesso SSH
adduser amar
usermod -aG sudo amar
# copier sa cle publique pour l'authentification sans mot de passe
rsync --archive --chown=amar:amar ~/.ssh /home/amarPoi si rafforza la configurazione SSH per vietare la connessione root e l'autenticazione tramite password:
# /etc/ssh/sshd_config
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yessudo systemctl restart sshd
# on garde la session root ouverte tant qu'on n'a pas confirme
# qu'on peut se reconnecter avec le nouvel utilisateur, dans un AUTRE terminal
ssh amar@mon-domaine.com3. Aggiornare il sistema e installare i pacchetti necessari
sudo apt update && sudo apt upgrade -y
# PHP 8.4 et les extensions dont Symfony a besoin
sudo apt install -y php8.4 php8.4-fpm php8.4-cli php8.4-common \
php8.4-mysql php8.4-xml php8.4-curl php8.4-mbstring \
php8.4-zip php8.4-intl php8.4-opcache php8.4-gd
# Apache, MySQL, Git, outils
sudo apt install -y apache2 mysql-server git unzip curl
# Composer
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composerVerifichiamo le versioni installate prima di andare avanti:
php -v
composer --version
apache2 -v4. Creare la struttura di cartelle e i permessi corretti
sudo mkdir -p /var/www/mon-projet
sudo adduser --system --group --no-create-home --shell /usr/sbin/nologin www-monprojet
# le code appartient a l'utilisateur dedie, le groupe www-data
# (celui du serveur web) doit pouvoir le lire
sudo chown -R www-monprojet:www-data /var/www/mon-projetIl punto che più spesso fa fallire una messa in produzione di Symfony: le cartelle var/cache e var/log devono essere scrivibili dal processo PHP-FPM, senza però aprire tutto il progetto in scrittura:
cd /var/www/mon-projet
sudo chmod -R 755 .
sudo chmod -R 775 var/cache var/log public/uploads
# le bit setgid garde le groupe www-data sur les nouveaux fichiers/dossiers
# crees dans var/ et uploads/, meme si un autre utilisateur les cree
sudo chmod g+s var/cache var/log public/uploadsSe i permessi danno ancora problemi (errore Unable to write in the "var/cache" directory), la soluzione più pulita è setfacl invece di un chmod 777 — mai 777 in produzione:
sudo apt install -y acl
sudo setfacl -R -m u:www-monprojet:rwX -m u:www-data:rwX var/cache var/log public/uploads
sudo setfacl -dR -m u:www-monprojet:rwX -m u:www-data:rwX var/cache var/log public/uploads5. Distribuire il codice
sudo -u www-monprojet git clone git@github.com:moi/mon-projet.git /var/www/mon-projet
cd /var/www/mon-projet
sudo -u www-monprojet composer install --no-dev --optimize-autoloader --no-interactionsudo -u www-monprojet tee .env.local > /dev/null << 'EOF'
APP_ENV=prod
APP_SECRET=change_moi_avec_une_vraie_valeur_aleatoire
DATABASE_URL="mysql://mon_user:mon_mdp@127.0.0.1:3306/mon_projet?serverVersion=8.0"
EOF
sudo chmod 640 .env.local
sudo chown www-monprojet:www-monprojet .env.localsudo -u www-monprojet php bin/console cache:clear --env=prod --no-debug
sudo -u www-monprojet php bin/console cache:warmup --env=prod6. Creare il database
CREATE DATABASE mon_projet CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
CREATE USER 'mon_user'@'localhost' IDENTIFIED BY 'mon_mdp';
GRANT ALL PRIVILEGES ON mon_projet.* TO 'mon_user'@'localhost';
FLUSH PRIVILEGES;sudo -u www-monprojet php bin/console doctrine:migrations:migrate --no-interaction7. Un pool PHP-FPM dedicato
; /etc/php/8.4/fpm/pool.d/mon-projet.conf
[mon-projet]
user = www-monprojet
group = www-data
listen = /run/php/mon-projet.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3sudo systemctl restart php8.4-fpm8. Il virtual host Apache
<VirtualHost *:80>
ServerName mon-domaine.com
ServerAlias www.mon-domaine.com
DocumentRoot /var/www/mon-projet/public
<Directory /var/www/mon-projet/public>
AllowOverride All
Require all granted
FallbackResource /index.php
</Directory>
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/mon-projet.sock|fcgi://localhost"
</FilesMatch>
ErrorLog ${APACHE_LOG_DIR}/mon-projet-error.log
CustomLog ${APACHE_LOG_DIR}/mon-projet-access.log combined
</VirtualHost>sudo a2enmod proxy_fcgi setenvif rewrite
sudo a2ensite mon-projet.conf
sudo apache2ctl configtest
sudo systemctl reload apache2A questo punto, http://mon-domaine.com (in HTTP, senza la S) deve già mostrare l'applicazione.
sudo apt install -y certbot python3-certbot-apache
sudo certbot --apache -d mon-domaine.com -d www.mon-domaine.comsudo systemctl status certbot.timer
sudo certbot renew --dry-run#!/usr/bin/env bash
# deploy.sh — a lancer en tant qu'utilisateur www-monprojet
set -euo pipefail
cd /var/www/mon-projet
git pull origin main
composer install --no-dev --optimize-autoloader --no-interaction
php bin/console doctrine:migrations:migrate --no-interaction
php bin/console cache:clear --env=prod --no-debug
php bin/console cache:warmup --env=prod
echo "Déploiement terminé : $(date)"chmod +x deploy.sh
sudo -u www-monprojet ./deploy.shChecklist finale
- DNS: dig +short mon-domaine.com restituisce correttamente l'IP del VPS.
- SSH: connessione possibile solo tramite chiave, con un utente non-root.
- var/cache, var/log e le cartelle di upload sono scrivibili da PHP-FPM, senza chmod 777.
- .env.local esiste sul server, non è mai versionato ed è leggibile solo dall'utente applicativo.
- Il pool PHP-FPM è dedicato all'applicazione, non condiviso con altri siti del VPS.
- https://mon-domaine.com risponde con un certificato valido, e l'HTTP reindirizza verso l'HTTPS.
- Esiste uno script di deploy per il prossimo aggiornamento, per non rifare questi passaggi a mano.
- Non usare mai chmod 777 per risolvere un problema di permessi — setfacl o un buon chown verso un utente dedicato risolvono il problema senza aprire il progetto a tutti.
- Un utente di sistema e un pool PHP-FPM per applicazione isolano in modo pulito ogni sito, anche su un VPS che ne ospita diversi (vedi il mio articolo sull'hosting di 15+ applicazioni su un solo VPS).
- Certbot con il plugin Apache fa tutto il lavoro (certificato + reindirizzamento HTTPS) con un solo comando — non serve configurare nulla a mano.
- Testare sempre la connessione SSH con il nuovo utente in un secondo terminale prima di chiudere la sessione root, per non ritrovarsi mai chiusi fuori.
- Uno script di deploy, anche basilare, evita di dimenticare un passaggio (migrazione, cache) tre mesi dopo, quando avremo dimenticato tutti i dettagli.