Nginx Web Rules & Rewrites

Nginx Rewrites, Redirects and other Cloud Configs

This guide will discuss the basics of customizing Cloud configuration to achieve URL Rewriting, Redirects and a few other common configuration needs. Basic knowledge of URL Rewriting and Redirects is assumed.

MODX Cloud uses the high performance Nginx HTTP server rather than Apache and, therefore, things you'd normally do in an .htaccess file, you will do in your Cloud's Web Rules settings.

Editing Nginx Web Rules

  1. From the Clouds page of the MODX Cloud Dashboard, locate the Cloud you'd like to download the backup for, and click on its name from the list to manage it.

  2. Find and click on the Webserver Tab at the top of the Cloud edit screen and you should see the Web Rules / Rewrites section.

Two important things to keep in mind when adjusting web rules:

  • Be sure to leave the MODX rewrite rule at the end.
  • Because of the systems that run MODX Cloud, you may not modify the server block. If you need help with this, open a ticket from the MODX Cloud Dashboard with details.

Recommendations for Optimal Search Rank and Site Performance

The best practices for maximizing site performance and search engine ranking is covered in this section. For other examples, see below.

Canonical URLs

It is considered a best practice to have your website accessible and indexed by search engines only at a single URL. Use one and only one of the following methods shown in examples 1-3.

  1. www.mydomain.com -> mydomain.com

    Redirect any requests for www.mydomain.com to mydomain.com

    if ($host = "www.mydomain.com") {
        return 301 $scheme://mydomain.com$request_uri;
    }
    location / {
        try_files $uri $uri/ @modx-rewrite;
    }
    
  2. mydomain.com -> www.mydomain.com

    Redirect any requests for the host mydomain.com to www.mydomain.com

    if ($host = "mydomain.com") {
        return 301 $scheme://www.mydomain.com$request_uri;
    }
    location / {
        try_files $uri $uri/ @modx-rewrite;
    }
  3. multiple domains -> www.mydomain.com

    Redirect any requests for alternate domains to www.mydomain.com

    if ($host ~ "(alt1.com|alt2.net|alt3.co.uk)$") {
        return 301 $scheme://www.mydomain.com$request_uri;
    }
    location / {
        try_files $uri $uri/ @modx-rewrite;
    }
    
Be sure to include the $request_uri variable in your domain redirects or Let's Encrypt pre-check and renewals may not work as expected.

SSL Sites

Google, and possibly other search engines, now positively factor a site being served securely in search ranking as they’re considered more trustworthy. If possible, it is best to use SSL for your site.

  1. Force Requests to Use Secure HTTPS Connections

    If your site uses SSL, you should force all visitors to use https so they do not visit your site using an unsecured connection. All SSL connections in MODX Cloud leverage SPDY, so your site will load faster in modern browsers, and search engines are starting to rank SSL sites higher compared to the same site served on unencrypted connections.

    Be sure to put your correct domain where you see mydomain.com. If you're using a redirect to point to or away from www, be sure your intended domain matches that form.

    Caution: Forcing HTTP to HTTPS cannot be easily reversed. It's best not to implement this if there is a chance you will turn off SSL. If you do need to reverse this, you can set the max-age to -1 (HTTPS must still be enabled) and wait 30 days before removing your SSL certficate.

    # Tells the browser to always force SSL. 
    # Do not uncomment this line if there is a chance you will turn off SSL
    # add_header Strict-Transport-Security "max-age=31536000; includeSubdomains"; 
    
    if ($host != "www.mydomain.com") {
        return 301 https://www.mydomain.com$request_uri;
    }
    if ($scheme != "https") {
        return 301 https://$host$request_uri;
    }
    

    Omit the add_header line if you think there is a chance you will disable SSL in the future. It may result in visitors experiencing errors or unable to visit your site without clearing their browser cache.

Minimize Requests and Data Transfers

Website visitors and search engines love sites that perform better. A factor that can affect this rank is how assets like images, CSS and JS files are cached by visitors’ web browsers.

  1. Leverage Browser Caching

    During development, you may not want the following settings on for testing. Once a site goes live, however, the example below will increase your Page Speed score—you may wish to set a longer expires line like 14d for two weeks, or 30d for thirty days.

    location ~* \.(?:ico|css|js|jpe?g|png|gif|svg|pdf|mov|mp4|mp3|woff|woff2|otf|ttf)$ {
        expires 7d;
        add_header Pragma public;
        add_header Cache-Control "public";
        gzip_vary on;
    }
    location / {
        try_files $uri $uri/ @modx-rewrite;
    }
    

Security & Content Protection

  1. Control access to your Cloud 

    If you are working on a website or specific part of the website that you don't want your visitors to have access to, but to have your team have access from a specific IP address. Using this method also prevents people other than the specified IP addresses to have access to your MODX Revolution manager by changing the location block.

    #Block access to the entire website
    location / {
        allow 192.168.1.1/24;
        allow 127.0.0.1;
        deny all;
    }
    #Block access to manager
    location /manager/ {
        allow 192.168.1.1/24;
        allow 127.0.0.1;
        deny all;
    }
    		

    If you wish to block a particular IP from accessing your website.

    #Block access to the entire website for a single IP or range
    location / {
        deny 127.0.0.1;
        deny 192.168.1.1/24;
    }
    		

    Substitute real IPs or IP blocks for the ones above, or you may find yourself locked from the Manager.

     

  2. Force SSL for the Manager

    If you wish to encrypt the MODX Manager only, using the freely available Cloud testing URLs the following rule should work.

    set $redirect false; 
    if ($request_uri ~ ^/manager(\/)?$ ) { 
        set $redirect true; 
    } 
    if ($scheme = https) { 
        set $redirect false; 
    } 
    if ($redirect = true) { 
        return 301 https://cXXXX.paas1.xxx.modxcloud.com$request_uri; 
    }
    

    In the example above, you would replace the internal cloud URL in the last line with the specific MODX Cloud URL assigned to your instance when it is created.

  3. Prevent Access to a Directory and its Contents from the Web

    You can block access to a directory and all of its contents from the web, for example for an internal application.

    location ^~ /apps {
        deny all;
    }
    location / {
        try_files $uri $uri/ @modx-rewrite;
    }
    

    Note that the path specified in the location block is relative to the site root.

    Read more about allowing and denying access.

  4. Preventing Hotlinking Files from Other Sites
    1. Preventing Hotlinking Files globally except certain sites

      location ~ \.(woff|eot)$ {
          valid_referers mysite.com www.mysite.com c0xxx.paas1.tx.modxcloud.com;
          if ($invalid_referer) {
              return 403;
          }
          try_files $uri $uri/ =404;
      }
      location / {
          try_files $uri $uri/ @modx-rewrite;
      }
      
    2. Preventing Hotlinking Files from specific sites and showing specific page
      location / {
          try_files $uri $uri/ @modx-rewrite;
      
          # Referrer protection
          if ($http_referer ~* (www.)?domain.com) {
              return 301 https://www.domain.com/custompage;
          }
      }
      
      location /custompage {
          try_files $uri $uri/ @modx-rewrite;
      }
      
  5. Password Protect a Directory

    In the following example, you should replace c0xxx with the first part of the Cloud Address field visible from the Dashboard. You will also need to manually create a .htpasswd file referenced in the configuration. You can use a tool such as this one or this one to get you started.

    location /protectme/ {
        auth_basic "Restricted";
        auth_basic_user_file /c0xxx/home/.htpasswd;
        # if the protected location is modx, then ...
        try_files $uri $uri/ @modx-rewrite;
        # otherwise, if static files, you'd use
        # try_files $uri $uri/ =404;
    }
    location / {
        try_files $uri $uri/ @modx-rewrite;
    }
    
  6. Blocking Exchange Autodiscover Requests

    Office365 Email and Exchange can fill up your error logs with requests for an autodiscover.xml file. To block it add the following rule:

    location /autodiscover/autodiscover.xml {
        return 404;
    }
    
  7. Block PHP execution in a user-uploads directory

    Sometimes your users need to upload files, but you want to prevent any PHP uploaded from executing there using a 403 Forbidden error code (i.e., “The server understood the request, but is refusing to authorize it.”). For example, you might have a assets/uploads/ directory for this purpose:

    location ~ /assets/uploads/.*\.php$ {
        return 403;
    }

Other Configuration Examples

Custom Routing & Redirects

  1. Custom Routing (Rewrites)

    Say you have a resource that is to function as a controller for a set of URLs. (You would likely have a custom snippet and some custom data to go along with this.) So, for example, you want the URL http://mysite.com/listings/123 to be rewritten (not redirected) to http://mysite.com/listing.html?listingid=123

    #rewrite /listings/* requests to a Listings controller resource and pass part of the URL
    rewrite ^/listings/(.*)$ /listing.html?listing=$1 last;
    location / {
        try_files $uri $uri/ @modx-rewrite;
    }
    

    Note that technically the MODX friendly URLs rewrite causes another rewrite, and there could be multiple ways of achieving the same result. If this concerns you, it’s time to dig into the NGINX docs :) Just remember that we’re happy to help—support is just a couple of clicks away at the bottom right-hand side of your Dashboard.

  2. Redirect Old URL to New URL

    Say you still get lots of requests to a URL that no longer exists on your site, e.g. http://mysite.com/someoldarticle.html. Maybe it’s been moved or deleted…in any case, you want to set up a permanent (301) redirect from the old URL to a new URL.

    # redirect /someoldarticle.html to /some/newarticle.html
    rewrite ^/someoldarticle\.html /some/newarticle.html permanent;
    
    location / {
        try_files $uri $uri/ @modx-rewrite;
    }
    

    Any line starting with # is a comment, which is always good to use to make notes about what each ruleset does for future reference. Empty lines are ignored.

  3. Babel for MODX Revolution

    Using Babel with MODX Revolution in Cloud requires special rules in order for routing of the various languages to function correctly. We've prepared a fairly detailed explanation with examples at Github.

WordPress

  1. WordPress Installed in a Subfolder

    If you’ve installed WordPress in a subfolder alongside MODX, here’s how you can set up Friendly URLs for WordPress.

    # Replace all occurrences of [subfolder] with the folder where your WordPress install is located
    
    # The WordPress rewrite
    location /[subfolder] {
        try_files $uri $uri/ /[subfolder]/index.php?$args;
    }
    
    # The default MODX rewrite</h1>
    location / {
        try_files $uri $uri/ @modx-rewrite;
    }
    
  2. Basic Wordpress Friendly URLs

    If you run WordPress, substitute @wp-rewrite for @modx-rewrite in the "try files" line in the examples that follow like:

        location / {
           try_files $uri $uri/ @wp-rewrite;
        }
    

    To get permalink URLs cleaned up, please visit the WordPress Codex on Nginx and install the Nginx Helper Plugin as outlined there. It removes index.php from WordPress Permalinks, and you can use it to set up a "sample-post" option.

Other Examples

  1. Display the Contents of Directory

    location /somefiles/ {
        autoindex on;
        try_files $uri $uri/ =404;
        # note that in a custom location block, if we don't end it with
        # try_files $uri $uri/ @modx-rewrite;
        # then we are telling Nginx to serve the files directly, and not pass the requests to MODX to be interpreted as a Friendly URL
    }
    location / {
        try_files $uri $uri/ @modx-rewrite;
    }
    

    See http://wiki.nginx.org/HttpAutoindexModule for more about the autoindex directive.

  2. Directory-specific Control over Cache Headers

    The following example adds the cache headers for all requests to the /assets/ folder or deeper. You could also do custom cache times for specific file types: e.g. location ~* .gif would match requests to all .gif files (made case-insensitive by the *)

    location /assets {
        # this adds an Expires header and a Cache-Control header
        expires 7d;
    }
    location / {
        try_files $uri $uri/ @modx-rewrite;
    }
    
  3. Control IE rendering modes

    add_header X-UA-Compatible IE=edge,chrome=1;
    location / {
        try_files $uri $uri/ @modx-rewrite;
    }
    

    Read more about this topic at Stack Overflow.

  4. Robots.txt as a MODX Resource

    MODX Cloud has global rules which prevent robots.txt from being served as a resource by default. If you would like to manage robots.txt in your MODX CMS, add the following rule.
    location = /robots.txt {
    try_files $uri $uri/ @modx-rewrite;
    }
  5. Custom Error Pages

    nginx allows the creation of custom error pages to customize the look of 50x errors that need to be handled without PHP. 500 Error pages need to be coded as standard HTML without any server-side logic since the server will be unresponsive during processing. In the following example, we'll point 500 errors to a page called custom_500.html in the webroot.
    error_page 500 502 503 504 /custom_500.html;

 

Have more questions? Submit a request

0 Comments

Please sign in to leave a comment.