Petite config d’apache
apt install libapache2-mod-fcgid a2enmod actions fcgid alias proxy_fcgi
Pour configurer chaque site web avec un utilisateur système différent, la méthode la plus courante et la plus robuste en PHP est d’utiliser PHP-FPM avec des pools séparés pour chaque site.
Voici les étapes générales :
Créer un utilisateur système et un groupe pour chaque site : Pour chaque site web, créez un utilisateur et un groupe dédiés. Par exemple, pour site1.com :
sudo groupadd site1 sudo useradd -g site1 -s /sbin/nologin site1user # ou adduser --allow-bad-names --shell /sbin/nologin site1.com # ne rien mettre comme mot de passe (plusieurs fois)
Répétez pour chaque site (site2user, site2, etc.). L’option -s /sbin/nologin empêche ces utilisateurs de se connecter directement au système.
Définir les permissions des dossiers des sites : Changez le propriétaire des répertoires de vos sites web pour qu’ils appartiennent à leur utilisateur et groupe respectifs :
chown -R site1user:site1 /var/www/site1.com # Assurez-vous que le répertoire du site est accessible en lecture par l'utilisateur chmod -R ug+rwX,o+rX-w /var/www/site1.com
Faites de même pour chaque site.
Configurer des pools PHP-FPM séparés : Si vous utilisez PHP-FPM (ce qui est fortement recommandé pour cette configuration), créez un fichier de configuration de pool pour chaque site. Ces fichiers se trouvent généralement dans /etc/php/X.X/fpm/pool.d/ (où X.X est votre version de PHP).
Par exemple, créez /etc/php/X.X/fpm/pool.d/site1.conf :
[site1] user = site1user group = site1 listen = /run/php/phpX.X-site1.sock ; Chemin unique pour le socket listen.owner = www-data ; L'utilisateur du serveur web (ex: nginx, apache) doit pouvoir accéder au socket listen.group = www-data pm = dynamic pm.max_children = 5 pm.start_servers = 2 pm.min_spare_servers = 1 pm.max_spare_servers = 3 pm.process_idle_timeout = 10s ; Définir le répertoire racine du site chdir = /var/www/site1.com ; Variables d'environnement si nécessaire ; php_admin_value[error_log] = /var/log/php-fpm/site1_error.log ; php_admin_flag[log_errors] = on
Répétez cette configuration pour chaque site, en changeant [site1], user, group, listen et chdir en conséquence.
Nginx : Pour chaque hôte virtuel (server block), configurez-le pour qu’il utilise le socket PHP-FPM du pool correspondant. Exemple pour /etc/nginx/sites-available/site1.com :
Nginx
server {
listen 80;
server_name site1.com www.site1.com;
root /var/www/site1.com/public; # Votre répertoire public
index index.php index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/phpX.X-site1.sock; # Pointer vers le bon socket
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# Autres configurations (logs, ssl, etc.)
}
Apache (avec mod_proxy_fcgi) : Configurez un VirtualHost pour chaque site. Exemple pour /etc/apache2/sites-available/site1.com.conf :
Apache
<VirtualHost *:80>
ServerName site1.com
ServerAlias www.site1.com
DocumentRoot /var/www/site1.com/public
<Directory /var/www/site1.com/public>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
<FilesMatch ".+\.ph(?:ar|p|tml)$">
SetHandler "proxy:unix:/run/php/phpX.X-site1.sock|fcgi://localhost/" # Pointer vers le bon socket
</FilesMatch>
ErrorLog ${APACHE_LOG_DIR}/site1_error.log
CustomLog ${APACHE_LOG_DIR}/site1_access.log combined
</VirtualHost>
Exemple avec plusieurs version de php pour le même site en fonction du répertoire
<VirtualHost *:80>
ServerName monsite.com
DocumentRoot /var/www/monsite
# Version par défaut pour toutes les URL (PHP 8.2)
<FilesMatch \.php$>
SetHandler "proxy:unix:/var/run/php/php8.2-fpm.sock|fcgi://localhost/"
</FilesMatch>
# Utiliser PHP 7.4 pour toutes les requêtes vers /blog
<LocationMatch "^/blog/.*\.php$">
SetHandler "proxy:unix:/var/run/php/php7.4-fpm.sock|fcgi://localhost/"
</LocationMatch>
# Utiliser PHP 8.0 pour toutes les requêtes vers /api
<LocationMatch "^/api/.*\.php$">
SetHandler "proxy:unix:/var/run/php/php8.0-fpm.sock|fcgi://localhost/"
</LocationMatch>
</VirtualHost>
Redémarrer les services : Après toutes ces modifications, redémarrez les services concernés :
Bash
sudo systemctl restart phpX.X-fpm sudo systemctl restart nginx # ou sudo systemctl restart apache2
Avantages de cette méthode :
Sécurité accrue : Chaque site s’exécute avec des permissions limitées à son propre environnement, réduisant le risque qu’un site compromis n’affecte les autres.
Isolation des processus : Les processus PHP de chaque site sont isolés, ce qui améliore la stabilité.
Facilite la configuration de Postfix : Avec chaque site s’exécutant sous un user différent, Postfix verra des expéditeurs comme site1user@votre_serveur ou site2user@votre_serveur.
Configurer main.cf pour utiliser les tables de réécriture :
Modifiez votre fichier /etc/postfix/main.cf et ajoutez les lignes suivantes (ou assurez-vous qu’elles sont présentes et non commentées) :
# Pour réécrire l'adresse de l'expéditeur basée sur le domaine d'origine sender_canonical_maps = hash:/etc/postfix/sender_canonical # Alternativement, ou en complément, pour réécrire les adresses génériques (plus global) smtp_generic_maps = hash:/etc/postfix/generic
sender_canonical_maps est généralement préféré pour les envois spécifiques de vos applications, car il se concentre sur l’expéditeur.
smtp_generic_maps peut aussi être utilisé, mais il est plus “générique” comme son nom l’indique, et est souvent utilisé pour des réécritures plus larges, par exemple, pour s’assurer que toutes les adresses locales (user@localhost) sont réécrites avec un domaine public.
Créer les fichiers de mappage :
Pour sender_canonical_maps (recommandé) :
Créez un fichier /etc/postfix/sender_canonical et ajoutez-y les règles de réécriture. Par exemple, si votre site site1.com utilise un utilisateur système webuser1 pour envoyer des mails, et que site2.net utilise webuser2, vous pouvez faire ceci :
# /etc/postfix/sender_canonical webuser1@yourserver.com no-reply@site1.com webuser2@yourserver.com contact@site2.net @site1.local @site1.com @site2.local @site2.net
Remplacez yourserver.com, site1.com, site2.net, site1.local, site2.local par vos noms d’hôte et domaines réels. @siteX.local est utile si vos applications PHP génèrent des adresses d’expéditeur avec le nom de l’hôte local.
Pour smtp_generic_maps (alternative ou complément) :
Créez un fichier /etc/postfix/generic et ajoutez-y des règles similaires :
# /etc/postfix/generic /^webuser1@.*/ no-reply@site1.com /^webuser2@.*/ contact@site2.net
Cette approche utilise des expressions régulières pour capturer n’importe quelle adresse provenant de webuser1 et la réécrire.
Générer les bases de données Postfix : Après avoir modifié les fichiers sender_canonical ou generic, vous devez les convertir en une base de données que Postfix peut utiliser efficacement. Exécutez les commandes suivantes :
Bash
sudo postmap /etc/postfix/sender_canonical # Si vous utilisez aussi generic: sudo postmap /etc/postfix/generic
Recharger Postfix :
Pour que les modifications prennent effet, rechargez Postfix :
Bash
sudo postfix reload
Points importants à considérer :
DNS (SPF, DKIM, DMARC) : Pour que vos e-mails ne soient pas marqués comme spam, il est crucial de configurer correctement les enregistrements DNS SPF, DKIM et DMARC pour chaque domaine qui envoie des e-mails. Ces enregistrements indiquent aux serveurs de messagerie destinataires que votre serveur Postfix est autorisé à envoyer des e-mails pour ces domaines.
Utilisateurs système et PHP : Assurez-vous que vos applications PHP envoient les e-mails en utilisant des utilisateurs système distincts ou des adresses d’expéditeur (From: header) que Postfix peut identifier et réécrire. Si vos scripts PHP définissent déjà correctement l’adresse From:, Postfix honorera souvent cela. Cependant, la réécriture avec sender_canonical_maps est une sécurité supplémentaire si les scripts ne sont pas parfaits.
Nom d’hôte du serveur : Assurez-vous que le nom d’hôte de votre serveur Postfix est correctement configuré (paramètre myhostname dans main.cf).
C’est la méthode standard pour héberger plusieurs sites PHP de manière isolée et sécurisée.