Chapitre 4.1 — Prérequis et choix d’environnement
Avant d’installer quoi que ce soit, il faut comprendre ce que l’on installe. Moodle n’est pas une application web « moderne » au sens où vous l’entendez en tant que développeur Next.js : pas de serveur Node, pas de build obligatoire pour démarrer, pas de npm run dev magique. C’est une application PHP monolithique, mature (plus de vingt ans d’histoire), avec ses propres conventions, ses propres exigences d’infrastructure, et — depuis Moodle 5.1 — une restructuration majeure de son arborescence qui change la donne pour la configuration du serveur web.
Ce chapitre pose toutes les fondations : ce qu’est concrètement une « instance Moodle », les prérequis matériels et logiciels de Moodle 5.2 (sortie le 20 avril 2026), le choix de la base de données, le choix du serveur web, et surtout le choix de votre environnement de développement sous Windows 11. À la fin de ce chapitre, vous saurez exactement quoi installer et pourquoi — l’installation elle-même fera l’objet du chapitre suivant.
Sommaire du chapitre
- Vue d’ensemble : anatomie d’une instance Moodle
- Prérequis matériels : dev, petite prod, grosse prod
- Prérequis logiciels : PHP 8.3/8.4, extensions, php.ini
- Choix de la base de données
- Serveur web : Apache ou Nginx
- Architecture des environnements : où vit chaque brique
- Choisir son environnement de développement
- Considérations spécifiques à Windows 11
- Checklist finale de préparation
1. Vue d’ensemble : anatomie d’une instance Moodle
Quand on parle d’« une instance Moodle » (un « site Moodle »), on ne parle pas d’un simple dossier de code. Une instance Moodle fonctionnelle est l’assemblage de cinq briques distinctes, chacune avec son cycle de vie propre, ses exigences de sauvegarde propres, et son emplacement propre sur le disque ou le réseau. Comprendre cette séparation dès maintenant vous évitera 80 % des erreurs classiques de débutant (moodledata dans le webroot, cron jamais configuré, caches incompris…).
1.1 Brique n°1 : le code PHP (le dépôt)
C’est le contenu du dépôt Git officiel (git://git.moodle.org/moodle.git, miroir GitHub moodle/moodle). Il contient le cœur de Moodle et tous les plugins standards. Point capital : ce code est en lecture seule à l’exécution, à une exception près, le fichier config.php que l’installateur génère à la racine. Moodle n’écrit jamais dans son propre code — tout ce qui est dynamique va dans moodledata ou en base. C’est ce qui rend les montées de version relativement propres : on remplace le code, on garde les données.
Depuis Moodle 5.1, l’arborescence du dépôt a été profondément restructurée : tout le code accessible par le web a été déplacé dans un sous-dossier public/. Concrètement :
config.phpreste à la racine du projet (hors du webroot, donc), aux côtés depublic/,vendor/,node_modules/, etc. ;- une nouvelle variable en lecture seule,
$CFG->root, pointe vers la racine du projet ; $CFG->dirroot, qui historiquement pointait vers la racine, pointe désormais verspublic/;- le DocumentRoot du serveur web doit pointer vers
/chemin/vers/moodle/public, et non plus vers la racine du dépôt ; - en revanche,
$CFG->wwwroot(l’URL publique du site) ne doit PAS se terminer par/public: le sous-dossier est un détail d’implémentation côté serveur, invisible dans les URL.
La motivation est purement sécuritaire : avant 5.1, vendor/, node_modules/, les fichiers de build et config.php lui-même vivaient dans le webroot, et seule la configuration du serveur (ou la chance) empêchait de les servir. Désormais, tout ce qui n’a pas vocation à être servi par HTTP est physiquement hors de portée du serveur web.
💡 Pour un dev React : c’est exactement la logique du dossier
public/de Next.js ou de Vite, mais inversée dans les proportions. Dans Next.js,public/contient quelques assets statiques et tout le reste est compilé ; dans Moodle 5.1+,public/contient toute l’application exécutable par le web (les scripts PHP sont à la fois le « code source » et les « endpoints »), tandis que la racine garde la configuration, les dépendances Composer (vendor/≈node_modules/côté PHP) et l’outillage. Le principe commun : le serveur ne doit jamais pouvoir servir un fichier qui n’a pas été explicitement placé dans le webroot.
⚠️ Piège : énormément de tutoriels, de snippets de configuration Apache/Nginx et de réponses StackOverflow antérieurs à 2025 font pointer le DocumentRoot vers la racine du dépôt Moodle. Avec Moodle 5.1+, cette configuration affiche une erreur ou une page blanche. Vérifiez systématiquement la date des ressources que vous consultez, et retenez la règle : DocumentRoot →
public/, maiswwwrootsans/public.
1.2 Brique n°2 : moodledata (le répertoire de données)
moodledata est un répertoire que vous créez, où Moodle stocke tout ce qui est écrit à l’exécution :
- les fichiers uploadés par les utilisateurs (devoirs rendus, ressources de cours, avatars…), stockés dans une arborescence adressée par hachage SHA1 du contenu (
filedir/ab/cd/abcd1234...) — un système de déduplication par contenu, pas une arborescence lisible par un humain ; - les caches fichiers (
cache/,localcache/) ; - les sessions PHP (si stockées sur fichier, ce qui est le défaut) ;
- les fichiers temporaires (
temp/), les traces (trashdir/), les données de langue téléchargées (lang/), etc.
Deux règles absolues, non négociables :
- moodledata doit être HORS du webroot. Si un visiteur peut télécharger
https://votresite/moodledata/..., c’est une faille de sécurité majeure : Moodle contrôle l’accès aux fichiers via un script PHP (pluginfile.php) qui vérifie les permissions, jamais par accès direct. L’installateur refuse d’ailleurs de continuer si moodledata est détecté comme accessible par le web. - Le serveur web doit pouvoir y écrire. C’est le seul endroit (avec la base) où Moodle écrit.
En développement, un moodledata à côté du dépôt (mais jamais dedans) fait l’affaire. En production répartie sur plusieurs frontaux, moodledata doit être un stockage partagé (NFS, GlusterFS, ou un montage objet) puisque tous les nœuds doivent voir les mêmes fichiers.
💡 Pour un dev React : pensez à moodledata comme à la combinaison d’un bucket S3 (les uploads, le
filedir/adressé par hash — c’est conceptuellement identique à un content-addressable store) et du dossier.next/cache(caches et fichiers temporaires régénérables). Comme pour S3, on le sauvegarde ; comme pour.next/cache, une partie peut être purgée sans perte de données réelles. Et comme vous ne commiteriez jamais un bucket S3 dans votre repo, moodledata ne vit jamais dans le dépôt de code.
1.3 Brique n°3 : la base de données
Toute la donnée structurée vit en base relationnelle : utilisateurs, cours, inscriptions, notes, tentatives de quiz, logs, configuration (la table mdl_config reflète et complète config.php)… Moodle 5.2 supporte PostgreSQL, MySQL, MariaDB, Microsoft SQL Server et Aurora MySQL — nous détaillerons le choix en section 4. Retenez à ce stade que la base et moodledata sont indissociables : les métadonnées des fichiers (nom, contexte, permissions) sont en base, les octets sont dans moodledata. Sauvegarder l’un sans l’autre produit une restauration incohérente.
Toutes les tables partagent un préfixe (par défaut mdl_), ce qui permet en théorie de faire cohabiter plusieurs applications dans une même base — en pratique, donnez toujours à Moodle sa base dédiée.
1.4 Brique n°4 : les caches (MUC — Moodle Universal Cache)
Moodle est intensif en requêtes : afficher une seule page de cours peut impliquer des centaines de lectures de configuration, de chaînes de langue, de définitions de plugins. Le MUC (Moodle Universal Cache) est la couche d’abstraction de cache qui rend cela viable. Il distingue trois portées :
- le cache application : partagé entre tous les utilisateurs (ex. : liste des plugins installés, chaînes de langue, configuration des cours) — c’est le plus gros volume ;
- le cache session : propre à une session utilisateur (ex. : navigation calculée) ;
- le cache request : durée de vie d’une seule requête HTTP, en mémoire PHP.
Chaque portée peut être branchée sur différents backends (« stores ») : fichiers (le défaut, dans moodledata), Redis (fortement recommandé dès qu’on dépasse le poste de dev, et indispensable en multi-frontaux), Memcached, ou APCu. Le mapping portée → backend se configure dans l’administration (ou config.php), et c’est l’un des leviers de performance les plus rentables de Moodle.
💡 Pour un dev React : le MUC joue le rôle combiné du cache de données de Next.js (
unstable_cache/ fetch cache), d’un Redis applicatif et du memo par requête (Reactcache()). La portée « request » est l’analogue direct deReact.cache(): mémoïsation le temps d’un rendu. La portée « application » est votre Redis partagé. La différence culturelle : dans Moodle, tout cela est unifié derrière une seule API et configurable par l’admin sans toucher au code.
1.5 Brique n°5 : le cron (les tâches planifiées)
Moodle repose massivement sur des traitements asynchrones : envoi des notifications et des e-mails, finalisation automatique des tentatives de quiz, sauvegardes programmées, nettoyage des sessions, indexation de la recherche, synchronisation des inscriptions, exécution des tâches ad hoc (file de jobs ponctuels)… Tout cela passe par le script admin/cli/cron.php, qu’il faut exécuter au moins toutes les minutes via le planificateur du système (crontab sous Linux, tâche planifiée sous Windows, service dédié en Docker).
Un Moodle sans cron semble fonctionner : les pages s’affichent, on peut créer des cours. Puis on s’étonne que personne ne reçoive d’e-mail, que les inscriptions par cohorte ne se propagent pas, que les quiz « en cours » ne se ferment jamais. Le cron n’est pas optionnel : c’est un composant de premier rang de l’architecture.
# Linux/WSL2 : entrée crontab typique (exécution chaque minute)
* * * * * /usr/bin/php /var/www/moodle/public/admin/cli/cron.php >/dev/null💡 Pour un dev React : le cron Moodle, c’est vos jobs/queues — l’équivalent d’un worker BullMQ, des crons Vercel et d’Inngest réunis. Les « tâches planifiées » (scheduled tasks) sont des crons récurrents déclarés par chaque plugin avec leur propre planning (modifiable par l’admin) ; les « tâches ad hoc » sont une file de jobs à la BullMQ, persistée en base. Le script
cron.phplancé chaque minute est le worker qui dépile tout ça. Oublier le cron, c’est déployer une app Next.js en oubliant de démarrer le worker de queue.
1.6 Schéma d’ensemble
Navigateur (Chrome, Firefox, Safari, Edge...)
|
| HTTPS
v
+---------------------------------+
| Serveur web (Apache / Nginx) |
| DocumentRoot = moodle/public |
+----------------+----------------+
|
| mod_php ou PHP-FPM
v
+---------------------------------------------------------------------+
| PHP 8.3 / 8.4 (64 bits) |
| |
| /chemin/vers/moodle/ <- $CFG->root (racine projet) |
| ├── config.php <- config, HORS webroot |
| ├── public/ <- $CFG->dirroot (webroot) |
| │ ├── index.php, course/, mod/, lib/, admin/... |
| ├── vendor/ <- dépendances Composer |
| └── node_modules/ <- outillage front (build AMD) |
+---------+----------------------+----------------------+------------+
| | |
v v v
+------------------+ +------------------+ +---------------------+
| Base de données | | moodledata/ | | Caches (MUC) |
| PostgreSQL 16+ | | filedir/ (SHA1) | | application |
| MySQL 8.4+ ... | | cache/, temp/, | | session |
| tables mdl_* | | sessions/ | | request |
| | | HORS webroot ! | | (file/Redis/APCu) |
+------------------+ +------------------+ +---------------------+
^ ^
| |
+---------+----------------------+---------+
| Cron : php admin/cli/cron.php |
| (chaque minute — indispensable) |
| tâches planifiées + tâches ad hoc |
+-------------------------------------------+1.7 Tableau de correspondance pour un développeur JavaScript
| Brique Moodle | Analogue dans l’écosystème Node/Next.js | À sauvegarder ? |
|---|---|---|
| Code PHP (dépôt) | Le repo Next.js + node_modules | Non (re-clonable), sauf config.php |
config.php | .env + next.config.js | Oui |
| moodledata | Bucket S3 + .next/cache + store de sessions | Oui (filedir surtout) |
| Base de données | PostgreSQL derrière Prisma/Drizzle | Oui, de façon cohérente avec moodledata |
| MUC | Redis + React.cache() + fetch cache | Non (régénérable) |
| Cron | Workers BullMQ / crons Vercel / Inngest | N/A (mais à superviser) |
Côté navigateur, aucun prérequis exotique : Moodle 5.2 fonctionne sur tout navigateur moderne conforme aux standards, et l’équipe Moodle HQ teste régulièrement sur Chrome, Firefox, Safari et Edge, ainsi que sur MobileSafari et Chrome mobile. Si vous développez déjà pour ces cibles en React, rien de nouveau sous le soleil.
📚 Aller plus loin : la page « Server requirements » de la documentation admin (docs.moodle.org/en/Installing_Moodle ) et les notes de version de Moodle 5.2 (moodledev.io/general/releases ) sont les références canoniques. Pour la restructuration
public/, voir l’annonce des changements dans les notes de développement 5.1 sur moodledev.io .
2. Prérequis matériels : dev, petite prod, grosse prod
Moodle est raisonnablement frugal pour un poste de développement et raisonnablement gourmand en production. La variable qui domine tout le dimensionnement n’est pas le nombre d’utilisateurs inscrits, mais le nombre d’utilisateurs simultanément actifs — et, pire, simultanément actifs sur des opérations coûteuses (un quiz chronométré passé par 200 étudiants à 14h00 pile est le scénario de charge canonique de Moodle).
2.1 Poste de développement
Pour développer confortablement sous Windows 11 avec Docker Desktop et WSL2 :
- RAM : 16 Go minimum, 32 Go confortable. Comptez : Windows 11 (~4 Go), WSL2/Docker (~4-8 Go alloués), VS Code + navigateur avec vos 40 onglets (~4 Go), et les conteneurs Moodle eux-mêmes (webserver + PostgreSQL + éventuellement Selenium/Behat, ~2-4 Go). Avec 8 Go, vous passerez votre temps à jongler.
- CPU : 4 cœurs minimum. Les suites de tests PHPUnit/Behat sont parallélisables et apprécient les cœurs.
- Disque : SSD NVMe obligatoire en pratique, 30 à 50 Go libres. Un checkout Moodle fait ~1,5 Go avec l’historique Git, chaque instance a son moodledata, chaque base de test PostgreSQL prend son espace, et les images Docker s’accumulent vite. Le facteur critique n’est pas la capacité mais les IOPS : Moodle, ce sont des dizaines de milliers de petits fichiers PHP — un disque mécanique ou un filesystem lent (on y reviendra avec
/mnt/c, section 8) rend l’expérience insupportable.
2.2 Petite production (jusqu’à ~1 000 utilisateurs inscrits, ~50 simultanés)
Un seul serveur (VPS ou VM) héberge tout : web, PHP, base, moodledata.
- RAM : 8 Go (4 Go strict minimum si la base est ailleurs).
- CPU : 2 à 4 vCPU.
- Disque : 50 Go+ SSD, en gardant à l’esprit que moodledata grossit avec chaque devoir rendu et chaque sauvegarde de cours. Prévoyez la surveillance de l’espace disque dès le premier jour : un moodledata plein est la panne la plus bête et la plus fréquente des petites installations.
2.3 Grosse production (établissement, université, milliers de simultanés)
L’architecture change de nature : plusieurs frontaux web derrière un répartiteur de charge, une base dédiée (souvent avec réplication), moodledata sur stockage partagé, Redis pour les sessions et le cache MUC, et un ou plusieurs nœuds dédiés au cron. Le dimensionnement se fait par tests de charge (l’outil JMeter est traditionnel dans la communauté Moodle), pas par règle de trois. Ordres de grandeur constatés : 4 à 8 frontaux de 8-16 Go, une base de 32-64 Go de RAM, et un Redis dimensionné pour tenir l’ensemble du cache application en mémoire.
2.4 La règle empirique de concurrence
La règle historique de la documentation Moodle reste un bon point de départ :
Environ 1 Go de RAM pour 10 à 20 utilisateurs simultanés, et un ratio typique de 1 utilisateur simultané pour 20 à 50 utilisateurs inscrits en usage scolaire classique.
Autrement dit, un site de 2 000 inscrits verra rarement plus de 100 utilisateurs réellement simultanés en régime normal — mais un examen en ligne peut faire monter ce chiffre à 500 d’un coup. Dimensionnez pour vos pics prévisibles (sessions d’examens, rentrées), pas pour la moyenne.
⚠️ Piège : « utilisateur simultané » au sens Moodle signifie « a cliqué dans les 5 dernières minutes », pas « a une session ouverte ». Les statistiques de sessions ouvertes surestiment la concurrence réelle d’un facteur 5 à 10. Inversement, un quiz auto-enregistré toutes les 30 secondes transforme chaque étudiant en utilisateur hautement simultané. Le type d’activité compte autant que le nombre de têtes.
💡 Pour un dev React : contrairement à une app Next.js déployée sur Vercel où le scaling horizontal est « gratuit » (serverless), Moodle est une application stateful classique : sessions, cache local, verrous de cron. Le scaling horizontal se prépare (sessions dans Redis, moodledata partagé, sticky sessions ou non) — c’est l’équivalent de faire tourner une app Express d’ancienne génération sur plusieurs instances. Rien d’insurmontable, mais rien d’automatique.