Nginx Rewrites, Redirects and other Cloud Configs
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
-
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.
-
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.
-
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; }
-
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; }
-
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; }
$request_uri
variable in your domain redirects or free SSL certificate 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.
-
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 fromwww
, 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 certificate. You may wish to start with the HSTSmax_age
setting to86400
(1 day in seconds) before changing it to31536000
(1 year in seconds) at some later time.# 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.
-
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 1y; add_header Pragma public; add_header Cache-Control "public"; gzip_vary on;
try_files $uri $uri/ @modx-rewrite; } location / { try_files $uri $uri/ @modx-rewrite; }
Security & Content Protection
-
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.
-
Force SSL for the Manager
If you wish to encrypt the MODX Manager only, using the freely available Cloud testing URL, 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://xxxx.modx.dev$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.
-
Force a specific domain for the Manager
If you wish to redirect all requests for the manager to a certain domain the following rule should work.
set $mgrcheck $host$request_uri;
if ($mgrcheck ~* "((www.|sub1.|sub2.)domain1.com|(www.)?domain2.org|(www.)?domain3.(org|com))/manager") {
rewrite ^ https://domain.com$request_uri;
}In the example above, you would replace the domain examples with your actual domains.
-
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.
-
Preventing Hotlinking Files from Other Sites
-
Preventing Hotlinking Files globally except certain sites
location ~ \.(woff|eot)$ { valid_referers mysite.com www.mysite.com; if ($invalid_referer) { return 403; } try_files $uri $uri/ =404; } location / { try_files $uri $uri/ @modx-rewrite; }
-
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; }
-
-
Password Protect a Directory
In the following example, you should replace
cXXXX
with the Cloud Code of your instance - this is the same as the SSH/SFTP username that you see in the Cloud 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. This file cannot be created from within the MODX Manager. It is created via SSH or SFTP.location /somefolder/ { auth_basic "Restricted"; auth_basic_user_file /cXXXX/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; }
To protect your access to the entire Cloud, you would do the same as above, however, you'd just do it for the
location / {…}
block. You can therefore combine the MODX rewrite line as it should also be inside thelocation / {…}
location / { auth_basic "Restricted"; auth_basic_user_file /cXXXX/home/.htpasswd; try_files $uri $uri/ @modx-rewrite; }
-
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; }
-
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
-
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.
-
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.
-
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
-
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; }
-
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
-
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.
-
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 1y; } location / { try_files $uri $uri/ @modx-rewrite; }
-
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.
-
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;
} -
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;
-
Common Security Headers
If you are using a service like https://securityheaders.com/ to evaluate your site you may want to implement additional security headers. Below is a baseline to get started. For a more specialized Content-Security-Policy, we recommend using a tool like https://report-uri.com/ to monitor your site and generate a CSP.add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
add_header X-Content-Type-Options "nosniff" always;
add_header Content-Security-Policy "default-src * 'unsafe-inline' 'unsafe-eval'; img-src * data: blob: 'unsafe-inline'";
add_header Referrer-Policy 'same-origin';
add_header X-Frame-Options SAMEORIGIN always;
add_header Permissions-Policy "geolocation=()";