Configuring the Router
This page is intended to help systems administrators to correctly configure the Routing Engine.
Moodle consists of thousands of web pages linked together with hyperlinks. Because HTML is a static markup language rather than a programming language, it cannot dynamically handle variables or links on its own.
PHP is the server-side programming language that powers Moodle. While PHP uses data variables internally, traditional PHP relies on messy "query strings" (like ?id=123) appended to the end of web links to pass information between pages.
This is where a router comes in. A router is a software feature that serves as a centralized traffic controller for Moodle's web requests. Instead of hardcoding rigid, direct paths to thousands of individual PHP files, all hyperlinks are directed through this central router. If a developer changes a webpage's filename or location, they only need to update a single "route" rule in the router script, rather than hunting through thousands of code files to fix broken links. This centralized control drastically improves programming productivity and quality, while also providing clean, human-readable URLs.
Although the routing architecture has been progressively introduced over several Moodle versions, formal environment checks and configuration warnings were explicitly introduced in Moodle 5.2. While a functioning router setup is not strictly forced to complete a basic installation in Moodle 5.2, Moodle HQ intends to make a fully working router mandatory in upcoming stable releases. Configuring it early ensures long-term site stability and seamless future upgrades.
While Moodle includes the router code by default, the router relies entirely on rewrite and routing features built into your underlying web server. It isn't part of the Moodle code.
Some web servers have these features enabled by default, while others do not. Because every server environment is unique, you must take different technical steps depending on whether you are running Apache, Nginx, or another platform. No single, one-size-fits-all solution works for everyone.
However, because Moodle cannot automatically configure your server hardware, you are ultimately responsible for ensuring that your server’s router environment is properly configured and functioning. Consider following these steps.
Step 1: Verify the Router Files are Present
Moodle introduced the core routing architecture in Moodle 5.1 and fully stabilized it in Moodle 5.2.0. If you are running Moodle 5.2 or later, the necessary framework is already included in your codebase.
To confirm that the router endpoints are physically present on your system, look inside your main Moodle directory. You should see a public/ subdirectory with two vital files:
- index.php - Serves your standard assets and entry points
- r.php - The main engine that intercepts and routes virtual URL paths
Step 2: Test Moodle’s Router
Understanding the Environment Warning
If you navigate to Site Administration > Server > Environment, you may see a notification in the Other Checks section that reads Router not configured.
Unlike other environment tests (like database or PHP version checks), Moodle cannot actively probe your web server to see if the router works. This notification is a static status message, not a real-time error tracker. While you can suppress the warning by adding $CFG->routerconfigured = true; to your config.php file, doing so only hides the alert—it does not actually configure your server.
How to Test Your Router
Before editing any server code, run any of these simple tests to confirm that your router is working correctly:
Test A: The 404 Behavior Test
Type a non-existent path into your browser, such as https://yourmoodle.com/fakefile.php (or https://yourdomain.com/moodle/fakefile.php if your Moodle is in a folder.)
- Router IS NOT working: You will see a generic, blank, or server-default "404 Not Found" page (often plain black-and-white text).
- Router IS working: You will see a styled Moodle "Not Found" error screen that matches your site's current graphic theme.
Test B: The Deep-Link Test
Log in to your site, navigate to any active course, and note its unique course ID (e.g., 19). Then, enter the following routed URL directly in your address bar: https://yourmoodle.com/course/19/manage (or https://yourdomain.com/moodle/course/19/manage if your Moodle is in a folder.)
- Router IS NOT working: The browser displays a generic server "Not Found" page.
- Router IS working: The browser successfully renders your Moodle "Course Administration" page. This successfully demonstrates exactly how the router is intended to process and deliver pages.
Test C: The System Status Report Test
Navigate to Site administration > Reports > System status in your browser.
If the $CFG->routerconfigured = true; setting (flag) is missing from your config.php file, or if the router is not set up, Moodle displays a Router Configuration Error stating, "The router is not correctly configured."
Clicking the Router Configuration link opens a detailed status page. The information displayed depends on your settings:
- Missing config.php flag: No additional information is displayed.
- Flag enabled, but router misconfigured: The page displays specific troubleshooting Errors.
- Flag enabled and router configured correctly: The page displays a list of OKs.
Test D: The Command Line Test
If you prefer using the command line, you can check this same status information by running the administrative CLI script:
php admin/cli/checks.php
Keep these tests handy! If your site fails them now, you will run the same tests to verify your setup after completing the server configurations in the next steps.
Step 3: Configure the web server
Moodle runs on a wide range of hosting environments, so server configurations vary widely. The examples below are general guidelines and may need adjustment to fit your specific system. Major differences exist not only between software platforms like Apache, Nginx, and IIS but also between management tools like cPanel and Plesk. Because no single procedure applies to every environment, configuring the server's routing rules can be challenging and requires careful attention to your unique setup.
Configuring Apache (Apache2)
Method A: Via the Main Server Virtual Host File (httpd.conf or apache2.conf)
This method is ideal for administrators who manage their own Virtual Private Server (VPS) or a dedicated root server with direct, unrestricted access to the core configuration files.
Configuring the router at the server level requires root access. Instead of using a local file, you will instruct Apache to support the Moodle Router by specifying the global directive FallbackResource in your site's directory configuration block.
# Set the server's front door directly to Moodle's public folder
DocumentRoot /var/www/moodle/public
<Directory /var/www/moodle/public>
AllowOverride None
Require all granted
DirectoryIndex index.php
FallbackResource /r.php
</Directory>
Handling Subdirectories
The FallbackResource path is relative to your specified DocumentRoot. If you are running Moodle out of a subdirectory rather than a root domain (for example: https://yourdomain.com), your configuration must adjust the fallback path to match that subfolder:
# Example configuration for a Moodle subdirectory installation
DocumentRoot /var/www/html
<Directory /var/www/html/moodle/public>
AllowOverride None
Require all granted
DirectoryIndex index.php
FallbackResource /moodle/public/r.php
</Directory>
- DirectoryIndex index.php: This line must be placed directly above the fallback directive to prevent unnecessary HTTP 404 errors from disrupting the Moodle Router.
- Require all granted: This allows standard web traffic to have unconditional access to your public Moodle routing endpoints.
Method B: Via an .htaccess File
Using an .htaccess file is the best solution for shared hosting environments or servers managed through control panels like cPanel. This approach works only on Apache and doesn't require modifying global configuration files or changing the server's root directory. It also works if you have installed multiple Moodle sites using symlinks. It is often the easiest and most flexible way to deploy the router.
Many hosting providers (such as GoDaddy) bundle Linux with a control panel like cPanel. When a control panel is active, it manages the server layout, often renaming folders or burying core configurations deep within custom system subdirectories. Fortunately, an .htaccess solution lets you bypass global server files entirely. This approach also seamlessly supports running multiple isolated Moodle instances on a single server—you simply place a separate .htaccess file in each site's `/public` folder.
Creating the .htaccess File
Create a new file named `.htaccess` containing the rules below, and place it directly in your Moodle site's `public/` directory.
Note: Because this file begins with a period (.), Linux treats it as a hidden file. Some file management systems may hide it from you unless you tell them to “show hidden files.” Alternatively, some people will name it `htaccess.txt` while working with it, and then rename it to `.htaccess` once it is in the `moodle/public` folder.
# Name this file ".htaccess" and place it into the moodle/public subdirectory.
DirectoryIndex index.php
# Essential if your Moodle environment utilizes symlinks
Options +FollowSymLinks
# Safely disable open directory browsing
Options -Indexes
<IfModule mod_rewrite.c>
RewriteEngine On
# ==========================================
# 1. PATH SECURITY RESTRICTIONS
# ==========================================
RewriteRule "(\/vendor\/)" - [F]
RewriteRule "(\/node_modules\/)" - [F]
RewriteRule "(^|/)\.(?!well-known\/)" - [F]
RewriteRule "(composer\.json)" - [F]
RewriteRule "(\.lock)" - [F]
RewriteRule "(\/environment.xml)" - [F]
RewriteRule "(\/install.xml)" - [F]
RewriteRule "(\/README)" - [F]
RewriteRule "(\/readme)" - [F]
RewriteRule "(\/moodle_readme)" - [F]
RewriteRule "(\/upgrade\.txt)" - [F]
RewriteRule "(\/UPGRADING\.md)" - [F]
RewriteRule "(phpunit\.xml\.dist)" - [F]
RewriteRule "(\/tests\/behat\/)" - [F]
RewriteRule "(\/fixtures\/)" - [F]
RewriteRule "(\/upgrade\.txt|UPGRADING\.md|UPGRADING\-CURRENT\.md)" - [F]
# ==========================================
# 2. HARDCODED MOODLE ENVIRONMENT TEST ROUTES
# ==========================================
RewriteRule ^core/check/controller/test$ r.php [QSA,L]
RewriteRule ^api/rest/v2/openapi.json$ r.php [QSA,L]
RewriteRule ^lib/exampleshimroute2\.php$ r.php [QSA,L]
# ==========================================
# 3. CATCH-ALL ROUTING FALLBACK
# ==========================================
# If the requested file or directory does not exist physically on disk, route to r.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ r.php [QSA,L]
</IfModule>
This is a comprehensive, production-ready “.htaccess” configuration. While a shorter file can technically do the job, these extra rules add valuable layers of security and environment compliance without harming Moodle performance.
Standard router setups typically require a “FallbackResource” directive. However, using this `mod_rewrite` block removes the need for “FallbackResource”, giving you more flexibility because the script doesn't need to know your specific Moodle root folder name. The “mod_rewrite” module is enabled by default on almost all modern commercial web servers.
Local Environments: MAMP and Laragon
Local development environments should run Apache to utilize this .htaccess file solution. Because local testing sites typically aren't exposed to the public internet, your .htaccess file doesn't need to be as comprehensive as one on a production server. It also shows that .htaccess files can differ.
Create a simplified .htaccess file and place it in your local site's public/ directory with the following rules:
Options +FollowSymLinks
DirectoryIndex index.php
<IfModule mod_rewrite.c>
RewriteEngine On
# Let Apache serve real files or folders directly
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
# Catch everything else and force-route it to r.php
RewriteRule ^ r.php [L]
</IfModule>
Enforcing Server Overrides
To use this local file, ensure your server allows local overrides. By default, fresh installations of MAMP and Laragon block .htaccess files from making changes, meaning you must modify the main server httpd.conf configuration file.
For MAMP:
- Open your main Apache configuration file (typically located at /Applications/MAMP/conf/apache/httpd.conf).
- Search for the block of code matching <Directory "/Applications/MAMP/htdocs">.
- Look for the line reading AllowOverride None and change it to AllowOverride All.
- Continue scanning further down the file for a second identical block, and ensure its AllowOverride None line is also changed to AllowOverride All.
- While in this file, search for LoadModule rewrite_module modules/mod_rewrite.so. If it begins with a hash (#), remove it to uncomment and enable the module.
- Save the file and restart your MAMP server (Step 5).
For Laragon:
- Open the Apache configuration file (typically located within a path similar to C:/Laragon/bin/apache/httpd-[version]/conf/httpd.conf).
- Follow the exact same editing steps outlined for MAMP above, updating the AllowOverride directives to All and ensuring mod_rewrite is enabled.
- Save the file and restart your Laragon server (Step 5).
Enabling the mod_rewrite module lets you remove the strict FallbackResource requirement from your local directory settings, making your files more flexible because your code tree no longer needs to hardcode the name of your Moodle installation folder.
Configuring Nginx
Note: There is a documentation web page about Nginx that might be helpful.
Option 1: Standard Root Installation
If your Moodle site is installed directly on your main domain (e.g., `https://yourdomain.com`), add the following block to your Nginx configuration:
location / {
try_files $uri /r.php;
}
Option 2: Subdirectory Installation
If your Moodle installation is in a subfolder rather than the root domain (e.g., `https://yourdomain.com`), you must specify a path:
location /moodle/ {
try_files $uri $uri/ /moodle/r.php;
}
Option 3: Multiple Moodle Installations (Advanced)
If you are hosting multiple independent Moodle sites on a single server, you can use a case-sensitive regular expression to dynamically capture the site folder path:
location ~ ^/(?<sitepath>[^/]*)/ {
try_files $uri $uri/ /$sitepath/r.php;
}
- $uri: This is the exact file path requested by the browser. If a student requests a real file (such as a core stylesheet or JavaScript asset), Nginx serves it instantly.
- /r.php: If the request does not match a real file, Nginx falls back to this file, handing control to the Moodle routing engine.
Configuring IIS
Internet Information Services (IIS) is Microsoft's web server platform for Windows environments. Like Apache, IIS supports directory-level configuration via a local file named web.config.
'Note:' The following instructions are community-submitted and have not been tested by Moodle HQ. If you manage an IIS environment and can provide verified updates, please consider contributing them to this page.
To support the Moodle Router, your server must have Microsoft’s official URL Rewriter installed. Once the module is active, open or create a `web.config` file in your Moodle site's `public/` directory, then insert the following XML rewrite block:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Moodle Router" stopProcessing="true">
<match url="^(.*)$" ignoreCase="false" />
<conditions logicalGrouping="MatchAll">
<!-- If the requested path is a real file, serve it directly -->
<add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
</conditions>
<!-- Otherwise, forward the clean URL request directly to r.php -->
<action type="Rewrite" url="r.php" appendQueryString="true" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
- negate="true": This tells IIS to ignore the rewrite rule if a student requests a real file (such as a graphic icon or a core JavaScript file) that exists on the disk.
- appendQueryString="true": This ensures that any data parameters attached to a link are passed through the rewrite rule directly to Moodle's routing engine.
Step 4: Restart the Server (If Required)
Depending on your hosting environment, you may need to restart your web server to apply the new configuration rules.
- Local Development Environments: Platforms such as MAMP, XAMPP, or Laragon almost always require a manual server restart or reload to apply configuration updates.
- Production Servers & Control Panels: In many enterprise environments, virtual private servers (VPS), or control panels like cPanel, directory-level changes take effect immediately without requiring a full server reboot.
Step 5: Verify the Router Functionality
Now that your server configuration is updated and running, it is time to verify your work. Return to Step 2 and re-run Test A (The 404 Behavior Test) and Test B (The Deep-Link Test). If your browser displays the styled Moodle error page and the Course Administration page, your router is officially functioning.
Step 6: Clear the Environment Notification
Once you have verified that your router is working correctly, you can clear the static warning message in Moodle's environment check.
Open your main config.php file and scroll to the bottom of the script. Insert the following configuration line, typically just above the final “require_once” statement:
$CFG->routerconfigured = true;
require_once(__DIR__ . '/lib/setup.php');
This tells Moodle that you have successfully validated the environment, updating the status on your Site Administration > Server > Environment page.