(Plesk for Linux) Setting up IP Geolocation for a Website

IP geolocation maps a website visitor’s IP address to their real-world geographical location, for example, a country or a city.

With IP geolocation, you can tailor how to display your website to visitors depending on the place they live in. For example, you can redirect your visitors to location-specific web pages or you can block access to your website for visitors from a specific country.

In this topic, you will learn how to set up IP geolocation in Plesk and how to use IP geolocation with common use cases, such as:

Setting up IP Geolocation in Plesk

You set up IP geolocation in Plesk using the built-in ngx_http_geoip2_module nginx module and MaxMind geolocation databases, which you need to download.

1. Downloading MaxMind Geolocation Databases

The MaxMind company offers two geolocation databases: free GeoLite2 and paid GeoIP2, which is more accurate than its free counterpart.

In this topic, we will use the free GeoLite2 database as an example. You can always upgrade it to GeoIP2.

To download the GeoLite2 geolocation database, you first need to create a free GeoLite2 account and then choose how to download the databases. You can do so in the following ways:

  • Directly download the databases’ archives and then upload them to your Plesk server.

  • Get permalinks. To download the databases, use these permalinks with scripts or curl and get commands. You will also need to generate and then use a license key for your GeoLite2 account. Learn more how to get and use permalinks.

  • (Recommended) Use the geoipupdate utility.

    We recommend this way of downloading the geolocation databases because this utility is available from system package repositories in major Linux distributions. With the geoipupdate utility, you can not only download but also update the geolocation databases.

To download the GeoLite2 geolocation database using the geoipupdate utility:

Note

To see which utility version is available and the utility settings, run geoipupdate -v.

  1. Sign up to get a free GeoLite2 account.

  2. Log in to your GeoLite2 account and generate a license key. Once you have done so, copy the key and keep it safe. For security reasons, license keys are shown only when they are generated.

    When you generate a license key, you will also see your account ID. You will need both the account ID and the license key at the next step.

  3. Open the /etc/GeoIP.conf file for editing. The path to the GeoIP.conf file may differ depending on your Linux distribution.

  4. Paste your account ID, license key, and the edition IDs of the databases you want to download. Separate multiple editions with spaces. Once you complete the setup, save the file.

  5. To download the databases, run sudo geoipupdate or sudo geoipupdate -v (to see the detailed information on which databases are downloaded and where to).

2. Enabling ngx_http_geoip2_module in Plesk

In Plesk 18.0.46 and later, nginx is already compiled with ngx_http_geoip2_module. By default, the module is disabled.

Note

To check if nginx is compiled with the module, run nginx -V. If it is, you will see mod_geoip2 in the output.

To enable ngx_http_geoip2_module:

  1. Log in to your Plesk server via SSH.
  2. Enable the module by running plesk bin nginx -e geoip2.

The module is enabled. You will see it in the list of enabled nginx modules if you run plesk bin nginx -s.

3. Configuring variables

To use geolocation data and make decisions based on them, you need to map a website visitor’s IP address to various properties (such as a country or city name) and store them as variables in nginx configuration files.

To configure variables:

  1. Add the following directives to the /etc/nginx/conf.d/geoip2.conf file:

    geoip2 <path-to-the-database>/GeoLite2-Country.mmdb {
        auto_reload 5m;
        $geoip2_metadata_country_build metadata build_epoch;
        $geoip2_data_country_code country iso_code;
        $geoip2_data_country_name country names en;
    }
    
    geoip2 <path-to-the-database>/GeoLite2-City.mmdb {
        $geoip2_data_city_name city names en;
    }
    

    Substitute <path-to-the-database> with the actual database path, for example, /usr/share/GeoIP/GeoLite2-Country.mmdb

    On CentOS, AlmaLinux, and other Red Hat-like operating systems, the default locations of the databases are the following:

    • /usr/share/GeoIP/GeoLite2-ASN.mmdb
    • /usr/share/GeoIP/GeoLite2-City.mmdb
    • /usr/share/GeoIP/GeoLite2-Country.mmdb

    On Debian and Ubuntu, the default location of the databases is /var/lib/GeoIP.

  2. Run the service nginx reload command to reload the nginx configuration file.

You have completed setting up IP geolocation in Plesk. You can now use ngx_http_geoip2_module with various use cases described below.

To apply these use cases, you need to configure nginx directives referencing the following variables:

Variable name Variable meaning
$geoip2_metadata_country_build Build time of the GeoLite2-Country database
$geoip2_data_country_code Two-letter ISO code of the country
$geoip2_data_country_name Country name in English
$geoip2_data_city_name City name in English

Blocking Access to a Website For Visitors From a Specific Country

You can deny website access to visitors from a specific country. When they try to access the website, they will see the HTTP 403 status code, which means access to the requested resource is forbidden.

To block access to a website for visitors from a specific country:

  1. Go to Websites & Domains > domain > the “Hosting & DNS” tab > Apache & nginx Settings.

  2. Put the following in the “Additional nginx directives” textbox and then click OK.

    if ($geoip2_data_country_code = "XX") {
            return 403;
    }
    

    Where XX is the two-letter ISO code of the country whose visitors you want to block (for example, AQ for Antarctica).

Visitors from the country whose ISO code you have specified no longer have access to your website.

Redirecting Website Visitors to a Geolocation-specific URL

You can redirect visitors who access the general URL (for example, https://example.com/test) to a country-specific URL (for example, https:// example.com/US/test).

To redirect website visitors to a geolocation-specific URL:

  1. Go to Websites & Domains > domain > the “Hosting & DNS” tab > Apache & nginx Settings.

  2. Put the following in the “Additional nginx directives” textbox and then click OK.

    location = /test {
        return 301 https://$host/$geoip2_data_country_code/<geolocation-specific-URL-part>;
    }
    

    Where <geolocation-specific-URL-part> is the geolocation-specific URL part (for example, test).

Visitors, for example, from the United States, will now be redirected to https://example.com/US/test.

Applying Geolocation-based Decisions to Websites that Belong to One Hosting Plan

You can, for example, block or redirect visitors from a specific country but apply it not to one individual website but to all websites that belong to one hosting plan. This case is similar to the two previous ones with an individual website. The only difference is that you need to use not a domain’s but a hosting plan’s nginx settings.

Let’s see how to do so on the example of website access block.

To block access to websites that belong to one hosting plan for visitors from a specific country:

  1. Go to Service Plans and click the name of the service plan access to whose websites you want to block.

  2. Go to the “Web Server” tab, add the following to the “Additional nginx directives” textbox, and then click OK.

    if ($geoip2_data_country_code = "XX") {
        return 403;
    }
    

    Where XX is the two-letter ISO code of the country whose visitors you want to block (for example, AQ for Antarctica).

Visitors from the country whose ISO code you have specified no longer have access to all websites that belong to the hosting plan.

Block Access to All Websites Hosted on the Server for Visitors From a Specific Country

There are two ways to implement this use case: using configuration templates or hosting plan settings. We have described how to use hosting plan settings earlier. Below we will show you how to use custom configuration templates.

Note

You need to use either configuration templates or hosting plan settings. It is not possible to deny access to all websites hosted on the server by adding the global nginx configuration file to /etc/nginx/conf.d.

To block access to all websites hosted on the server for visitors from a specific country:

  1. Create a custom configuration template nginxDomainVirtualHost.php using this procedure.

  2. Find the following text at the end of the copied default template:

    <?php if (is_file($VAR->domain->physicalHosting->customNginxConfigFile)) : ?>
        include "<?php echo $VAR->domain->physicalHosting->customNginxConfigFile ?>";
    <?php endif ?>
    }
    

    And insert your access restriction directives before the right brace as follows:

    <?php if (is_file($VAR->domain->physicalHosting->customNginxConfigFile)) : ?>
        include "<?php echo $VAR->domain->physicalHosting->customNginxConfigFile ?>";
    <?php endif ?>
        if ($geoip2_data_country_code = "XX") {
            return 403;
        }
    }
    

    Where XX is the two-letter ISO code of the country whose visitors you want to block (for example, AQ for Antarctica).

  3. Run the following command to check that the modified templates are valid PHP files:

    php -l nginxDomainVirtualHost.php
    
  4. Run the following command to generate new configuration files:

    plesk sbin httpdmng --reconfigure-all
    

Visitors from the country whose ISO code you have specified no longer have access to all websites hosted on the server.

Protecting a Website From Brute-force Attacks From the Same Country

You can protect your website from brute-force attacks by limiting requests from IP addresses that have the same ISO country code. You can apply this protection to the following:

  • A single website
  • All websites that belong to one hosting plan
  • All websites hosted on the server
  • One or multiple web pages (for example, example.com/test)

To protect one or multiple websites from brute-force attacks from the same country:

  1. Add the directive of the following pattern to the /etc/nginx/conf.d/limit_req_zone.conf file:

    limit_req_zone $geoip_data_country_code zone=country_code:10m rate=5r/m;
    

    This creates a memory zone shared among nginx worker processes. The zone stores the state of each IP address and how often it has accessed a request‑limited URL. The directive above limits requests from IP addresses with the same ISO country code to five per minute (rate=5r/m).

    Learn more about rate limiting in nginx.

  2. The second step varies depending on which and how many websites you want to protect:

    • (A single website) Go to Websites & Domains > domain > the “Hosting & DNS” tab > Apache & nginx Settings, put the following in the “Additional nginx directives” textbox, and then click OK:

      limit_req zone=country_code;
      
    • (All websites that belong to one hosting plan) Go to Service Plans and click the name of the service plan whose websites you want to protect. Then go to the “Web Server” tab, add the following to the “Additional nginx directives” textbox, and click OK:

      limit_req zone=country_code;
      
    • (All websites hosted on the server) Put the following to the /etc/nginx/conf.d/limit_req.conf file:

      limit_req zone=country_code;
      

You have limited requests to one or multiple websites from IP addresses with the same country ISO code to five per minute.

You can also protect a single or multiple web pages by limiting requests from IP addresses that have the same ISO country code. The procedure differs depending on your website hosting type:

  • Apache+nginx hosting
  • nginx-only hosting
  • nginx configured to serve PHP directly

(Apache+nginx hosting) To protect a particular web page from brute-force attacks from the same country:

  1. Add the directive of the following pattern to the /etc/nginx/conf.d/limit_req_zone.conf file:

    limit_req_zone $geoip_data_country_code zone=country_code:10m rate=5r/m;
    

    This creates a memory zone shared among nginx worker processes. The zone stores the state of each IP address and how often it has accessed a request‑limited URL. The directive above limits requests from IP addresses with the same ISO country code to five per minute (rate=5r/m).

    Learn more about rate limiting in nginx.

  2. Create a custom configuration template nginxDomainVirtualHost.php using this procedure.

  3. Find the following text at the end of the copied default template:

    <?php if ($VAR->domain->physicalHosting->proxySettings['nginxProxyMode']): ?>
        location / {
        <?php if ($VAR->domain->physicalHosting->scriptTimeout): ?>
            proxy_read_timeout <?php echo min($VAR->domain->physicalHosting->scriptTimeout, 2147483) ?>;
        <?php endif ?>
        <?php echo $VAR->includeTemplate('domain/service/proxy.php', $OPT) ?>
        }
    

    And insert your directives after it as follows replacing example.com with your domain name and /test—with the exact web page you want to apply the limit to:

    <?php if ($VAR->domain->physicalHosting->proxySettings['nginxProxyMode']): ?>
        location / {
        <?php if ($VAR->domain->physicalHosting->scriptTimeout): ?>
            proxy_read_timeout <?php echo min($VAR->domain->physicalHosting->scriptTimeout, 2147483) ?>;
        <?php endif ?>
        <?php echo $VAR->includeTemplate('domain/service/proxy.php', $OPT) ?>
        }
    
        <?php if ($VAR->domain->asciiName == 'example.com'): ?>
            location = /test {
                limit_req zone=country_code;
            <?php if ($VAR->domain->physicalHosting->scriptTimeout): ?>
                proxy_read_timeout <?php echo min($VAR->domain->physicalHosting->scriptTimeout, 2147483) ?>;
            <?php endif ?>
            <?php echo $VAR->includeTemplate('domain/service/proxy.php', $OPT) ?>
            }
        <?php endif ?>
    
  4. Run the following command to check that the modified templates are valid PHP files:

    php -l nginxDomainVirtualHost.php
    
  5. Run the following command to generate new configuration files:

    plesk sbin httpdmng --reconfigure-all
    

You have limited requests to the web page from IP addresses with the same country ISO code to 5 per minute.

(nginx-only hosting) To protect a particular web page from brute-force attacks from the same country:

  1. Add the directive of the following pattern to the /etc/nginx/conf.d/limit_req_zone.conf file:

    limit_req_zone $geoip_data_country_code zone=country_code:10m rate=5r/m;
    

    This creates a memory zone shared among nginx worker processes. The zone stores the state of each IP address and how often it has accessed a request‑limited URL. The directive above limits requests from IP addresses with the same ISO country code to five per minute (rate=5r/m).

    Learn more about rate limiting in nginx.

  2. Go to Websites & Domains > domain > the “Hosting & DNS” tab > Apache & nginx Settings.

  3. Put the following in the “Additional nginx directives” textbox replacing /test with the exact web page you want to apply the limit to:

    location = /test {
        limit_req zone=country_code;
    }
    
  4. Click OK.

You have limited requests to the web page from IP addresses with the same country ISO code to 5 per minute.

(nginx serves PHP directly) To protect a particular PHP script from brute-force attacks from the same country:

  1. Add the directive of the following pattern to the /etc/nginx/conf.d/limit_req_zone.conf file:

    limit_req_zone $geoip_data_country_code zone=country_code:10m rate=5r/m;
    

    This creates a memory zone shared among nginx worker processes. The zone stores the state of each IP address and how often it has accessed a request‑limited URL. The directive above limits requests from IP addresses with the same ISO country code to five per minute (rate=5r/m).

    Learn more about rate limiting in nginx.

  2. Create a custom configuration template nginxDomainVirtualHost.php using this procedure.

  3. Find the following text at the end of the copied default template:

    location ~ \.php(/.*)?$ {
        <?php if ($VAR->domain->physicalHosting->scriptTimeout): ?>
        fastcgi_read_timeout <?php echo min($VAR->domain->physicalHosting->scriptTimeout, 2147483) ?>;
        <?php endif ?>
        <?php echo $VAR->includeTemplate('domain/service/fpm.php', $OPT) ?>
    }
    

    And insert the following directives before the text including limit_req and replacing example.com with your domain name and /test\.php—with the exact PHP script you want to apply the limit to:

    <?php if ($VAR->domain->asciiName == 'example.com'): ?>
        location ~ ^/test\.php$ {
            limit_req zone=country_code;
            <?php if ($VAR->domain->physicalHosting->scriptTimeout): ?>
            fastcgi_read_timeout <?php echo min($VAR->domain->physicalHosting->scriptTimeout, 2147483) ?>;
            <?php endif ?>
            <?php echo $VAR->includeTemplate('domain/service/fpm.php', $OPT) ?>
        }
    <?php endif ?>
    location ~ \.php(/.*)?$ {
        <?php if ($VAR->domain->physicalHosting->scriptTimeout): ?>
        fastcgi_read_timeout <?php echo min($VAR->domain->physicalHosting->scriptTimeout, 2147483) ?>;
        <?php endif ?>
        <?php echo $VAR->includeTemplate('domain/service/fpm.php', $OPT) ?>
    }
    
  4. Run the following command to check that the modified templates are valid PHP files:

    php -l nginxDomainVirtualHost.php
    
  5. Run the following command to generate new configuration files:

    plesk sbin httpdmng --reconfigure-all
    

You have limited requests to the PHP script from IP addresses with the same country ISO code to 5 per minute.