Skip to content

Nginx

Configuring Nginx Through Plesk

The following outlines several common & recommended server configuration rules for various stores.

Force HTTPS

Do this in Plesk under Domain > Hosting & DNS > Hosting Settings > Permanent SEO-safe 301 redirect from HTTP to HTTPS

Force WWW

Do this in Plesk under Domain > Hosting & DNS > Hosting Settings > Preferred domain

Additional nginx Directives

The following snippet should be reviewed & customized as needed. It covers some recommendations & best practices for the following server configurations:

  • Default Charset
  • Directory Index
  • Miva URI Management
  • Strict-Transport-Security
  • X-XSS-Protection / XSS Filtering
  • Content-Security-Policy
  • Referrer-Policy
  • X-Content-Type-Options
  • ETags
  • Server software information
  • Compression
  • Cache Expiration
  • Content transformation
  • Old Platform Links - 301 Redirects

Verify and provide the following snippet in Plesk under Domain > Hosting & DNS > Apache & nginx Settings > Additional nginx directives

#-------------------------------------------------------------------------------
# Default Charset
#-------------------------------------------------------------------------------
charset utf-8;

#-------------------------------------------------------------------------------
# Directory Index
#-------------------------------------------------------------------------------

# Allow index.html & index.php files to load when uploaded to their own directory (ex. wordpress, mkdocs, etc.)
#
# Be sure to set `/mm5/` to match the directory Miva is installed in. It could be `/Merchant2/`, `/store/` or something else.

index "index.html" "index.php" "/mm5/uri.mvc";

#-------------------------------------------------------------------------------
# Miva URI Management
#-------------------------------------------------------------------------------

# The following rules are used to force most traffic to Miva's `uri.mvc` so that Miva can route to the proper page, product, or category.

location / {
    try_files $uri /mm5/uri.mvc$is_args$args;
}

#-------------------------------------------------------------------------------
# Strict-Transport-Security
#-------------------------------------------------------------------------------
#
# Force client-side TLS (Transport Layer Security) redirection.
#
# If a user types `example.com` in their browser, even if the server redirects
# them to the secure version of the website, that still leaves a window of
# opportunity (the initial HTTP connection) for an attacker to downgrade or
# redirect the request.
#
# The following header ensures that a browser only connects to your server
# via HTTPS, regardless of what the users type in the browser's address bar.
#
# (!) Be aware that Strict Transport Security is not revokable and you
#     must ensure being able to serve the site over HTTPS for the duration
#     you've specified in the `max-age` directive. When you don't have a
#     valid TLS connection anymore (e.g. due to an expired TLS certificate)
#     your visitors will see a nasty error message even when attempting to
#     connect over HTTP.
#
# (1) Preloading Strict Transport Security.
#     To submit your site for HSTS preloading, it is required that:
#     * the `includeSubDomains` directive is specified
#     * the `preload` directive is specified
#     * the `max-age` is specified with a value of at least 31536000 seconds
#       (1 year).
#     https://hstspreload.org/#deployment-recommendations
#
# https://tools.ietf.org/html/rfc6797#section-6.1
# https://owasp.org/www-project-secure-headers/#http-strict-transport-security
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
# https://www.html5rocks.com/en/tutorials/security/transport-layer-security/
# https://hstspreload.org/
#
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

#-------------------------------------------------------------------------------
# X-XSS-Protection / XSS Filtering
#-------------------------------------------------------------------------------
#
# Protect users against XSS attacks, mode=block instructs
# the browser to prevent the entire page from rendering when an XSS attack is detected.
#
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection

add_header X-XSS-Protection "1; mode=block" always;

#-------------------------------------------------------------------------------
# Content-Security-Policy
#-------------------------------------------------------------------------------

# Mitigate the risk of cross-site scripting and other content-injection
# attacks.
#
# This can be done by setting a Content Security Policy which permits
# trusted sources of content for your website.
#
# There is no policy that fits all websites, you will have to modify the
# `Content-Security-Policy` directives in the example depending on your needs.
#
# To make your CSP implementation easier, you can use an online CSP header
# generator such as:
# https://report-uri.com/home/generate/
#
# It is encouraged that you validate your CSP header using a CSP validator
# such as:
# https://csp-evaluator.withgoogle.com
#
# https://www.w3.org/TR/CSP/
# https://owasp.org/www-project-secure-headers/#content-security-policy
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
# https://developers.google.com/web/fundamentals/security/csp
# https://content-security-policy.com/

add_header Content-Security-Policy "default-src 'self' https: wss:; script-src 'self' https: 'unsafe-inline'; style-src https: 'unsafe-inline'; base-uri 'self' https:; font-src 'self' https: data:; img-src 'self' data: https:; frame-ancestors 'self'; object-src 'none'; upgrade-insecure-requests; block-all-mixed-content;" always;

#-------------------------------------------------------------------------------
# Referrer-Policy
#-------------------------------------------------------------------------------
#
# Controls how much referrer information (sent via the Referer header) should be included with requests
#
# Strict-origin-when-cross-origin... Send the origin, path, and querystring when performing a same-origin request.
# For cross-origin requests send the origin (only) when the protocol security level stays same (HTTPS→HTTPS).
# Don't send the Referer header to less secure destinations (HTTPS→HTTP).
#
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy

add_header Referrer-Policy "strict-origin-when-cross-origin" always;

#-------------------------------------------------------------------------------
# X-Content-Type-Options
#-------------------------------------------------------------------------------
#
# Prevent some browsers from MIME-sniffing the response.
#
# This reduces exposure to drive-by download attacks and cross-origin data
# leaks, and should be left uncommented, especially if the server is serving
# user-uploaded content or content that could potentially be treated as
# executable by the browser.
#
# https://owasp.org/www-project-secure-headers/#x-content-type-options
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
# https://blogs.msdn.microsoft.com/ie/2008/07/02/ie8-security-part-v-comprehensive-protection/
# https://mimesniff.spec.whatwg.org/

add_header X-Content-Type-Options nosniff always;

#-------------------------------------------------------------------------------
# ETags
#-------------------------------------------------------------------------------

# Remove `ETags` as resources are sent with far-future expires headers.
#
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag
# https://developer.yahoo.com/performance/rules.html#etags
# https://tools.ietf.org/html/rfc7232#section-2.3

etag off;

#-------------------------------------------------------------------------------
# Server software information
#-------------------------------------------------------------------------------

# Prevent Nginx from sending its version number in the "Server" response header.
#
# https://nginx.org/en/docs/http/ngx_http_core_module.html#server_tokens

server_tokens off;

#-------------------------------------------------------------------------------
# Compression
#-------------------------------------------------------------------------------

# https://nginx.org/en/docs/http/ngx_http_gzip_module.html

# Enable gzip compression.
# Default: off
gzip on;

# Compression level (1-9).
# 5 is a perfect compromise between size and CPU usage, offering about 75%
# reduction for most ASCII files (almost identical to level 9).
# Default: 1
gzip_comp_level 5;

# Don't compress anything that's already small and unlikely to shrink much if at
# all (the default is 20 bytes, which is bad as that usually leads to larger
# files after gzipping).
# Default: 20
gzip_min_length 256;

# Compress data even for clients that are connecting to us via proxies,
# identified by the "Via" header (required for CloudFront).
# Default: off
gzip_proxied any;

# Tell proxies to cache both the gzipped and regular version of a resource
# whenever the client's Accept-Encoding capabilities header varies;
# Avoids the issue where a non-gzip capable client (which is extremely rare
# today) would display gibberish if their proxy gave them the gzipped version.
# Default: off
gzip_vary on;

# Compress all output labeled with one of the following MIME-types.
# `text/html` is always compressed by gzip module.
# Default: text/html
gzip_types
  application/atom+xml
  application/geo+json
  application/javascript
  application/x-javascript
  application/json
  application/ld+json
  application/manifest+json
  application/rdf+xml
  application/rss+xml
  application/vnd.ms-fontobject
  application/wasm
  application/x-web-app-manifest+json
  application/xhtml+xml
  application/xml
  font/eot
  font/otf
  font/ttf
  image/bmp
  image/svg+xml
  image/vnd.microsoft.icon
  image/x-icon
  text/cache-manifest
  text/calendar
  text/css
  text/javascript
  text/markdown
  text/plain
  text/xml
  text/vcard
  text/vnd.rim.location.xloc
  text/vtt
  text/x-component
  text/x-cross-domain-policy;


#-------------------------------------------------------------------------------
# Cache Expiration
#-------------------------------------------------------------------------------

# Serve resources with a far-future expiration date.
#
# (!) If you don't control versioning with filename-based cache busting, you
# should consider lowering the cache times to something like one week.
#
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expires
# https://nginx.org/en/docs/http/ngx_http_headers_module.html#expires

location ~* \.(ico|pdf|flv|eot|otf|svg|ttf|woff|woff2)$ {
    expires 1y;
    add_header Cache-Control "public, no-transform";
}
location ~* \.(jpg|jpeg|png|gif|swf)$ {
    expires 1M;
    add_header Cache-Control "public, no-transform";
}

location ~ ^/mm5/(graphics|themes) {
    expires 10y;
}

#-------------------------------------------------------------------------------
# Content transformation
#-------------------------------------------------------------------------------

# Prevent intermediate caches or proxies (such as those used by mobile
# network providers) and browsers data-saving features from modifying
# the website's content using the `cache-control: no-transform` directive.
#
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
# https://tools.ietf.org/html/rfc7234#section-5.2.2.4
#
# (!) Carefully consider the impact on your visitors before disabling
#     content transformation. These transformations are performed to
#     improve the experience for data- and cost-constrained users
#     (e.g. users on a 2G connection).
#
#     You can test the effects of content transformation applied by
#     Google's Lite Mode by visiting: https://googleweblight.com/i?u=https://www.example.com
#
#     https://support.google.com/webmasters/answer/6211428
#
# (!) If you are using `ngx_pagespeed`, note that disabling this will
#     prevent `PageSpeed` from rewriting HTML files, and, if the
#     `pagespeed DisableRewriteOnNoTransform` directive isn't set to
#     `off`, also from rewriting other resources.
#
#     https://developers.google.com/speed/pagespeed/module/configuration#notransform

add_header Cache-Control "no-transform";

#-------------------------------------------------------------------------------
# Old Platform Links - 301 Redirects
#-------------------------------------------------------------------------------

# Static URL
# location /old-url {
#   return 301 /new_url;
# }

# # Patterns of URLs
# location /images {
#   rewrite ^/images/Product/medium(.*) /mm5/graphics/00000001/images/product/large$1 redirect;
#   rewrite ^/images/(.*) /mm5/graphics/00000001/images/$1 redirect;
# }

# # Legacy Miva Short Links
# location / {
#   if (!-e $request_filename){
#       rewrite ^/page/([^/]+)/PROD/([^/]+)$ /mm5/merchant.mvc?Store_code=$1&Screen=PROD&Product_code=$2 break;
#   }
#   if (!-e $request_filename){
#       rewrite ^/page/([^/]+)/CTGY/([^/]+)$ /mm5/merchant.mvc?Store_code=$1&Screen=CTGY&Category_code=$2 break;
#   }
#   if (!-e $request_filename){
#       rewrite ^/page/([^/]+)/([^/]+)/([^/]+)$ /mm5/merchant.mvc?Store_code=$1&Screen=PROD&Category_code=$2&Product_code=$3 break;
#   }
#   if (!-e $request_filename){
#       rewrite ^/page/([^/]+)/([^/]+)$ /mm5/merchant.mvc?Store_code=$1&Screen=$2 break;
#   }
# }

Additional Customizations

Dev Store Access Protection

Create Access Directory & .htpasswd File

First, create a directory named access on the server root. Then create a file name .htpasswd inside of the access directory.

After the .htpasswd file has been created, add all username / password combinations that should be supported in this file. Typically an online helper like https://www.web2generators.com/apache-tools/htpasswd-generator will be used for this step.

The contents of the .htpasswd file should look similar to the following:

support_jsmith:$apr1$5uj81asw$esBp5EvOpLmzvDaOV85kI1
api_foo:$apr1$bhsxcz8f$xiOVFFLqxukvqZA2g3Koi0
acme_inc:$apr1$zi86vao4$w6j8ElgVr0LBpInoj2JF1.

Update Nginx Config

After the access directory and .htpasswd file have been setup, modify the following snippet to the setup the IP addresses that should be allowed to bypass the password protection.

Nginx configs are applied in the server's Plesk admin. They cannont be added to the file-system of the server like Apache servers & their .htaccess files.

Open the Plesk admin of the server and navigate to Domains > example.com > Apache & nginx Settings and update the Additional nginx directives textbox with rules similar to these.

#-------------------------------------------------------------------------------
# Force Basic Auth If Not On IP Allow List
#-------------------------------------------------------------------------------

auth_basic "Restricted Access";
auth_basic_user_file /var/www/vhosts/example.com/access/.htpasswd;

#-------------------------------------------------------------------------------
# Miva IPs
#-------------------------------------------------------------------------------

allow 10.7.12.0/22;
allow 10.7.16.0/22;
allow 10.7.20.0/22;
allow 2607:4d00::/32;

# Server Requests To Self
# allow xx.xx.xx.xx;

#-------------------------------------------------------------------------------
# Client IPs
#-------------------------------------------------------------------------------

# allow xx.xx.xx.xx;

#-------------------------------------------------------------------------------
# 3rd Party IPs
#-------------------------------------------------------------------------------

# allow xx.xx.xx.xx;

#-------------------------------------------------------------------------------
# Satisfy Any Request (IP acceptance list or basic authentication)
#-------------------------------------------------------------------------------

deny all;
satisfy any;

#-------------------------------------------------------------------------------
# Deny Access to Hidden Files
#-------------------------------------------------------------------------------

location ~ /\.(.*) {
    return 403;
}