One place for hosting & domains

      Module

      How To Implement Browser Caching with Nginx’s header Module on CentOS 8


      Not using CentOS 8?


      Choose a different version or distribution.

      The author selected the COVID-19 Relief Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      The faster a website loads, the more likely a visitor is to stay. When websites are full of images and interactive content run by scripts loaded in the background, opening a website is not a simple task. It consists of requesting many different files from the server one by one. Minimizing the quantity of these requests is one way to speed up your website.

      One method for improving website performance is browser caching. Browser caching tells the browser that it can reuse local versions of downloaded files instead of requesting the server for them again and again. To do this, you must introduce new HTTP response headers that tell the browser how to behave.

      Nginx’s header module can help you accomplish browser caching. You can use this module to add any arbitrary headers to the response, but its major role is to properly set caching headers. In this tutorial, we will use Nginx’s header module to implement browser caching.

      Prerequisites

      To follow this tutorial, you will need:

      Step 1 — Creating Test Files

      In this step, we will create several test files in the default Nginx directory. We’ll use these files later to check Nginx’s default behavior and then to test that browser caching is working.

      To infer what kind of file is served over the network, Nginx does not analyze the file contents; that would be prohibitively slow. Instead, it looks up the file extension to determine the file’s MIME type, which denotes its purpose.

      Because of this behavior, the content of our test files is irrelevant. By naming the files appropriately, we can trick Nginx into thinking that, for example, one entirely empty file is an image and another is a stylesheet.

      Create a file named test.html in the default Nginx directory using truncate. This extension denotes that it’s an HTML page:

      • sudo truncate -s 1k /usr/share/nginx/html/test.html

      Let’s create a few more test files in the same manner: one jpg image file, one css stylesheet, and one js JavaScript file:

      • sudo truncate -s 1k /usr/share/nginx/html/test.jpg
      • sudo truncate -s 1k /usr/share/nginx/html/test.css
      • sudo truncate -s 1k /usr/share/nginx/html/test.js

      The next step is to check how Nginx behaves with respect to sending caching control headers on a fresh installation with the files we have just created.

      Step 2 — Checking the Default Behavior

      By default, all files will have the same default caching behavior. To explore this, we’ll use the HTML file we created in step 1, but you can run these tests with any example files.

      So, let’s check if test.html is served with any information regarding how long the browser should cache the response. The following command requests a file from our local Nginx server and shows the response headers:

      • curl -I http://localhost/test.html

      You should see several HTTP response headers:

      Output: Nginx response headers

      HTTP/1.1 200 OK Server: nginx/1.14.1 Date: Thu, 04 Feb 2021 18:23:09 GMT Content-Type: text/html Content-Length: 1024 Last-Modified: Thu, 04 Feb 2021 18:22:39 GMT Connection: keep-alive ETag: "601c3b6f-400" Accept-Ranges: bytes

      In the second to last line you will find the ETag header, which contains a unique identifier for this particular revision of the requested file. If you execute the previous curl command repeatedly, you will find the exact same ETag value.

      When using a web browser, the ETag value is stored and sent back to the server with the If-None-Match request header when the browser wants to request the same file again — for example, when refreshing the page.

      We can simulate this on the command line with the following command. Make sure you change the ETag value in this command to match the ETag value in your previous output:

      • curl -I -H 'If-None-Match: "601c3b6f-400"' http://localhost/test.html

      The response will now be different:

      Output: Nginx response headers

      HTTP/1.1 304 Not Modified Server: nginx/1.14.1 Date: Thu, 04 Feb 2021 18:24:05 GMT Last-Modified: Thu, 04 Feb 2021 18:22:39 GMT Connection: keep-alive ETag: "601c3b6f-400"

      This time, Nginx will respond with 304 Not Modified. It won’t send the file over the network again; instead, it will tell the browser that it can reuse the file it already has downloaded locally.

      This is useful because it reduces network traffic, but it’s not good enough to achieve good caching performance. The problem with ETag is that the browser always sends a request to the server asking if it can reuse its cached file. Even though the server responds with a 304 instead of sending the file again, it still takes time to make the request and receive the response.

      In the next step, we will use the headers module to append caching control information. This will make the browser to cache some files locally without explicitly asking the server if its fine to do so.

      Step 3 — Configuring Cache-Control and Expires Headers

      In addition to the ETag file validation header, there are two caching control response headers: Cache-Control and Expires. Cache-Control is the newer version, with more options than Expires and is generally more useful if you want finer control over your caching behavior.

      If these headers are set, they can tell the browser that the requested file can be kept locally for a certain amount of time (including forever) without requesting it again. If the headers are not set, browsers will always request the file from the server, expecting either 200 OK or 304 Not Modified responses.

      We can use the header module to set these HTTP headers. The header module is a core Nginx module, which means it doesn’t need to be installed separately to be used.

      To add the header module, open the default server block Nginx configuration file in vi (here’s a short introduction to vi) or your favorite text editor:

      • sudo vi /etc/nginx/nginx.conf

      Find the server configuration block:

      /etc/nginx/nginx.conf

      . . .
      server {
          listen 80 default_server;
          listen [::]:80 default_server;
          server_name  _;
          root         /usr/share/nginx/html;
      . . .
      

      Add the following two new sections here: one before the server block, to define how long to cache different file types, and one inside it, to set the caching headers appropriately:

      Modified /etc/nginx/nginx.conf

      . . .
      # Expires map
      map $sent_http_content_type $expires {
          default                    off;
          text/html                  epoch;
          text/css                   max;
          application/javascript     max;
          ~image/                    max;
          ~font/                     max;
      }
      
      server {
          listen 80 default_server;
          listen [::]:80 default_server;
          server_name  _;
          root         /usr/share/nginx/html;
      
          expires $expires;
      . . .
      

      The section before the server block is a new map block that defines the mapping between the file type and how long that kind of file should be cached.

      We’re using several different settings in this map:

      • The default value is set to off, which will not add any caching control headers. It’s a safe bet for the content, we have no particular requirements on how the cache should work.

      • For text/html, we set the value to epoch. This is a special value that results explicitly in no caching, which forces the browser to always ask if the website itself is up to date.

      • For text/css and application/javascript, which are stylesheets and JavaScript files, we set the value to max. This means the browser will cache these files for as long as possible, reducing the number of requests considerably given that there are typically many of these files.

      • The last two settings are for ~image/ and ~font/, which are regular expressions that will match all file types containing image/ or font/ in their MIME type name (like image/jpg, image/png or font/woff2). Like stylesheets, both pictures and web fonts on websites can be safely cached to speed up page-loading times, so we set this to max as well.

      Note: These are just a few examples of the most common MIME types used on websites. You can get acquainted with the more extensive list of such types on Common MIME types site and add others to the map that you might find useful in your case.

      Inside the server block, the expires directive (a part of the headers module) sets the caching control headers. It uses the value from the $expires variable set in the map. This way, the resulting headers will be different depending on the file type.

      Save and close the file to exit.

      To enable the new configuration, restart Nginx:

      • sudo systemctl restart nginx

      Next, let’s make sure our new configuration works.

      Step 4 — Testing Browser Caching

      Execute the same request as before for the test HTML file:

      • curl -I http://localhost/test.html

      This time the response will be different. You will see two additional HTTP response headers:

      Nginx response headers

      HTTP/1.1 200 OK
      Server: nginx/1.14.1
      Date: Thu, 04 Feb 2021 18:28:19 GMT
      Content-Type: text/html
      Content-Length: 1024
      Last-Modified: Thu, 04 Feb 2021 18:22:39 GMT
      Connection: keep-alive
      ETag: "601c3b6f-400"
      Expires: Thu, 01 Jan 1970 00:00:01 GMT
      Cache-Control: no-cache
      Accept-Ranges: bytes
      

      The Expires header shows a date in the past and Cache-Control is set with no-cache, which tells the browser to always ask the server if there is a newer version of the file (using the ETag header, like before).

      You’ll find a difference in response with the test image file.

      • curl -I http://localhost/test.jpg

      Note the new output:

      Nginx response headers

      HTTP/1.1 200 OK
      Server: nginx/1.14.1
      Date: Thu, 04 Feb 2021 18:29:05 GMT
      Content-Type: image/jpeg
      Content-Length: 1024
      Last-Modified: Thu, 04 Feb 2021 18:22:42 GMT
      Connection: keep-alive
      ETag: "601c3b72-400"
      Expires: Thu, 31 Dec 2037 23:55:55 GMT
      Cache-Control: max-age=315360000
      Accept-Ranges: bytes
      

      In this case, Expires shows the date in the distant future, and Cache-Control contains max-age information, which tells the browser how long it can cache the file in seconds. This tells the browser to cache the downloaded image for as long as it can, so any subsequent appearances of this image will use local cache and not send a request to the server at all.

      The result should be similar for both test.js and test.css, as both JavaScript and stylesheet files are set with caching headers too.

      This means the cache control headers have been configured properly and your website will benefit from the performance gain and less server requests due to browser caching. You should customize the caching settings based on your website’s content, but the defaults in this article are a reasonable place to start.

      Conclusion

      The headers module can be used to add any arbitrary headers to the response, but properly setting caching control headers is one of its most useful applications. It increases performance for the website users, especially on networks with higher latency, like mobile carrier networks. It can also lead to better results on search engines that factor speed tests into their results. Setting browser caching headers is a crucial recommendation from Google’s PageSpeed and similar performance testing tools.

      You can find more detailed information about the headers module in Nginx’s official headers module documentation.



      Source link

      How To Implement Browser Caching with Nginx’s header Module on Ubuntu 20.04


      The author selected the COVID-19 Relief Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      The faster a website loads, the more likely a visitor is to stay. When websites are full of images and interactive content run by scripts loaded in the background, opening a website is not a simple task. It consists of requesting many different files from the server one by one. Minimizing the quantity of these requests is one way to speed up your website.

      One method for improving website performance is browser caching. Browser caching tells the browser that it can reuse local versions of downloaded files instead of requesting the server for them again and again. To do this, you must introduce new HTTP response headers that tell the browser how to behave.

      Nginx’s header module can help you accomplish browser caching. You can use this module to add any arbitrary headers to the response, but its major role is to properly set caching headers. In this tutorial, we will use Nginx’s header module to implement browser caching.

      Prerequisites

      To follow this tutorial, you will need:

      Step 1 — Creating Test Files

      In this step, we will create several test files in the default Nginx directory. We’ll use these files later to check Nginx’s default behavior and then to test that browser caching is working.

      To infer what kind of file is served over the network, Nginx does not analyze the file contents; that would be prohibitively slow. Instead, it looks up the file extension to determine the file’s MIME type, which denotes its purpose.

      Because of this behavior, the content of our test files is irrelevant. By naming the files appropriately, we can trick Nginx into thinking that, for example, one entirely empty file is an image and another is a stylesheet.

      Create a file named test.html in the default Nginx directory using truncate. This extension denotes that it’s an HTML page:

      • sudo truncate -s 1k /var/www/html/test.html

      Let’s create a few more test files in the same manner: one jpg image file, one css stylesheet, and one js JavaScript file:

      • sudo truncate -s 1k /var/www/html/test.jpg
      • sudo truncate -s 1k /var/www/html/test.css
      • sudo truncate -s 1k /var/www/html/test.js

      The next step is to check how Nginx behaves with respect to sending caching control headers on a fresh installation with the files we have just created.

      Step 2 — Checking the Default Behavior

      By default, all files will have the same default caching behavior. To explore this, we’ll use the HTML file we created in step 1, but you can run these tests with any example files.

      So, let’s check if test.html is served with any information regarding how long the browser should cache the response. The following command requests a file from our local Nginx server and shows the response headers:

      • curl -I http://localhost/test.html

      You will see several HTTP response headers:

      Output: Nginx response headers

      HTTP/1.1 200 OK Server: nginx/1.18.0 (Ubuntu) Date: Tue, 02 Feb 2021 19:03:21 GMT Content-Type: text/html Content-Length: 1024 Last-Modified: Tue, 02 Feb 2021 19:02:58 GMT Connection: keep-alive ETag: "6019a1e2-400" Accept-Ranges: bytes

      In the second to last line you will find the ETag header, which contains a unique identifier for this particular revision of the requested file. If you execute the previous curl command repeatedly, you will find the exact same ETag value.

      When using a web browser, the ETag value is stored and sent back to the server with the If-None-Match request header when the browser wants to request the same file again — for example, when refreshing the page.

      We can simulate this on the command line with the following command. Make sure you change the ETag value in this command to match the ETag value in your previous output:

      • curl -I -H 'If-None-Match: "6019a1e2-400"' http://localhost/test.html

      The response will now be different:

      Output: Nginx response headers

      HTTP/1.1 304 Not Modified Server: nginx/1.18.0 (Ubuntu) Date: Tue, 02 Feb 2021 19:04:09 GMT Last-Modified: Tue, 02 Feb 2021 19:02:58 GMT Connection: keep-alive ETag: "6019a1e2-400"

      This time, Nginx will respond with 304 Not Modified. It won’t send the file over the network again; instead, it will tell the browser that it can reuse the file it already has downloaded locally.

      This is useful because it reduces network traffic, but it’s not good enough to achieve good caching performance. The problem with ETag is that browsers always send a request to the server asking if it can reuse its cached file. Even though the server responds with a 304 instead of sending the file again, it still takes time to make the request and receive the response.

      In the next step, we will use the headers module to append caching control information. This will make the browser cache some files locally without explicitly asking the server if its fine to do so.

      Step 3 — Configuring Cache-Control and Expires Headers

      In addition to the ETag file validation header, there are two caching control response headers: Cache-Control and Expires. Cache-Control is the newer version, with more options than Expires and is generally more useful if you want finer control over your caching behavior.

      If these headers are set, they can tell the browser that the requested file can be kept locally for a certain amount of time (including forever) without requesting it again. If the headers are not set, browsers will always request the file from the server, expecting either 200 OK or 304 Not Modified responses.

      We can use the header module to set these HTTP headers. The header module is a core Nginx module, which means it doesn’t need to be installed separately to be used.

      To add the header module, open the default Nginx configuration file in nano or your favorite text editor:

      • sudo nano /etc/nginx/sites-available/default

      Find the server configuration block:

      /etc/nginx/sites-available/default

      . . .
      # Default server configuration
      #
      
      server {
          listen 80 default_server;
          listen [::]:80 default_server;
      
      . . .
      

      Add the following two new sections here: one before the server block, to define how long to cache different file types, and one inside it, to set the caching headers appropriately:

      Modified /etc/nginx/sites-available/default

      . . .
      # Default server configuration
      #
      
      # Expires map
      map $sent_http_content_type $expires {
          default                    off;
          text/html                  epoch;
          text/css                   max;
          application/javascript     max;
          ~image/                    max;
          ~font/                     max;
      }
      
      server {
          listen 80 default_server;
          listen [::]:80 default_server;
      
          expires $expires;
      . . .
      

      The section before the server block is a new map block that defines the mapping between the file type and how long that kind of file should be cached.

      We’re using several different settings in this map:

      • The default value is set to off, which will not add any caching control headers. It’s a safe bet for the content, we have no particular requirements on how the cache should work.

      • For text/html, we set the value to epoch. This is a special value that results explicitly in no caching, which forces the browser to always ask if the website itself is up to date.

      • For text/css and application/javascript, which are stylesheets and JavaScript files, we set the value to max. This means the browser will cache these files for as long as possible, reducing the number of requests considerably given that there are typically many of these files.

      • The last two settings are for ~image/ and ~font/, which are regular expressions that will match all file types containing image/ or font/ in their MIME type name (like image/jpg, image/png or font/woff2). Like stylesheets, both pictures and web fonts on websites can be safely cached to speed up page-loading times, so we set this to max as well.

      Note: These are just a few examples of the most common MIME types used on websites. You can get acquainted with the more extensive list of such types on Common MIME types site and add others to the map that you might find useful in your case.

      Inside the server block, the expires directive (a part of the headers module) sets the caching control headers. It uses the value from the $expires variable set in the map. This way, the resulting headers will be different depending on the file type.

      Save and close the file to exit.

      To enable the new configuration, restart Nginx:

      • sudo systemctl restart nginx

      Next, let’s make sure our new configuration works.

      Step 4 — Testing Browser Caching

      Execute the same request as before for the test HTML file:

      • curl -I http://localhost/test.html

      This time the response will be different. You will see two additional HTTP response headers:

      Output

      HTTP/1.1 200 OK Server: nginx/1.18.0 (Ubuntu) Date: Tue, 02 Feb 2021 19:10:13 GMT Content-Type: text/html Content-Length: 1024 Last-Modified: Tue, 02 Feb 2021 19:02:58 GMT Connection: keep-alive ETag: "6019a1e2-400" Expires: Thu, 01 Jan 1970 00:00:01 GMT Cache-Control: no-cache Accept-Ranges: bytes

      The Expires header shows a date in the past and Cache-Control is set with no-cache, which tells the browser to always ask the server if there is a newer version of the file (using the ETag header, like before).

      You’ll find a difference in response with the test image file:

      • curl -I http://localhost/test.jpg

      Note the new output:

      Output

      HTTP/1.1 200 OK Server: nginx/1.18.0 (Ubuntu) Date: Tue, 02 Feb 2021 19:10:42 GMT Content-Type: image/jpeg Content-Length: 1024 Last-Modified: Tue, 02 Feb 2021 19:03:02 GMT Connection: keep-alive ETag: "6019a1e6-400" Expires: Thu, 31 Dec 2037 23:55:55 GMT Cache-Control: max-age=315360000 Accept-Ranges: bytes

      In this case, Expires shows the date in the distant future, and Cache-Control contains max-age information, which tells the browser how long it can cache the file in seconds. This tells the browser to cache the downloaded image for as long as it can, so any subsequent appearances of this image will use local cache and not send a request to the server at all.

      The result should be similar for both test.js and test.css, as both JavaScript and stylesheet files are set with caching headers too.

      This means the cache control headers have been configured properly and your website will benefit from the performance gain and less server requests due to browser caching. You should customize the caching settings based on your website’s content, but the defaults in this article are a reasonable place to start.

      Conclusion

      The headers module can be used to add any arbitrary headers to the response, but properly setting caching control headers is one of its most useful applications. It increases performance for the website users, especially on networks with higher latency, like mobile carrier networks. It can also lead to better results on search engines that factor speed tests into their results. Setting browser caching headers is a crucial recommendation from Google’s PageSpeed and similar performance testing tools.

      More detailed information about the headers module can be found in Nginx’s official headers module documentation.



      Source link

      How to Use Nginx’s map Module on Ubuntu 20.04


      The author selected the Open Internet/Free Speech Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      Nginx’s map module lets you create variables in Nginx’s configuration file whose values are conditional — that is, they depend on other variables’ values. In this guide, we will look at how to use Nginx’s map module to implement two examples: setting up a list of redirects from old website URLs to new ones and creating an allowlist of countries to control traffic to your website.

      Prerequisites

      To follow this tutorial, you will need:

      Step 1 — Creating and Testing an Example Webpage

      First, we will create a test file representing a newly published website. We’ll use this file to test our configuration.

      Let’s create a simple page, index.html, in the default Nginx website directory. This file will just have plain text describing what’s inside: Home:

      • sudo sh -c 'echo "Home" > /var/www/html/index.html'

      With this test file in place, we’ll check that it’s being served correctly with curl. We don’t need to specify index.html for this command because that file is served by default if no exact filename is provided:

      In response, you should see a single word saying Home just like below:

      Output

      Home

      Now let’s try to access a file that doesn’t exist in /var/www/html/, like old.html:

      • curl -L http://localhost/old.html

      The response will be a system error message, 404 Not Found, meaning the page does not exist:

      Output

      <html> <head><title>404 Not Found</title></head> <body bgcolor="white"> <center><h1>404 Not Found</h1></center> <hr><center>nginx/1.18.0 (Ubuntu)</center> </body> </html>

      We’re just using a dummy website in this tutorial, but if old.html was a page on a real website that used to exist and was deleted, returning a 404 would mean that all links to that page are broken. This is less than ideal because those links may have been indexed by Google, printed out or written down, or shared by any other means.

      In the next step, we’ll use the map module to make sure this old address will work again by redirecting viewers to the new replacements automatically.

      Step 2 — Configuring the Redirects

      For small websites with only a few pages, simple if conditional statements can be used for redirects and similar things. However, such a configuration is not easy to maintain or extend in the long run as the list of conditions grows longer.

      The map module is a more elegant, concise solution. It allows you to compare Nginx variable values against a list of conditions and then associate a new value with the variable depending on the match. In this example, we’ll be comparing the requested URL with the list of old pages that we want to redirect to their new counterparts. For each old address, we’ll associate the new one.

      The map module is a core Nginx module, which means it doesn’t need to be installed separately. To create the necessary map and redirect configuration, open the default server block Nginx configuration file in nano or your favorite text editor:

      • sudo nano /etc/nginx/sites-available/default

      Find the server configuration block, which looks like this:

      /etc/nginx/sites-available/default

      . . .
      # Default server configuration
      #
      
      server {
          listen 80 default_server;
          listen [::]:80 default_server;
      
      . . .
      

      We’ll be adding two new sections: one before the server block, and one inside it.

      The section before the server block is a new map block, which defines the mapping between the old URLs and the new ones using the map module. The section inside the server block is the redirect itself:

      /etc/nginx/sites-available/default

      . . .
      # Default server configuration
      #
      
      # Old website redirect map
      #
      map $uri $new_uri {
          /old.html /index.html;
      }
      
      server {
          listen 80 default_server;
          listen [::]:80 default_server;
      
          # Old website redirect
          if ($new_uri) {
              rewrite ^ $new_uri permanent;
          }
      . . .
      

      The map $uri $new_uri directive takes the contents of system $uri variable, which contains the URL address of the requested page, and then compares it against the list of conditions in the curly brackets. Each item in the list of conditions has two sections: the value to match against and the new value to assign to the variable if it matches.

      The line /old.html /index.html inside the map block means that if $uri’s value is /old.html, $new_uri will be changed to /index.html. If it doesn’t match, it’s not changed. Here, we only define one condition, but you can define as many conditions as you want in a map.

      Using a conditional if statement inside the server block, we check if the $new_uri variable’s value is set. If it is, it means the condition in the map was satisfied, and we should redirect to the new website using the rewrite command. The permanent keyword ensured that the redirect will be a 301 Moved Permanently HTTP redirect, which means that the old address is no longer valid and will not come back online.

      Save and close the file to exit.

      To enable the new configuration, restart Nginx:

      • sudo systemctl restart nginx

      To test the new configuration, execute the same request as before:

      • curl -L http://localhost/old.html

      This time there will be no 404 Not Found error in the output. Instead, you’ll see the simple home page we created in Step 1:

      Output

      Home

      This means the map has been appropriately configured, and you can use it to redirect URLs by adding more entries to the map.

      Redirecting URLs is one useful application of the map module. Another, which we’ll explore in the next step, is filtering traffic based on the visitors’ geographical location.

      Step 3 — Restricting Website Access to Certain Countries

      Sometimes, a server might receive an excessive quantity of automated, malicious requests. This could be a DDoS attack, an attempt to brute-force passwords to website administrative panels, or an attempt to exploit known vulnerabilities in software to attack the website and use it to send spam or modify the site contents.

      Such automated attacks may come from many different distributed servers in many different countries, making it difficult to block. One solution to mitigate the effects of an attack like this is to create an allowlist of countries that can access the website.

      It’s not a perfect solution, but in situations where restricting access to the website based on the visitor’s geographical location is a sensible choice and does not limit the website’s audience, this solution has the benefit of being fast and less error-prone.

      Filtering at the server level is faster than filtering at the website level and also covers all requests (including static files, like images). This kind of filtering also prevents requests from reaching the website software directly, making vulnerabilities harder to exploit.

      To make use of the geographical filtering, we must first install the Nginx GeoIP module as well as the GeoIP database containing the mappings between visitors’ IP addresses and their respective countries. To do so, let’s execute:

      • sudo apt install libnginx-mod-http-geoip geoip-database

      Now, let’s first create a new configuration file:

      • sudo nano /etc/nginx/conf.d/geoip.conf

      Paste the following contents into the file. This tells Nginx where to find the GeoIP database to identify countries based on the visitors’ IP addresses:

      /etc/nginx/conf.d/geoip.conf

      # GeoIP database path
      #
      
      geoip_country /usr/share/GeoIP/GeoIP.dat;
      

      The next step is to create the necessary map and restriction configuration. Open the default server block Nginx configuration:

      • sudo nano /etc/nginx/sites-available/default

      Find the server configuration block which, after the modifications in steps 1 and 2, looks like this:

      /etc/nginx/sites-available/default

      . . .
      # Default server configuration
      #
      
      # Old website redirect map
      #
      map $uri $new_uri {
          /old.html /index.html;
      }
      
      server {
          listen 80 default_server;
          listen [::]:80 default_server;
      
          # Old website redirect
          if ($new_uri) {
              rewrite ^ $new_uri permanent;
          }
      . . .
      

      We’ll be adding two new sections: one before the server block and one inside it.

      The section before the server block is a new map block, which defines the default action (access disallowed) as well as the list of country codes allowed to access the website. The section inside the server block denies access to the website if the map result says so:

      Modified /etc/nginx/sites-available/default

      . . .
      # Default server configuration
      #
      
      # Allowed countries
      #
      map $geoip_country_code $allowed_country {
          default no;
          country_code_1 yes;
          country_code_2 yes;
      }
      
      # Old website redirect map
      #
      map $uri $new_uri {
          /old.html /index.html;
      }
      
      server {
          listen 80 default_server;
          listen [::]:80 default_server;
      
          # Disallow access based on GeoIP
          if ($allowed_country = no) {
              return 444;
          }
      
          # Old website redirect
          if ($new_uri) {
              rewrite ^ $new_uri permanent;
          }
      . . .
      

      Save and close the file to exit.

      Here, we used country_code_1 and country_code_2 as placeholders. Replace these variables with the two-character country code for the country or countries you want to allow. You can use the ISO’s full, searchable list of all country codes to find. For example, the code for the United States is US.

      Unlike the first example, in this map block, the $allowed_country variable will always be set to something. By default, it’s set to no; if the $geoip_country_code variable matches one of the country codes in the block, it’s set to yes. If the $allowed_country variable is no, we return a 444 Connection Closed Without Response instead of serving the actual website.

      To enable the new configuration, restart Nginx:

      • sudo systemctl restart nginx

      If you didn’t add your country to the allowlist, when you try to visit http://your_server_ip, you’ll see an error message like The page isn’t working or The page didn’t send any data. If you did add your country to the allowlist, you’ll see Home as before.

      Conclusion

      The map module not only allows simple comparisons but also supports regular expressions allowing more complex matches. It is a great way to make configuration files clearer if multiple conditions must be evaluated.

      More detailed information can be found in Nginx’s official map module documentation.



      Source link