12 KiB
Créer un groupe d'utilisateurs pour un site web Apache
Pourquoi un groupe par site ?
Quand on héberge un site web, deux populations doivent pouvoir lire ses fichiers : Apache (le serveur web, qui les sert aux visiteurs) et les personnes qui maintiennent le site (développeurs, intégrateurs, administrateurs de contenu). Si on ne réfléchit pas à la question des droits, on tombe rapidement dans un des deux travers classiques :
- Tout ouvrir (
chmod 777partout) : c'est la porte ouverte aux compromissions. Si une faille permet à Apache d'écrire un fichier, l'attaquant peut alors écraser n'importe quel script PHP du site. - Tout faire en root : c'est pratique au début, mais cela impose à chaque mainteneur de connaître le mot de passe administrateur, et il devient impossible de tracer qui a modifié quoi.
La bonne pratique est donc de créer un groupe dédié par site, qui rassemble les personnes habilitées à intervenir dessus. Plusieurs avantages :
- Évolutif : ajouter ou retirer un mainteneur revient à ajouter ou retirer un utilisateur du groupe, sans rien changer aux permissions des fichiers.
- Étanche : les mainteneurs d'un site n'ont aucun droit sur les autres sites de la machine.
- Traçable : chaque modification est faite par un compte nommé, pas par
root.
Cette approche reste valable même pour un site géré par une seule personne : le jour où vous voudrez déléguer la maintenance ou simplement créer un compte de déploiement, le travail aura déjà été fait.
Dans cet article, on prend comme exemple un site fictif perdu.com, dont les fichiers seront placés dans /var/www/perdu.com. Adaptez les noms à votre cas.
Étape 1 — Créer le groupe dédié
sudo groupadd www-perdu.com
Le nom du groupe est arbitraire ; le préfixe www- est une convention qui rappelle qu'il s'agit d'un groupe lié à un site web. Vous pouvez vérifier sa création :
getent group www-perdu.com
Étape 2 — Ajouter les mainteneurs au groupe
Ajoutez chaque utilisateur qui devra travailler sur le site :
sudo usermod -aG www-perdu.com chloe
L'option -a (append) est obligatoire : sans elle, -G remplace la liste complète des groupes secondaires de l'utilisateur au lieu d'y ajouter. C'est l'erreur classique qui fait perdre à quelqu'un l'accès à sudo, docker ou libvirt parce qu'on a écrasé ses autres appartenances.
Pour ajouter plusieurs personnes :
sudo usermod -aG www-perdu.com chloe
sudo usermod -aG www-perdu.com mathieu
Important : l'appartenance à un nouveau groupe n'est prise en compte qu'à la prochaine ouverture de session. Si chloe est déjà connectée, elle doit se déconnecter puis se reconnecter (ou ouvrir un nouveau terminal SSH). Pour vérifier ses groupes effectifs :
groups chloe
Étape 3 — Créer l'arborescence du site
On place le site dans /var/www, l'emplacement standard sur Debian/Ubuntu et un choix courant sur Fedora/RHEL :
sudo mkdir -p /var/www/perdu.com/www
sudo mkdir -p /var/www/perdu.com/logs
L'option -p crée les dossiers parents au besoin et ne renvoie pas d'erreur s'ils existent déjà. La structure proposée sépare les fichiers servis publiquement (www/) de ce qui ne doit jamais être exposé (logs applicatifs, sauvegardes, données privées).
À ce stade, les dossiers appartiennent à root:root avec des droits 755. Personne d'autre que root ne peut y écrire.
Étape 4 — Attribuer la propriété au groupe
On veut que :
- Le groupe
www-perdu.compuisse lire et écrire dans les dossiers (les mainteneurs déploient et modifient les fichiers). - Apache puisse lire les fichiers pour les servir.
- Personne d'autre ne puisse y accéder.
On commence par attribuer le groupe :
sudo chgrp -R www-perdu.com /var/www/perdu.com
L'option -R (récursif) applique le changement à tout le contenu déjà présent.
Puis on applique des permissions adaptées :
sudo find /var/www/perdu.com -type d -exec chmod 2775 {} \;
sudo find /var/www/perdu.com -type f -exec chmod 664 {} \;
Décortiquons ce qui se passe ici. On utilise find plutôt qu'un chmod -R unique parce que les permissions des dossiers et des fichiers ne doivent pas être les mêmes : un fichier de configuration n'a pas à être exécutable, alors qu'un dossier a besoin du bit x pour être parcouru.
- Dossiers :
2775soitrwxrwsr-x. Le propriétaire (root) et les membres du groupewww-perdu.compeuvent lire, écrire et entrer dans le dossier. Les autres (dontwww-data/apache) peuvent lire et entrer, mais pas modifier. - Fichiers :
664soitrw-rw-r--. Le propriétaire et le groupe peuvent lire et écrire, les autres uniquement lire.
Le bit SGID : pourquoi le 2 en tête ?
Le chiffre 2 devant 775 active le bit SGID sur les dossiers. Ce bit a un effet décisif : tout nouveau fichier ou sous-dossier créé hérite automatiquement du groupe du dossier parent, au lieu d'hériter du groupe principal de la personne qui le crée.
Sans SGID, si chloe (dont le groupe principal est chloe) crée un fichier, ce fichier appartient au groupe chloe, ce qui le rend invisible en écriture pour les autres mainteneurs du site. Avec SGID, le fichier appartient automatiquement à www-perdu.com, et toute l'équipe peut continuer à travailler dessus sans intervention.
Si vous préférez utiliser chmod directement plutôt que find, voici la version équivalente — un peu plus permissive sur les exécutables existants, mais plus simple à retenir :
sudo chmod -R g+rwX,o+rX,o-w /var/www/perdu.com
sudo find /var/www/perdu.com -type d -exec chmod g+s {} \;
L'astuce du X majuscule (au lieu de x minuscule) est utile : elle n'ajoute le droit d'exécution qu'aux dossiers et aux fichiers déjà exécutables, sans rendre exécutables tous les fichiers texte par mégarde.
Étape 5 — Garantir les bons droits sur les nouveaux fichiers
Le SGID s'occupe du groupe, mais pas des permissions elles-mêmes. Pour que les fichiers créés par un mainteneur soient en 664 (et non en 644 qui interdirait l'écriture aux autres membres du groupe), il faut un umask permissif côté utilisateur.
Demandez à chaque mainteneur d'ajouter cette ligne à son ~/.bashrc :
umask 0002
Cet umask conserve les droits d'écriture pour le groupe. Avec un umask 0022 (le défaut habituel), chloe créerait des fichiers en 644 que mathieu ne pourrait pas modifier.
Solution plus robuste : les ACL
Si vous voulez une garantie absolue sans dépendre du umask de chacun, les ACL (Access Control Lists) sont l'outil de référence :
sudo setfacl -R -m g:www-perdu.com:rwX /var/www/perdu.com
sudo setfacl -R -d -m g:www-perdu.com:rwX /var/www/perdu.com
La première ligne applique le droit, la seconde le rend par défaut : tout nouveau fichier ou dossier créé dedans héritera automatiquement de ces droits, peu importe l'umask. Sur Debian/Ubuntu, les ACL sont déjà activées par défaut sur les systèmes de fichiers modernes ; sur d'autres distributions, vous pourriez devoir installer le paquet acl.
Vérifier les ACL en place :
getfacl /var/www/perdu.com
Étape 6 — Le cas particulier d'Apache
Sur Debian/Ubuntu, Apache fonctionne sous l'utilisateur www-data ; sur Fedora/RHEL et openSUSE, il s'agit de apache. Vérifiez le bon nom sur votre système :
ps aux | grep -E 'apache|httpd' | grep -v grep
Avec les permissions définies plus haut, Apache peut lire tous les fichiers du site (le droit r-x accordé aux autres suffit). C'est ce qu'on veut dans 90 % des cas : Apache sert le contenu sans pouvoir le modifier, ce qui limite considérablement les dégâts d'une éventuelle faille.
Quand Apache a besoin d'écrire
Certaines applications web ont besoin qu'Apache puisse écrire dans des dossiers précis : envoi de fichiers via un formulaire, cache, sessions, génération de miniatures… Le piège, c'est de répondre à ce besoin en ouvrant l'écriture partout, ce qui rend possible le téléversement d'un script malveillant qui sera ensuite exécuté.
Ne donnez l'écriture à Apache que sur les dossiers strictement nécessaires. Exemple pour un dossier uploads :
sudo mkdir -p /var/www/perdu.com/www/uploads
sudo chown www-data:www-perdu.com /var/www/perdu.com/www/uploads
sudo chmod 2775 /var/www/perdu.com/www/uploads
Sur Fedora/RHEL, remplacez www-data par apache.
Variante avec ACL, sans changer le propriétaire :
sudo setfacl -R -m u:www-data:rwX /var/www/perdu.com/www/uploads
sudo setfacl -R -d -m u:www-data:rwX /var/www/perdu.com/www/uploads
C'est souvent plus propre : le propriétaire principal reste root, et on ajoute juste un droit ciblé pour Apache. Pas d'ambiguïté sur « à qui appartient ce dossier ».
Empêcher l'exécution dans les dossiers d'upload
Un dossier où Apache peut écrire et où il peut exécuter du PHP est une cible classique. Désactivez explicitement l'exécution de scripts dans uploads/ via la configuration Apache du site :
<Directory /var/www/perdu.com/www/uploads>
php_admin_flag engine off
<FilesMatch "\.(php|phtml|phar|cgi|pl|py|sh)$">
Require all denied
</FilesMatch>
</Directory>
Étape 7 — Cas particulier de SELinux (Fedora, RHEL, AlmaLinux…)
Sur les distributions qui activent SELinux par défaut, des permissions Unix correctes ne suffisent pas : il faut aussi que les fichiers portent le bon contexte de sécurité. Si Apache renvoie des erreurs 403 alors que ls -l semble correct, c'est presque toujours SELinux.
Pour un dossier de contenu en lecture seule par Apache :
sudo semanage fcontext -a -t httpd_sys_content_t "/var/www/perdu.com(/.*)?"
sudo restorecon -Rv /var/www/perdu.com
Pour un dossier où Apache doit pouvoir écrire (comme uploads) :
sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/perdu.com/www/uploads(/.*)?"
sudo restorecon -Rv /var/www/perdu.com/www/uploads
La commande semanage enregistre la règle de manière persistante (elle survit aux mises à jour), et restorecon l'applique aux fichiers existants. Sur Debian/Ubuntu, ces commandes ne sont pas nécessaires (SELinux n'y est pas activé par défaut, AppArmor joue un rôle équivalent mais ne demande généralement pas de configuration spécifique pour Apache).
Vérification finale
Pour vérifier que tout est correct, listez les permissions :
ls -ld /var/www/perdu.com
ls -l /var/www/perdu.com/www
Vous devriez voir quelque chose comme :
drwxrwsr-x 3 root www-perdu.com 4096 Mar 12 14:00 /var/www/perdu.com
drwxrwsr-x 2 root www-perdu.com 4096 Mar 12 14:00 /var/www/perdu.com/www
Notez le s dans rws à la place du x du groupe : c'est la signature visuelle du bit SGID. C'est le signe que la configuration héritera correctement.
Créez un fichier de test en tant que chloe pour valider :
su - chloe
cd /var/www/perdu.com/www
echo "<h1>Bienvenue</h1>" > index.html
ls -l index.html
Le fichier index.html doit appartenir à chloe:www-perdu.com et être en -rw-rw-r-- (mode 664). Si c'est le cas, vous êtes prêt à configurer le VirtualHost Apache pointant vers /var/www/perdu.com/www.
En résumé
La recette complète, condensée :
# 1. Créer le groupe et y ajouter les mainteneurs
sudo groupadd www-perdu.com
sudo usermod -aG www-perdu.com chloe
# 2. Créer l'arborescence
sudo mkdir -p /var/www/perdu.com/www
# 3. Attribuer propriété et permissions avec SGID
sudo chgrp -R www-perdu.com /var/www/perdu.com
sudo find /var/www/perdu.com -type d -exec chmod 2775 {} \;
sudo find /var/www/perdu.com -type f -exec chmod 664 {} \;
# 4. (Optionnel mais recommandé) Garantir l'héritage avec des ACL
sudo setfacl -R -d -m g:www-perdu.com:rwX /var/www/perdu.com
# 5. Donner l'écriture à Apache UNIQUEMENT là où c'est nécessaire
sudo setfacl -R -m u:www-data:rwX /var/www/perdu.com/www/uploads
sudo setfacl -R -d -m u:www-data:rwX /var/www/perdu.com/www/uploads
# 6. Sur les systèmes SELinux, ajuster les contextes
sudo semanage fcontext -a -t httpd_sys_content_t "/var/www/perdu.com(/.*)?"
sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/perdu.com/www/uploads(/.*)?"
sudo restorecon -Rv /var/www/perdu.com
Le principe directeur à retenir : un groupe par site, l'écriture pour les mainteneurs, la lecture pour Apache, et l'écriture pour Apache uniquement là où l'application en a strictement besoin. C'est la base d'un hébergement multi-sites propre, durable et raisonnablement sûr.