NGINX is a lightweight, powerful web server that can also function as a reverse proxy, load balancer, HTTP cache, and mail proxy server. One drawback of Nginx is that it doesn’t support directory-based configuration overrides, like Apache does with .htaccess files. If Nginx were to implement this feature, it could potentially become the unbeatable web server software.

The event-driven architecture of Nginx is its most powerful feature. To learn more about the performance comparison between Nginx and Apache, you can read our article on NGINX vs. Apache. If you’re using the Apache2 HTTP server, check out our guide on the most important Apache2 configuration rules.

Serving Compressed Content

You can serve compressed content using ngx_http_gzip_module. This module is a filter that compresses responses using the “gzip” method. Use the following code to implement this feature.

gzip                       on;
gzip_vary                  on;
gzip_proxied               any;
gzip_disable               "msie6";
gzip_comp_level            6;
gzip_buffers               16 8k;
gzip_http_version          1.1;
gzip_types                 text/css text/javascript;

Serving Pre-Compressed Gzip Assets

Compressing responses on the fly using the “gzip” method can increase CPU usage. To reduce CPU load, you can serve pre-compressed gzip files directly. This can be achieved by enabling the ngx_http_gzip_static_module. This module allows Nginx to serve pre-compressed files instead of regular ones, but it requires the pre-compressed versions to be stored in the same directory as the original files.

For example, if you have an index.js file in the js_assets directory, you must also save a pre-compressed version named index.js.gz in the same directory. Ensure that the pre-compressed file has the same name as the original file with a gz extension. Note that this module will not work with files having the svgz extension. Use the following code to enable this functionality.

gzip_static                on;

Image Hotlinking Protection in NGINX

Image hotlinking is a common problem where other website owners steal your server’s bandwidth by using your image URLs on their websites. To prevent this, it is advisable to implement image hotlink protection. This can stop unauthorized websites from using your resources and reduce bandwidth usage. The following Nginx rule will return a 403 Forbidden Error for websites that are not whitelisted to access images served by your Nginx server.

location ~ \.(jpe?g?|png|gif)$ {
    # Replace diversifyindia.in with your domain name and any additional trusted domains.
    valid_referers none blocked diversifyindia.in *.diversifyindia.in google.com;
    if ($invalid_referer) {
        # Return a 403 Forbidden response if the referer is invalid (i.e., image hotlinking detected).
        return   403;
    }
}

Enable Browser Caching for General Assets

Browser caching enhances web server performance, especially for returning visitors. It works by caching heavy assets like videos, images, fonts, CSS, and JS files in the client’s browser. When a user revisits your website, the browser will serve the cached content, eliminating the need to re-download those assets from the server.

The benefits of browser caching include faster response times for returning visitors, bandwidth savings, and reduced unnecessary requests. Browser caching is enabled by adding the Cache-Control header to the response, along with an expiry value for each asset. This expiry value tells the browser how long the cached asset will remain valid, based on the max-age directive.

add_header Cache-Control "public, max-age=31536000";

The public keyword in the Cache-Control response header indicates that the response can be stored in a shared cache. The value 31536000 represents the time in seconds, which equals 1 year. This is calculated as:

31536000 = 60 seconds × 60 minutes × 24 hours × 365 days

Useful Headers for Improving Security

# This directive will block requests for stylesheets (i.e., .css files)
# where the MIME type is not "text/css".
# MIME sniffing can be a security risk if a browser incorrectly identifies
# a file as executable content.
# Servers prevent MIME sniffing by sending the X-Content-Type-Options header.
add_header             X-Content-Type-Options "nosniff";

# The X-Frame-Options header prevents the website from being embedded
# in <frame>, <iframe>, <embed>, or <object> tags, which protects against clickjacking attacks.
add_header             X-Frame-Options "SAMEORIGIN";

# Strict-Transport-Security ensures that browsers only access the site via HTTPS,
# automatically converting future HTTP requests to HTTPS.
add_header             Strict-Transport-Security "max-age=63072000";

# The Referrer-Policy header controls how much information about the referer
# should be sent with requests. This setting limits data exposure to cross-origin requests.
add_header             Referrer-Policy "strict-origin-when-cross-origin";

For more detailed security tips, you can read our article on 11 Rules to Improve the Security of Your Website.

Block Direct Execution of PHP Code

It is crucial to block direct execution of PHP code, especially for sensitive directories like the includes directory. For instance, you should only allow the execution of index.php. Blocking other PHP files helps protect against potential security risks where PHP scripts might expose confidential information in the browser, leading to a compromised website.

# Block PHP file execution in the includes directory. This improves security
# by preventing direct access to potentially vulnerable scripts.
location ~* /includes/.*\.php$ {
    deny all;          # Deny access to PHP files in the includes directory.
    access_log off;    # Disable access logging for blocked requests to reduce log file size.
    log_not_found off; # Avoid logging 404 errors for non-existent files.
}

Block by Referer in Nginx

Referer spam is a common issue for websites that allow users to comment on blog posts. Nginx configurations to block spam referrers can impact server performance, but using the following optimized configuration, you can efficiently block spam referrers. This setup evaluates only one regex to block as many referrers as needed. Traditional configurations often contain one regex per referrer, which can cause a significant performance penalty for the Nginx server.

# Extract the domain name from the referer URL to use it for referer filtering.
map $http_referer $http_referer_host {
    "~^(?:https?://)?([^/]+)" $1;
}

# Block requests from a list of known spam domains or subdomains.
map $http_referer_host $bad_referer {
    hostnames;
    default         0; # By default, no referer is considered "bad."

    .1xbetts.ru     1; # Block specific spam domains (example: 1xbetts.ru).
    .1xslot.site    1; # Add additional spam domains to the list.
    .adcash.com     1;
}

# Include the following block in your server configuration to block bad referers.
server {
    if ($bad_referer) {
        # Return status 444 to drop the connection without sending a response.
        return 444;
    }
}

Block Spam Bots or Block by User Agent on Nginx

In today’s internet landscape, bots are everywhere. There are two types of bots: good bots that follow the rules specified in your website’s robots.txt file and bad bots that ignore these rules. Both types of bots, whether good or bad, can consume a lot of your server’s resources. It’s a good practice to block as many unwanted bots as possible to reduce unnecessary resource consumption. You can analyze your server’s log files to identify bots causing high CPU usage and block them accordingly.

The following Nginx configuration can be used to block specific user agents whose strings match known bad bots:

# Add the following block to your server configuration to implement nginx bot protection.
server {

    # Block specific bots based on exact matches (case-sensitive).
    if ($http_user_agent ~ (AhrefsBot|ZAP|Zeus)) {
        return 403; # Deny access to bad bots.
    }

    # Block bots using case-insensitive matching (slower than case sensitive).
    if ($http_user_agent ~* (360spider|bolt|dragonfly)) {
        return 403; # Deny access to bots matching case-insensitive patterns.
    }
}

How to Configure WP Super Cache on Nginx Server

You can configure any WordPress caching plugin to work with an Nginx server by adjusting the cache file location in the following configuration.

# Store the value of the request URI in the cache_uri variable.
set $cache_uri $request_uri;

# Disable caching for POST requests because they should be handled dynamically by PHP.
if ($request_method = POST) {
    set $cache_uri 'null cache';
}

# Disable caching if the requested URI contains a query string (e.g., search results).
if ($query_string != "") {
    set $cache_uri 'null cache';
}

# Fix issues related to cache preloading for specific user agents (like WordPress localhost).
if ($http_user_agent ~* ^WordPress.*\ localhost ) {
    set $cache_uri    'null cache';
}

# Disable caching for URIs that match specific patterns (e.g., admin pages, feeds, sitemaps).
if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|/wp-(app|cron|login|register|mail).php|wp-.*.php|/feed/|index.php|wp-comments-popup.php|wp-links-opml.php|wp-locations.php|sitemap(_index)?.xml|[a-z0-9_-]+-sitemap([0-9]+)?.xml)") {
    set $cache_uri 'null cache';
}

# Prevent caching for logged-in users or commenters.
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in") {
    set $cache_uri    'null cache';
}

# Adjust this path according to the caching plugin you use (e.g., WP Super Cache).
# The following path is for WP Super Cache.
set $cachefile        "/wp-content/cache/supercache/$http_host/$cache_uri/index.html";

# Use a different cache file for HTTPS requests.
if ($scheme = https) {
    set $cachefile    "/wp-content/cache/supercache/$http_host/$cache_uri/index-https.html";
}

# Try to serve content in the following order:
# 1. From the cache file
# 2. Directly from the URI
# 3. Via PHP if not cached
location / {
    try_files         $cachefile $uri $uri/ /index.php?$args;
}

If you’re having difficulties setting up a WordPress website on Nginx, you can refer to our article on How to Set Up a WordPress Website on Nginx Server for step-by-step guidance.

Frequently Asked Questions

What is Load Balancing?

Load balancing refers to the efficient distribution of incoming network traffic across a group of backend servers. In Nginx, the upstream directive is used to enable load balancing between multiple backend servers, improving performance and availability.

How to Fix SVGZ Encoding Error in Nginx?

When trying to access an svgz file on an Nginx server, you may encounter the error: error on line 1 at column 1: Encoding error. To resolve this, you need to add a Content-Encoding header with the value set to gzip.

Here’s how you can fix the issue:

location ~ \.svgz$ {
    # turn off gzip module to avoid double header problem
    gzip           off;
    # fix svgz error with nginx server
    add_header     Content-Encoding "gzip";
    add_header     Vary  "Accept-Encoding";
}

Which Companies Use Nginx?

Many popular companies use Nginx as their web server, including Netflix, WordPress.com, Hulu, Cloudflare, Pinterest, GitHub, Airbnb, SoundCloud, and others. Nginx holds approximately 41.17% of the market share in the web and application server market.

Should I Learn Nginx or Apache?

Nginx is easy to learn and may be a good choice if your website experiences high traffic levels or if it’s hosted on a VPS instance instead of shared hosting. Its scalability and efficiency make it particularly suitable for high-demand environments.