Skip to main content

NGINX

GeoIP2 NGINX Rocky Linux 10: Geolocation Guide

by ,


We have by far the largest RPM repository with NGINX module packages and VMODs for Varnish. If you want to install NGINX, Varnish, and lots of useful performance/security software with smooth yum upgrades for production use, this is the repository for you.
Active subscription is required.

GeoIP2 NGINX Rocky Linux 10 enables geographic-based access control, content customization, and analytics for your web applications. The GeoIP2 module reads MaxMind databases to determine visitor locations from their IP addresses, allowing you to serve localized content, block traffic from specific countries, or route users to regional servers.

This comprehensive guide shows you how to install and configure the GeoIP2 module for NGINX on Rocky Linux 10, AlmaLinux 10, and other Enterprise Linux 10 distributions. You will learn how to set up MaxMind databases, configure location-based routing, and implement geo-blocking. By the end, you will have GeoIP2 NGINX Rocky Linux 10 performing geolocation lookups on every request.

Why Use GeoIP2 with NGINX

The GeoIP2 module provides powerful geolocation capabilities directly in NGINX. Here are key use cases for GeoIP2 NGINX Rocky Linux 10:

  • Content localization: Serve region-specific content, currencies, or languages automatically
  • Geographic access control: Block or allow traffic from specific countries or regions
  • Load balancing: Route users to the nearest data center or server
  • Compliance: Restrict access to meet regulatory requirements (GDPR, data residency)
  • Analytics: Enrich access logs with geographic data for better insights
  • Fraud prevention: Flag or block requests from high-risk regions

The module supports both GeoIP2 and GeoLite2 databases from MaxMind, reading the highly efficient MMDB format for fast lookups with minimal memory usage.

Prerequisites

Before installing GeoIP2 NGINX Rocky Linux 10 packages, ensure you have:

  • Rocky Linux 10, AlmaLinux 10, RHEL 10, or Oracle Linux 10
  • Root or sudo access to the server
  • NGINX installed (or we will install it in this guide)
  • MaxMind account for database downloads (free registration)

The GetPageSpeed repository provides pre-built GeoIP2 modules that integrate seamlessly with the standard NGINX package.

Installation

Step 1: Configure GetPageSpeed Repository

The GetPageSpeed repository provides enterprise-grade NGINX modules including GeoIP2 for RHEL-based distributions. Install the repository:

sudo dnf -y install https://extras.getpagespeed.com/release-latest.rpm

Step 2: Install NGINX

If NGINX is not already installed, install it from the repository:

sudo dnf -y install nginx
sudo systemctl enable --now nginx

Step 3: Install GeoIP2 Module

Install the NGINX GeoIP2 module:

sudo dnf -y install nginx-module-geoip2

The installation provides two modules:

  • ngx_http_geoip2_module: For HTTP traffic geolocation
  • ngx_stream_geoip2_module: For TCP/UDP stream geolocation

After installation, you will see:

----------------------------------------------------------------------

The nginx-module-geoip2 package has been installed.
To enable this module, add the following to /etc/nginx/nginx.conf
and reload NGINX:

    load_module modules/ngx_http_geoip2_module.so;
    load_module modules/ngx_stream_geoip2_module.so;

----------------------------------------------------------------------

Step 4: Install MaxMind Library

The libmaxminddb library is required for reading MMDB database files:

sudo dnf -y install libmaxminddb

Step 5: Obtain MaxMind Databases

MaxMind provides two database types:

  • GeoLite2: Free databases with country and city data
  • GeoIP2: Commercial databases with higher accuracy

To download GeoLite2 databases, register for a free account at maxmind.com, then:

# Create database directory
sudo mkdir -p /usr/share/GeoIP

# Download using your MaxMind license key
cd /usr/share/GeoIP
sudo curl -O "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key=YOUR_LICENSE_KEY&suffix=tar.gz"
sudo curl -O "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&license_key=YOUR_LICENSE_KEY&suffix=tar.gz"

# Extract databases
sudo tar -xzf GeoLite2-Country*.tar.gz --strip-components=1
sudo tar -xzf GeoLite2-City*.tar.gz --strip-components=1

Alternatively, use the official GeoIP update tool:

sudo dnf -y install geoipupdate

# Configure /etc/GeoIP.conf with your credentials
sudo geoipupdate

Step 6: Enable the Module

Add the module loading directive at the top of your NGINX configuration:

# /etc/nginx/nginx.conf
load_module modules/ngx_http_geoip2_module.so;

user nginx;
worker_processes auto;
# ... rest of configuration

Basic Configuration

Define GeoIP2 Database

Configure the database path and define variables in the http block:

http {
    # Load GeoIP2 database
    geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
        auto_reload 60m;
        $geoip2_metadata_country_build metadata build_epoch;
        $geoip2_data_country_code default=XX source=$remote_addr country iso_code;
        $geoip2_data_country_name country names en;
    }

    # ... rest of configuration
}

Configuration Directives Explained

geoip2 defines a database and its variables:

geoip2 /path/to/database.mmdb {
    $variable_name path to data;
}

auto_reload enables automatic database reloading:

auto_reload 60m;  # Reload every 60 minutes

source specifies the IP address source (useful for proxied requests):

$geoip2_data_country_code source=$http_x_forwarded_for country iso_code;

default sets a fallback value when lookup fails:

$geoip2_data_country_code default=US country iso_code;

Available Data Fields

For GeoLite2-Country database:

  • country iso_code – Two-letter country code (US, GB, DE)
  • country names en – Country name in English
  • continent code – Continent code (NA, EU, AS)
  • registered_country iso_code – Registered country code

For GeoLite2-City database (additional fields):

  • city names en – City name
  • subdivisions 0 iso_code – State/province code
  • subdivisions 0 names en – State/province name
  • location latitude – Latitude
  • location longitude – Longitude
  • location time_zone – Time zone

Common Configuration Examples

Country-Based Access Control

Block traffic from specific countries:

http {
    geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
        $geoip2_data_country_code country iso_code;
    }

    # Map blocked countries
    map $geoip2_data_country_code $blocked_country {
        default 0;
        CN 1;  # China
        RU 1;  # Russia
        KP 1;  # North Korea
    }

    server {
        listen 80;

        if ($blocked_country) {
            return 403;
        }

        location / {
            root /usr/share/nginx/html;
        }
    }
}

Allow Only Specific Countries

Whitelist approach for restricting access:

map $geoip2_data_country_code $allowed_country {
    default 0;
    US 1;
    CA 1;
    GB 1;
    DE 1;
}

server {
    listen 80;

    if ($allowed_country = 0) {
        return 403;
    }

    # ... rest of configuration
}

Geographic Load Balancing

Route users to regional servers:

http {
    geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
        $geoip2_data_continent_code continent code;
    }

    # Select upstream based on continent
    map $geoip2_data_continent_code $backend {
        default us_backend;
        EU eu_backend;
        AS asia_backend;
    }

    upstream us_backend {
        server us1.example.com;
        server us2.example.com;
    }

    upstream eu_backend {
        server eu1.example.com;
        server eu2.example.com;
    }

    upstream asia_backend {
        server asia1.example.com;
        server asia2.example.com;
    }

    server {
        listen 80;

        location / {
            proxy_pass http://$backend;
        }
    }
}

Adding Geolocation to Logs

Enrich access logs with geographic data:

http {
    geoip2 /usr/share/GeoIP/GeoLite2-City.mmdb {
        $geoip2_data_country_code country iso_code;
        $geoip2_data_city_name city names en;
    }

    log_format geo '$remote_addr - $remote_user [$time_local] '
                   '"$request" $status $body_bytes_sent '
                   '"$http_referer" "$http_user_agent" '
                   '$geoip2_data_country_code $geoip2_data_city_name';

    access_log /var/log/nginx/access.log geo;
}

Content Localization

Serve different content based on location:

http {
    geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
        $geoip2_data_country_code country iso_code;
    }

    server {
        listen 80;

        location / {
            root /usr/share/nginx/html/$geoip2_data_country_code;
            try_files $uri $uri/ /default$uri /default/index.html;
        }
    }
}

Handling Proxied Requests

When NGINX is behind a reverse proxy or load balancer, use the X-Forwarded-For header:

geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
    $geoip2_data_country_code source=$http_x_forwarded_for country iso_code;
}

For multiple proxy layers, extract the original client IP:

# Get the first IP from X-Forwarded-For
map $http_x_forwarded_for $client_ip {
    default $remote_addr;
    ~^(?P<first_ip>[^,]+) $first_ip;
}

geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
    $geoip2_data_country_code source=$client_ip country iso_code;
}

Automatic Database Updates

Set up automatic GeoIP database updates using geoipupdate:

# Install geoipupdate
sudo dnf -y install geoipupdate

# Configure credentials
sudo tee /etc/GeoIP.conf > /dev/null << 'EOF'
AccountID YOUR_ACCOUNT_ID
LicenseKey YOUR_LICENSE_KEY
EditionIDs GeoLite2-Country GeoLite2-City
DatabaseDirectory /usr/share/GeoIP
EOF

# Initial download
sudo geoipupdate

# Add weekly cron job
echo "0 3 * * 0 root /usr/bin/geoipupdate" | sudo tee /etc/cron.d/geoipupdate

NGINX reloads the database automatically when auto_reload is configured.

Verification

After configuring GeoIP2 NGINX Rocky Linux 10, verify the setup.

Test Configuration

sudo nginx -t

Check Variable Values

Add a test location to expose geolocation data:

location /geotest {
    default_type text/plain;
    return 200 "Country: $geoip2_data_country_code\nCity: $geoip2_data_city_name\n";
}

Test with curl:

curl http://localhost/geotest

Test with Specific IP

Use the source directive to test with a known IP:

# Temporary test configuration
geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
    $geoip2_test source=8.8.8.8 country iso_code;  # Google DNS (US)
}

Troubleshooting

Database Not Found

Symptom: geoip2: cannot open database

Solutions:

  1. Verify database path exists: ls -la /usr/share/GeoIP/
  2. Check file permissions: chmod 644 /usr/share/GeoIP/*.mmdb
  3. Ensure SELinux allows access

Variable Always Empty

Symptom: GeoIP variables return empty values

Solutions:

  1. Verify database contains data for the IP range
  2. Check the variable path matches database structure
  3. Test with a known public IP, not localhost

Lookup Performance

For high-traffic sites, consider these optimizations:

  1. Use SSD storage for database files
  2. Ensure sufficient memory for database caching
  3. Use country-only database if city data is not needed

SELinux Compatibility

The nginx-module-geoip2 package from GetPageSpeed works correctly with SELinux. Ensure database files have the correct context:

sudo restorecon -Rv /usr/share/GeoIP/

Complete Production Configuration

Here is a complete GeoIP2 NGINX Rocky Linux 10 configuration:

# /etc/nginx/nginx.conf
load_module modules/ngx_http_geoip2_module.so;

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    # GeoIP2 database configuration
    geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
        auto_reload 60m;
        $geoip2_data_country_code default=XX country iso_code;
        $geoip2_data_country_name country names en;
    }

    # Geo-enhanced log format
    log_format geo_combined '$remote_addr - $remote_user [$time_local] '
                            '"$request" $status $body_bytes_sent '
                            '"$http_referer" "$http_user_agent" '
                            '$geoip2_data_country_code';

    access_log /var/log/nginx/access.log geo_combined;

    sendfile on;
    keepalive_timeout 65;

    server {
        listen 80;
        server_name example.com;

        # Add country code header for debugging
        add_header X-Country-Code $geoip2_data_country_code;

        location / {
            root /usr/share/nginx/html;
            index index.html;
        }
    }
}

Test and apply:

sudo nginx -t && sudo systemctl reload nginx

For more NGINX configuration guides:

Conclusion

GeoIP2 NGINX Rocky Linux 10 provides powerful geolocation capabilities for access control, content localization, and analytics. With the GetPageSpeed repository, installation is straightforward, and the module integrates seamlessly with standard NGINX packages.

The combination of the GeoIP2 module and MaxMind databases enables sophisticated location-based routing without application code changes. Whether you need to comply with regional regulations, optimize content delivery, or enhance security, GeoIP2 provides the tools to implement geographic policies at the web server level.

Remember to keep your MaxMind databases updated regularly for accurate geolocation results. The auto_reload feature and geoipupdate tool make this process automatic and reliable.

D

Danila Vershinin

Founder & Lead Engineer

NGINX configuration and optimizationLinux system administrationWeb performance engineering

10+ years NGINX experience • Maintainer of GetPageSpeed RPM repository • Contributor to open-source NGINX modules

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

This site uses Akismet to reduce spam. Learn how your comment data is processed.