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 Englishcontinent code– Continent code (NA, EU, AS)registered_country iso_code– Registered country code
For GeoLite2-City database (additional fields):
city names en– City namesubdivisions 0 iso_code– State/province codesubdivisions 0 names en– State/province namelocation latitude– Latitudelocation longitude– Longitudelocation 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:
- Verify database path exists:
ls -la /usr/share/GeoIP/ - Check file permissions:
chmod 644 /usr/share/GeoIP/*.mmdb - Ensure SELinux allows access
Variable Always Empty
Symptom: GeoIP variables return empty values
Solutions:
- Verify database contains data for the IP range
- Check the variable path matches database structure
- Test with a known public IP, not localhost
Lookup Performance
For high-traffic sites, consider these optimizations:
- Use SSD storage for database files
- Ensure sufficient memory for database caching
- 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
Related Articles
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.
