Setting up Moodle on NGINX with Pretty URLs
How to Add Pretty URLs for Moodle Pages
Tutorial: Setting Up Pretty URLs for Moodle on NGINX
This guide explains how to configure NGINX so that your Moodle pages are accessible through clean, readable URLs such as:
https://SAMPLEDOMAIN.com/about
https://SAMPLEDOMAIN.com/contact
https://SAMPLEDOMAIN.com/licensesinstead of the default Moodle structure:
https://SAMPLEDOMAIN.com/local/page/?id=3
https://SAMPLEDOMAIN.com/local/page/?id=4
https://SAMPLEDOMAIN.com/local/page/?id=21. Open Your NGINX Configuration
Edit your NGINX server block for your site (usually located in /etc/nginx/sites-available/SAMPLEDOMAIN.com):
sudo nano /etc/nginx/sites-available/SAMPLEDOMAIN.com2. Add Rewrites for Pretty URLs
Inside your main server { ... } block, locate or create a section for your Moodle site.
Add the following block:
# --- Pretty URLs for Moodle custom pages ---
location / {
# Rewrite clean URLs to Moodle internal page IDs
rewrite ^/licenses$ /local/page/?id=2 last;
rewrite ^/about$ /local/page/?id=3 last;
rewrite ^/contact$ /local/page/?id=4 last;
rewrite ^/faq$ /local/page/?id=5 last;
# Handle Moodle PHP files like /plugin/file.php/...
rewrite ^/(.*\.php)(/)(.*)$ /$1?file=/$3 last;
# Fallback to index.php for everything else
try_files $uri $uri/ /index.php?$args;
}✅ What this does
Each line tells NGINX to:
Match a friendly URL (e.g.,
/about)Redirect internally to the correct Moodle page (e.g.,
/local/page/?id=3)Keep the clean URL visible in the browser
3. How to Add a New Pretty URL
Let’s say you created a new Moodle page with ID 6 and want it to be available at
https://SAMPLEDOMAIN.com/support.
Just add this line inside the same block:
rewrite ^/support$ /local/page/?id=6 last;Now /support will display Moodle’s page ID 6.
4. How to Rename or Change a URL
If you want to rename /faq to /help, just replace:
rewrite ^/faq$ /local/page/?id=5 last;with:
rewrite ^/help$ /local/page/?id=5 last;5. Full Example Configuration
Here’s a complete working example, ready to use:
server {
listen 80;
listen [::]:80;
listen 443 ssl http2;
listen [::]:443 ssl http2;
{{ssl_certificate_key}}
{{ssl_certificate}}
server_name SAMPLEDOMAIN.com;
{{root}}
{{nginx_access_log}}
{{nginx_error_log}}
# Allow access to ACME challenge for SSL certificates
location ~ /.well-known {
auth_basic off;
allow all;
}
{{settings}}
# --- Pretty URLs for Moodle custom pages ---
location / {
# Rewrite clean URLs to Moodle internal page IDs
rewrite ^/licenses$ /local/page/?id=2 last;
rewrite ^/about$ /local/page/?id=3 last;
rewrite ^/contact$ /local/page/?id=4 last;
rewrite ^/faq$ /local/page/?id=5 last;
rewrite ^/support$ /local/page/?id=6 last;
# Handle plugin PHP files like /plugin/file.php/...
rewrite ^/(.*\.php)(/)(.*)$ /$1?file=/$3 last;
# Fallback for all other requests
try_files $uri $uri/ /index.php?$args;
}
# --- Moodle & PHP rewrites ---
rewrite ^/(.*\.php)(/)(.*)$ /$1?file=/$3 last;
try_files $uri $uri/ /index.php?$args;
index index.php index.html;
# --- PHP processing ---
location ~ \.php$ {
include fastcgi_params;
fastcgi_intercept_errors on;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
try_files $uri =404;
fastcgi_read_timeout 3600;
fastcgi_send_timeout 3600;
fastcgi_param HTTPS $fastcgi_https;
fastcgi_pass 127.0.0.1:{{php_fpm_port}};
fastcgi_param PHP_VALUE "{{php_settings}}";
}
# --- Static files ---
location ~* ^.+\.(css|js|jpg|jpeg|gif|png|ico|gz|svg|svgz|ttf|otf|woff|woff2|eot|mp4|ogg|ogv|webm|webp|zip|swf)$ {
add_header Access-Control-Allow-Origin "*";
expires max;
access_log off;
}
# Stop processing if file exists
if (-f $request_filename) {
break;
}
}✅ Result:
Any slug at the root level (
/licenses,/about, etc.) automatically maps to your PHP page controller.No hardcoding of
id=Xrequired.Works with an unlimited number of pages.
Last updated