Introduction
GeoIP (Geolocation IP) is a database and technology that maps an IP address to a physical geographic location (country, region, or city). When a user visits your website, the server looks up their IP in a database to determine where they are physically connecting from. It is used for geoblocking or geographic filtering. For instance, you can configure your server to drop traffic or show a 404 Forbidden error if a request originates from a specific foreign country or if you only want traffic from local users.The safest, cleanest method to install GeoIP2 is to Download your exact matching Nginx source code to congfigure and compile GeoIP2 as a dynamic module (.so file). You will have to re-compile each time you upgrade nginx to a new version. I have written a script (located at the bottom of this page) that will re-compile using the correct Nginx version for you to run after an nginx upgrade.
Prerequisites:
Ubuntu 26.04 installed on a VPS or Bare-Metal hostNginx 1.14.0 or later
User with sudo privileges
Start the GeoIP2 set up:
Proceed as root for convenience otherwise most commands would have to be preceeded with ’sudo’.sudo -iAdd the required dependencies and repositories
apt-get update
apt-get install build-essential software-properties-common wget libmaxminddb0 libmaxminddb-dev mmdb-bin geoipupdate libpcre2 libpcre2-dev libssl-dev zlib1g-dev -yCreate a MaxMind Account
1. Go to the MaxMind Account Sign-Up page and create a free account.
2. Log in and go to Manage License Keys in the left-hand menu.
3. Click Generate new license key.IMPORTANT: This is the only time you will see the complete License Key.
4. Write down your Account ID and your new License Key.
Configure geoipupdate
Edit the GeoIP configuration file using your preferred text editor (e.g., nano ):sudo nano /etc/GeoIP.confReplace the placeholder texts with your Account ID and License Key. Update the EditionIDs line so you get both the City and Country databases:
AccountID YOUR_ACCOUNT_ID_HERE
LicenseKey YOUR_LICENSE_KEY_HERE
EditionIDs GeoLite2-City GeoLite2-Country
Save and close the file ( Ctrl+O , Enter , then Ctrl+X ).
Download the GeoIP2 Databases
Run the update command to fetch the latest .mmdb GeoIP databases:geoipupdate -v
geoipupdate -v shows the location of the downloaded GeoIP databases. Note the location for future use.
Create a workspace and download your exact matching Nginx source code
cd /opt/
mkdir -p /opt/nginx-upgrade
cd /opt/nginx-upgrade
Get your Nginx version:
nginx -v
Will return your version i.e.nginx version: nginx/1.31.2
Download the Nginx source code replacing 1.31.2 with your version number:
curl -O https://nginx.org/download/nginx-1.31.2.tar.gz
tar -zxf nginx-1.31.2.tar.gz
Clone the GeoIP2 module
git clone https://github.com/leev/ngx_http_geoip2_module.git
cd ngx_http_geoip2_module
git submodule update --init --recursive
cd /opt/nginx-upgrade
Configure and Compile
Replace 1.31.2 with your NGINX version number (from nginx -v)cd /opt/nginx-upgrade/nginx-1.31.2Run configure with the --add-dynamic-module flag appended to your configuration:
./configure --with-compat --add-dynamic-module=../ngx_http_geoip2_module
Note: Using --with-compat ensures binary compatibility with official Nginx packages.Important If you are re-running configure after fixing an error, run the following [make clean] command to remove previous configurations
make clean
Compile only the module:
make modulesCopy the freshly compiled .so files into your system’s Nginx modules directory:
mkdir -p /etc/nginx/modules
cp objs/ngx_http_geoip2_module.so /etc/nginx/modules/
Add GeoIP2 to nginx.conf
Edit nginx.confsudo nano /etc/nginx/confAdd this to the top line
load_module modules/ngx_http_geoip2_module.so;Place this in your http block
# Load GeoIP2 Country Database
geoip2 /var/lib/GeoIP/GeoLite2-Country.mmdb {
auto_reload 60m;
$geoip2_data_country_iso_code country iso_code;
$geoip2_data_country_name country names en;
}
# Load GeoIP2 City database
geoip2 /var/lib/GeoIP/GeoLite2-City.mmdb {
auto_reload 60m;
$geoip2_city_name city names en;
$geoip2_data_region_iso_code subdivisions 0 iso_code;
}
You can allow private or local IP addresses {like LAN, VPN, or Docker ranges} to bypass your GeoIP country check, use Nginx’s geo module. This creates an IP-based variable that you can chain with your country variable to form a whitelist. Define the allowed networks in the http block of your nginx.conf:
Define your private IP networks
geo $is_local_ip {
default 0;
127.0.0.1 1; # localhost
192.168.1.0/24 1; # Private LAN
10.0.0.0/8 1; # Private LAN
172.16.0.0/12 1; # Docker/Private network
}
Define your allowed countries (using standard ISO codes)
In the http block of your nginx.confmap $geoip_country_code $allowed_country {
default no;
US yes;
CA yes;
}Then, use a conditional if check or a map combination inside your website server block to enforce it:
#Combine your local IP and country checks
if ($is_local_ip = 1) {
set $allowed_country yes;
}
# Block access if the country code is not whitelisted
if ($allowed_country = no) {
return 403
}
Test and re-start Nginx
nginx -t
systemctl restart nginxTo check the status of your GeoIP $allowed_country from the Ubuntu terminal, you can test a specific IP against your local database using mmdblookup (for .mmdb MaxMind databases).
Run the lookup command:
mmdblookup --file /var/lib/GeoIP/GeoLite2-Country.mmdb --ip 8.8.8.8 country iso_code
Script to re-compile the ngx_http_geoip2_module
To be run after an nginx upgrade.(It will automatically get the right version of the GeoIP2 NGINX module)#!/bin/bash
################
# To be run after an nginx upgrade.(it will automatically get the right version of the GeoIP2 NGINX module)
# Build against a specific nginx.org NGINX version (nginx -v).
# Intended to run inside an Ubuntu container
# matching the target distribution.
# Compiles GeoIP2 as a dynamic module (.so file)
#
# Must be run as root
if ! id | grep -q "uid=0(root)"; then
echo "Must be run as root"
exit 1
fi
# Make executable ##
# cd /opt/nginx-upgrade
# chmod +x nginx_geoip_update.sh
## Run ##
# ./nginx_geoip_update.sh
##
cd /opt/
if [ ! -d /opt/nginx-upgrade ]; then
mkdir -p /opt/nginx-upgrade
fi
cd /opt/nginx-upgrade
# Set log file
scriptdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
logname=`basename "$0"`
logname+=".log"
logfile=$scriptdir/$logname
touch "$logfile"
# Functions
logger(){
echo "$(date): $@" >> $logfile
echo "## $@"
}
logger "Starting script"
# Best practice settings for running bash scripts:
# Exit the script when an error is encountered
set -o errexit
# Exit the script when a pipe operation fails
set -o pipefail
# Exit the script when there are undeclared variables
set -o nounset
# Uncomment this to see a log to the screen of each command run in the script
# set -o xtrace
# Credit: nginx.org 2020-10-05 https://gist.github.com/nginx-gists/bdc7da70b124c4f3e472970c7826cccc
# Back up Your Current Configuration
cp -r /etc/nginx /etc/nginx_backup
# Prerequisites
apt-get -qq update
apt-get -qq install -y \
libpcre2 \
libpcre2-dev \
libssl-dev \
zlib1g-dev \
libmaxminddb0 \
libmaxminddb-dev \
mmdb-bin
# Install the module
## Get installed Nginx version number
NGINX_VER=$(nginx -v |& sed 's/nginx version: nginx\///' | sed 's/\s.*$//')
# Create a workspace and download the exact matching Nginx ${NGINX_VER} source code:
cd /opt/
if [ ! -d /opt/nginx-upgrade ]; then
mkdir -p /opt/nginx-upgrade
fi
cd /opt/nginx-upgrade
if [ ! -f /opt/nginx-upgrade/nginx-${NGINX_VER}/configure ]; then
curl -O https://nginx.org/download/nginx-${NGINX_VER}.tar.gz
tar -zxf nginx-${NGINX_VER}.tar.gz
logger "nginx-${NGINX_VER} source downloaded"
fi
# Clone Module Repositories
# Download the source code for the Brotli GeoIP2 ModSecurity-nginx modules into your workspace.
# delete previous clone directory
if [ -d /opt/nginx-upgrade/ngx_http_geoip2_module ]; then
rm -r /opt/nginx-upgrade/ngx_http_geoip2_module
fi
# Clone GeoIP2 module
git clone https://github.com/leev/ngx_http_geoip2_module.git
cd ngx_http_geoip2_module
git submodule update --init --recursive
cd /opt/nginx-upgrade
logger "GeoIP2 module cloned"
# Configure and Compile Dynamic Module
cd /opt/nginx-upgrade/nginx-${NGINX_VER}
# Remove previous configs
if [ -d /opt/nginx-upgrade/nginx-${NGINX_VER}/objs ]; then
make clean
logger "make clean invoked"
fi
# Run configure with the --add-dynamic-module flags appended to your configuration:
./configure --with-compat --add-dynamic-module=../ngx_http_geoip2_module
logger "GeoIP2 dynamic module completed"
# Compile only the modules:
make modules
logger "GeoIP2 module compiled"
# Copy the freshly compiled .so files into your system’s Nginx modules directory:
if [ ! -d /etc/nginx/modules/ ]; then
mkdir -p /etc/nginx/modules
fi
cp objs/ngx_http_geoip2_module.so /etc/nginx/modules/
logger "GeoIP2 dynamic module copied to /etc/nginx/modules/"
# Verify
# nginx -t
if [ "$(command nginx -t) | grep 'ok'" ]; then
logger "Nginx configuration ok, reloading.."
systemctl reload nginx
else
logger "Nginx errors"
fi
Download Script
Download nginx_geoip_update.tgz rawIntroduction
GeoIP (Geolocation IP) is a database and technology that maps an IP address to a physical geographic location (country, region, or city). When a user visits your website, the server looks up their IP in a database to determine where they are physically connecting from. It is used for geoblocking or geographic filtering. For instance, you can configure your server to drop traffic or show a 404 Forbidden error if a request originates from a specific foreign country or if you only want traffic from local users.The safest, cleanest method to install GeoIP2 is to Download your exact matching Nginx source code to congfigure and compile GeoIP2 as a dynamic module (.so file). You will have to re-compile each time you upgrade nginx to a new version. I have written a script (located at the bottom of this page) that will re-compile using the correct Nginx version for you to run after an nginx upgrade.
Prerequisites:
Ubuntu 26.04 installed on a VPS or Bare-Metal hostNginx 1.14.0 or later
User with sudo privileges
Start the GeoIP2 set up:
Proceed as root for convenience otherwise most commands would have to be preceeded with ’sudo’.sudo -iAdd the required dependencies and repositories
apt-get update
apt-get install build-essential software-properties-common wget libmaxminddb0 libmaxminddb-dev mmdb-bin geoipupdate libpcre2 libpcre2-dev libssl-dev zlib1g-dev -yCreate a MaxMind Account
1. Go to the MaxMind Account Sign-Up page and create a free account.
2. Log in and go to Manage License Keys in the left-hand menu.
3. Click Generate new license key.IMPORTANT: This is the only time you will see the complete License Key.
4. Write down your Account ID and your new License Key.
Configure geoipupdate
Edit the GeoIP configuration file using your preferred text editor (e.g., nano ):sudo nano /etc/GeoIP.confReplace the placeholder texts with your Account ID and License Key. Update the EditionIDs line so you get both the City and Country databases:
AccountID YOUR_ACCOUNT_ID_HERE
LicenseKey YOUR_LICENSE_KEY_HERE
EditionIDs GeoLite2-City GeoLite2-Country
Save and close the file ( Ctrl+O , Enter , then Ctrl+X ).
Download the GeoIP2 Databases
Run the update command to fetch the latest .mmdb GeoIP databases:geoipupdate -v
geoipupdate -v shows the location of the downloaded GeoIP databases. Note the location for future use.
Create a workspace and download your exact matching Nginx source code
cd /opt/
mkdir -p /opt/nginx-upgrade
cd /opt/nginx-upgrade
Get your Nginx version:
nginx -v
Will return your version i.e.nginx version: nginx/1.31.2
Download the Nginx source code replacing 1.31.2 with your version number:
curl -O https://nginx.org/download/nginx-1.31.2.tar.gz
tar -zxf nginx-1.31.2.tar.gz
Clone the GeoIP2 module
git clone https://github.com/leev/ngx_http_geoip2_module.git
cd ngx_http_geoip2_module
git submodule update --init --recursive
cd /opt/nginx-upgrade
Configure and Compile
Replace 1.31.2 with your NGINX version number (from nginx -v)cd /opt/nginx-upgrade/nginx-1.31.2Run configure with the --add-dynamic-module flag appended to your configuration:
./configure --with-compat --add-dynamic-module=../ngx_http_geoip2_module
Note: Using --with-compat ensures binary compatibility with official Nginx packages.Important If you are re-running configure after fixing an error, run the following [make clean] command to remove previous configurations
make clean
Compile only the module:
make modulesCopy the freshly compiled .so files into your system’s Nginx modules directory:
mkdir -p /etc/nginx/modules
cp objs/ngx_http_geoip2_module.so /etc/nginx/modules/
Add GeoIP2 to nginx.conf
Edit nginx.confsudo nano /etc/nginx/confAdd this to the top line
load_module modules/ngx_http_geoip2_module.so;Place this in your http block
# Load GeoIP2 Country Database
geoip2 /var/lib/GeoIP/GeoLite2-Country.mmdb {
auto_reload 60m;
$geoip2_data_country_iso_code country iso_code;
$geoip2_data_country_name country names en;
}
# Load GeoIP2 City database
geoip2 /var/lib/GeoIP/GeoLite2-City.mmdb {
auto_reload 60m;
$geoip2_city_name city names en;
$geoip2_data_region_iso_code subdivisions 0 iso_code;
}
You can allow private or local IP addresses {like LAN, VPN, or Docker ranges} to bypass your GeoIP country check, use Nginx’s geo module. This creates an IP-based variable that you can chain with your country variable to form a whitelist. Define the allowed networks in the http block of your nginx.conf:
Define your private IP networks
geo $is_local_ip {
default 0;
127.0.0.1 1; # localhost
192.168.1.0/24 1; # Private LAN
10.0.0.0/8 1; # Private LAN
172.16.0.0/12 1; # Docker/Private network
}
Define your allowed countries (using standard ISO codes)
In the http block of your nginx.confmap $geoip_country_code $allowed_country {
default no;
US yes;
CA yes;
}Then, use a conditional if check or a map combination inside your website server block to enforce it:
#Combine your local IP and country checks
if ($is_local_ip = 1) {
set $allowed_country yes;
}
# Block access if the country code is not whitelisted
if ($allowed_country = no) {
return 403
}
Test and re-start Nginx
nginx -t
systemctl restart nginxTo check the status of your GeoIP $allowed_country from the Ubuntu terminal, you can test a specific IP against your local database using mmdblookup (for .mmdb MaxMind databases).
Run the lookup command:
mmdblookup --file /var/lib/GeoIP/GeoLite2-Country.mmdb --ip 8.8.8.8 country iso_code
Script to re-compile the ngx_http_geoip2_module
To be run after an nginx upgrade.(It will automatically get the right version of the GeoIP2 NGINX module)#!/bin/bash
################
# To be run after an nginx upgrade.(it will automatically get the right version of the GeoIP2 NGINX module)
# Build against a specific nginx.org NGINX version (nginx -v).
# Intended to run inside an Ubuntu container
# matching the target distribution.
# Compiles GeoIP2 as a dynamic module (.so file)
#
# Must be run as root
if ! id | grep -q "uid=0(root)"; then
echo "Must be run as root"
exit 1
fi
# Make executable ##
# cd /opt/nginx-upgrade
# chmod +x nginx_geoip_update.sh
## Run ##
# ./nginx_geoip_update.sh
##
cd /opt/
if [ ! -d /opt/nginx-upgrade ]; then
mkdir -p /opt/nginx-upgrade
fi
cd /opt/nginx-upgrade
# Set log file
scriptdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
logname=`basename "$0"`
logname+=".log"
logfile=$scriptdir/$logname
touch "$logfile"
# Functions
logger(){
echo "$(date): $@" >> $logfile
echo "## $@"
}
logger "Starting script"
# Best practice settings for running bash scripts:
# Exit the script when an error is encountered
set -o errexit
# Exit the script when a pipe operation fails
set -o pipefail
# Exit the script when there are undeclared variables
set -o nounset
# Uncomment this to see a log to the screen of each command run in the script
# set -o xtrace
# Credit: nginx.org 2020-10-05 https://gist.github.com/nginx-gists/bdc7da70b124c4f3e472970c7826cccc
# Back up Your Current Configuration
cp -r /etc/nginx /etc/nginx_backup
# Prerequisites
apt-get -qq update
apt-get -qq install -y \
libpcre2 \
libpcre2-dev \
libssl-dev \
zlib1g-dev \
libmaxminddb0 \
libmaxminddb-dev \
mmdb-bin
# Install the module
## Get installed Nginx version number
NGINX_VER=$(nginx -v |& sed 's/nginx version: nginx\///' | sed 's/\s.*$//')
# Create a workspace and download the exact matching Nginx ${NGINX_VER} source code:
cd /opt/
if [ ! -d /opt/nginx-upgrade ]; then
mkdir -p /opt/nginx-upgrade
fi
cd /opt/nginx-upgrade
if [ ! -f /opt/nginx-upgrade/nginx-${NGINX_VER}/configure ]; then
curl -O https://nginx.org/download/nginx-${NGINX_VER}.tar.gz
tar -zxf nginx-${NGINX_VER}.tar.gz
logger "nginx-${NGINX_VER} source downloaded"
fi
# Clone Module Repositories
# Download the source code for the Brotli GeoIP2 ModSecurity-nginx modules into your workspace.
# delete previous clone directory
if [ -d /opt/nginx-upgrade/ngx_http_geoip2_module ]; then
rm -r /opt/nginx-upgrade/ngx_http_geoip2_module
fi
# Clone GeoIP2 module
git clone https://github.com/leev/ngx_http_geoip2_module.git
cd ngx_http_geoip2_module
git submodule update --init --recursive
cd /opt/nginx-upgrade
logger "GeoIP2 module cloned"
# Configure and Compile Dynamic Module
cd /opt/nginx-upgrade/nginx-${NGINX_VER}
# Remove previous configs
if [ -d /opt/nginx-upgrade/nginx-${NGINX_VER}/objs ]; then
make clean
logger "make clean invoked"
fi
# Run configure with the --add-dynamic-module flags appended to your configuration:
./configure --with-compat --add-dynamic-module=../ngx_http_geoip2_module
logger "GeoIP2 dynamic module completed"
# Compile only the modules:
make modules
logger "GeoIP2 module compiled"
# Copy the freshly compiled .so files into your system’s Nginx modules directory:
if [ ! -d /etc/nginx/modules/ ]; then
mkdir -p /etc/nginx/modules
fi
cp objs/ngx_http_geoip2_module.so /etc/nginx/modules/
logger "GeoIP2 dynamic module copied to /etc/nginx/modules/"
# Verify
# nginx -t
if [ "$(command nginx -t) | grep 'ok'" ]; then
logger "Nginx configuration ok, reloading.."
systemctl reload nginx
else
logger "Nginx errors"
fi
Download Script
Download nginx_geoip_update.tgz rawTotal Views: 937Daily Views: 14
Introduction
GeoIP (Geolocation IP) is a database and technology that maps an IP address to a physical geographic location (country, region, or city). When a user visits your website, the server looks up their IP in a database to determine where they are physically connecting from. It is used for geoblocking or geographic filtering. For instance, you can configure your server to drop traffic or show a 404 Forbidden error if a request originates from a specific foreign country or if you only want traffic from local users.The safest, cleanest method to install GeoIP2 is to Download your exact matching Nginx source code to congfigure and compile GeoIP2 as a dynamic module (.so file). You will have to re-compile each time you upgrade nginx to a new version. I have written a script (located at the bottom of this page) that will re-compile using the correct Nginx version for you to run after an nginx upgrade.
Prerequisites:
Ubuntu 26.04 installed on a VPS or Bare-Metal hostNginx 1.14.0 or later
User with sudo privileges
Start the GeoIP2 set up:
Proceed as root for convenience otherwise most commands would have to be preceeded with ’sudo’.sudo -iAdd the required dependencies and repositories
apt-get update
apt-get install build-essential software-properties-common wget libmaxminddb0 libmaxminddb-dev mmdb-bin geoipupdate libpcre2 libpcre2-dev libssl-dev zlib1g-dev -yCreate a MaxMind Account
1. Go to the MaxMind Account Sign-Up page and create a free account.
2. Log in and go to Manage License Keys in the left-hand menu.
3. Click Generate new license key.IMPORTANT: This is the only time you will see the complete License Key.
4. Write down your Account ID and your new License Key.
Configure geoipupdate
Edit the GeoIP configuration file using your preferred text editor (e.g., nano ):sudo nano /etc/GeoIP.confReplace the placeholder texts with your Account ID and License Key. Update the EditionIDs line so you get both the City and Country databases:
AccountID YOUR_ACCOUNT_ID_HERE
LicenseKey YOUR_LICENSE_KEY_HERE
EditionIDs GeoLite2-City GeoLite2-Country
Save and close the file ( Ctrl+O , Enter , then Ctrl+X ).
Download the GeoIP2 Databases
Run the update command to fetch the latest .mmdb GeoIP databases:geoipupdate -v
geoipupdate -v shows the location of the downloaded GeoIP databases. Note the location for future use.
Create a workspace and download your exact matching Nginx source code
cd /opt/
mkdir -p /opt/nginx-upgrade
cd /opt/nginx-upgrade
Get your Nginx version:
nginx -v
Will return your version i.e.nginx version: nginx/1.31.2
Download the Nginx source code replacing 1.31.2 with your version number:
curl -O https://nginx.org/download/nginx-1.31.2.tar.gz
tar -zxf nginx-1.31.2.tar.gz
Clone the GeoIP2 module
git clone https://github.com/leev/ngx_http_geoip2_module.git
cd ngx_http_geoip2_module
git submodule update --init --recursive
cd /opt/nginx-upgrade
Configure and Compile
Replace 1.31.2 with your NGINX version number (from nginx -v)cd /opt/nginx-upgrade/nginx-1.31.2Run configure with the --add-dynamic-module flag appended to your configuration:
./configure --with-compat --add-dynamic-module=../ngx_http_geoip2_module
Note: Using --with-compat ensures binary compatibility with official Nginx packages.Important If you are re-running configure after fixing an error, run the following [make clean] command to remove previous configurations
make clean
Compile only the module:
make modulesCopy the freshly compiled .so files into your system’s Nginx modules directory:
mkdir -p /etc/nginx/modules
cp objs/ngx_http_geoip2_module.so /etc/nginx/modules/
Add GeoIP2 to nginx.conf
Edit nginx.confsudo nano /etc/nginx/confAdd this to the top line
load_module modules/ngx_http_geoip2_module.so;Place this in your http block
# Load GeoIP2 Country Database
geoip2 /var/lib/GeoIP/GeoLite2-Country.mmdb {
auto_reload 60m;
$geoip2_data_country_iso_code country iso_code;
$geoip2_data_country_name country names en;
}
# Load GeoIP2 City database
geoip2 /var/lib/GeoIP/GeoLite2-City.mmdb {
auto_reload 60m;
$geoip2_city_name city names en;
$geoip2_data_region_iso_code subdivisions 0 iso_code;
}
You can allow private or local IP addresses {like LAN, VPN, or Docker ranges} to bypass your GeoIP country check, use Nginx’s geo module. This creates an IP-based variable that you can chain with your country variable to form a whitelist. Define the allowed networks in the http block of your nginx.conf:
Define your private IP networks
geo $is_local_ip {
default 0;
127.0.0.1 1; # localhost
192.168.1.0/24 1; # Private LAN
10.0.0.0/8 1; # Private LAN
172.16.0.0/12 1; # Docker/Private network
}
Define your allowed countries (using standard ISO codes)
In the http block of your nginx.confmap $geoip_country_code $allowed_country {
default no;
US yes;
CA yes;
}Then, use a conditional if check or a map combination inside your website server block to enforce it:
#Combine your local IP and country checks
if ($is_local_ip = 1) {
set $allowed_country yes;
}
# Block access if the country code is not whitelisted
if ($allowed_country = no) {
return 403
}
Test and re-start Nginx
nginx -t
systemctl restart nginxTo check the status of your GeoIP $allowed_country from the Ubuntu terminal, you can test a specific IP against your local database using mmdblookup (for .mmdb MaxMind databases).
Run the lookup command:
mmdblookup --file /var/lib/GeoIP/GeoLite2-Country.mmdb --ip 8.8.8.8 country iso_code
Script to re-compile the ngx_http_geoip2_module
To be run after an nginx upgrade.(It will automatically get the right version of the GeoIP2 NGINX module)#!/bin/bash
################
# To be run after an nginx upgrade.(it will automatically get the right version of the GeoIP2 NGINX module)
# Build against a specific nginx.org NGINX version (nginx -v).
# Intended to run inside an Ubuntu container
# matching the target distribution.
# Compiles GeoIP2 as a dynamic module (.so file)
#
# Must be run as root
if ! id | grep -q "uid=0(root)"; then
echo "Must be run as root"
exit 1
fi
# Make executable ##
# cd /opt/nginx-upgrade
# chmod +x nginx_geoip_update.sh
## Run ##
# ./nginx_geoip_update.sh
##
cd /opt/
if [ ! -d /opt/nginx-upgrade ]; then
mkdir -p /opt/nginx-upgrade
fi
cd /opt/nginx-upgrade
# Set log file
scriptdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
logname=`basename "$0"`
logname+=".log"
logfile=$scriptdir/$logname
touch "$logfile"
# Functions
logger(){
echo "$(date): $@" >> $logfile
echo "## $@"
}
logger "Starting script"
# Best practice settings for running bash scripts:
# Exit the script when an error is encountered
set -o errexit
# Exit the script when a pipe operation fails
set -o pipefail
# Exit the script when there are undeclared variables
set -o nounset
# Uncomment this to see a log to the screen of each command run in the script
# set -o xtrace
# Credit: nginx.org 2020-10-05 https://gist.github.com/nginx-gists/bdc7da70b124c4f3e472970c7826cccc
# Back up Your Current Configuration
cp -r /etc/nginx /etc/nginx_backup
# Prerequisites
apt-get -qq update
apt-get -qq install -y \
libpcre2 \
libpcre2-dev \
libssl-dev \
zlib1g-dev \
libmaxminddb0 \
libmaxminddb-dev \
mmdb-bin
# Install the module
## Get installed Nginx version number
NGINX_VER=$(nginx -v |& sed 's/nginx version: nginx\///' | sed 's/\s.*$//')
# Create a workspace and download the exact matching Nginx ${NGINX_VER} source code:
cd /opt/
if [ ! -d /opt/nginx-upgrade ]; then
mkdir -p /opt/nginx-upgrade
fi
cd /opt/nginx-upgrade
if [ ! -f /opt/nginx-upgrade/nginx-${NGINX_VER}/configure ]; then
curl -O https://nginx.org/download/nginx-${NGINX_VER}.tar.gz
tar -zxf nginx-${NGINX_VER}.tar.gz
logger "nginx-${NGINX_VER} source downloaded"
fi
# Clone Module Repositories
# Download the source code for the Brotli GeoIP2 ModSecurity-nginx modules into your workspace.
# delete previous clone directory
if [ -d /opt/nginx-upgrade/ngx_http_geoip2_module ]; then
rm -r /opt/nginx-upgrade/ngx_http_geoip2_module
fi
# Clone GeoIP2 module
git clone https://github.com/leev/ngx_http_geoip2_module.git
cd ngx_http_geoip2_module
git submodule update --init --recursive
cd /opt/nginx-upgrade
logger "GeoIP2 module cloned"
# Configure and Compile Dynamic Module
cd /opt/nginx-upgrade/nginx-${NGINX_VER}
# Remove previous configs
if [ -d /opt/nginx-upgrade/nginx-${NGINX_VER}/objs ]; then
make clean
logger "make clean invoked"
fi
# Run configure with the --add-dynamic-module flags appended to your configuration:
./configure --with-compat --add-dynamic-module=../ngx_http_geoip2_module
logger "GeoIP2 dynamic module completed"
# Compile only the modules:
make modules
logger "GeoIP2 module compiled"
# Copy the freshly compiled .so files into your system’s Nginx modules directory:
if [ ! -d /etc/nginx/modules/ ]; then
mkdir -p /etc/nginx/modules
fi
cp objs/ngx_http_geoip2_module.so /etc/nginx/modules/
logger "GeoIP2 dynamic module copied to /etc/nginx/modules/"
# Verify
# nginx -t
if [ "$(command nginx -t) | grep 'ok'" ]; then
logger "Nginx configuration ok, reloading.."
systemctl reload nginx
else
logger "Nginx errors"
fi
Download Script
Download nginx_geoip_update.tgz rawIntroduction
GeoIP (Geolocation IP) is a database and technology that maps an IP address to a physical geographic location (country, region, or city). When a user visits your website, the server looks up their IP in a database to determine where they are physically connecting from. It is used for geoblocking or geographic filtering. For instance, you can configure your server to drop traffic or show a 404 Forbidden error if a request originates from a specific foreign country or if you only want traffic from local users.The safest, cleanest method to install GeoIP2 is to Download your exact matching Nginx source code to congfigure and compile GeoIP2 as a dynamic module (.so file). You will have to re-compile each time you upgrade nginx to a new version. I have written a script (located at the bottom of this page) that will re-compile using the correct Nginx version for you to run after an nginx upgrade.
Prerequisites:
Ubuntu 26.04 installed on a VPS or Bare-Metal hostNginx 1.14.0 or later
User with sudo privileges
Start the GeoIP2 set up:
Proceed as root for convenience otherwise most commands would have to be preceeded with ’sudo’.sudo -iAdd the required dependencies and repositories
apt-get update
apt-get install build-essential software-properties-common wget libmaxminddb0 libmaxminddb-dev mmdb-bin geoipupdate libpcre2 libpcre2-dev libssl-dev zlib1g-dev -yCreate a MaxMind Account
1. Go to the MaxMind Account Sign-Up page and create a free account.
2. Log in and go to Manage License Keys in the left-hand menu.
3. Click Generate new license key.IMPORTANT: This is the only time you will see the complete License Key.
4. Write down your Account ID and your new License Key.
Configure geoipupdate
Edit the GeoIP configuration file using your preferred text editor (e.g., nano ):sudo nano /etc/GeoIP.confReplace the placeholder texts with your Account ID and License Key. Update the EditionIDs line so you get both the City and Country databases:
AccountID YOUR_ACCOUNT_ID_HERE
LicenseKey YOUR_LICENSE_KEY_HERE
EditionIDs GeoLite2-City GeoLite2-Country
Save and close the file ( Ctrl+O , Enter , then Ctrl+X ).
Download the GeoIP2 Databases
Run the update command to fetch the latest .mmdb GeoIP databases:geoipupdate -v
geoipupdate -v shows the location of the downloaded GeoIP databases. Note the location for future use.
Create a workspace and download your exact matching Nginx source code
cd /opt/
mkdir -p /opt/nginx-upgrade
cd /opt/nginx-upgrade
Get your Nginx version:
nginx -v
Will return your version i.e.nginx version: nginx/1.31.2
Download the Nginx source code replacing 1.31.2 with your version number:
curl -O https://nginx.org/download/nginx-1.31.2.tar.gz
tar -zxf nginx-1.31.2.tar.gz
Clone the GeoIP2 module
git clone https://github.com/leev/ngx_http_geoip2_module.git
cd ngx_http_geoip2_module
git submodule update --init --recursive
cd /opt/nginx-upgrade
Configure and Compile
Replace 1.31.2 with your NGINX version number (from nginx -v)cd /opt/nginx-upgrade/nginx-1.31.2Run configure with the --add-dynamic-module flag appended to your configuration:
./configure --with-compat --add-dynamic-module=../ngx_http_geoip2_module
Note: Using --with-compat ensures binary compatibility with official Nginx packages.Important If you are re-running configure after fixing an error, run the following [make clean] command to remove previous configurations
make clean
Compile only the module:
make modulesCopy the freshly compiled .so files into your system’s Nginx modules directory:
mkdir -p /etc/nginx/modules
cp objs/ngx_http_geoip2_module.so /etc/nginx/modules/
Add GeoIP2 to nginx.conf
Edit nginx.confsudo nano /etc/nginx/confAdd this to the top line
load_module modules/ngx_http_geoip2_module.so;Place this in your http block
# Load GeoIP2 Country Database
geoip2 /var/lib/GeoIP/GeoLite2-Country.mmdb {
auto_reload 60m;
$geoip2_data_country_iso_code country iso_code;
$geoip2_data_country_name country names en;
}
# Load GeoIP2 City database
geoip2 /var/lib/GeoIP/GeoLite2-City.mmdb {
auto_reload 60m;
$geoip2_city_name city names en;
$geoip2_data_region_iso_code subdivisions 0 iso_code;
}
You can allow private or local IP addresses {like LAN, VPN, or Docker ranges} to bypass your GeoIP country check, use Nginx’s geo module. This creates an IP-based variable that you can chain with your country variable to form a whitelist. Define the allowed networks in the http block of your nginx.conf:
Define your private IP networks
geo $is_local_ip {
default 0;
127.0.0.1 1; # localhost
192.168.1.0/24 1; # Private LAN
10.0.0.0/8 1; # Private LAN
172.16.0.0/12 1; # Docker/Private network
}
Define your allowed countries (using standard ISO codes)
In the http block of your nginx.confmap $geoip_country_code $allowed_country {
default no;
US yes;
CA yes;
}Then, use a conditional if check or a map combination inside your website server block to enforce it:
#Combine your local IP and country checks
if ($is_local_ip = 1) {
set $allowed_country yes;
}
# Block access if the country code is not whitelisted
if ($allowed_country = no) {
return 403
}
Test and re-start Nginx
nginx -t
systemctl restart nginxTo check the status of your GeoIP $allowed_country from the Ubuntu terminal, you can test a specific IP against your local database using mmdblookup (for .mmdb MaxMind databases).
Run the lookup command:
mmdblookup --file /var/lib/GeoIP/GeoLite2-Country.mmdb --ip 8.8.8.8 country iso_code
Script to re-compile the ngx_http_geoip2_module
To be run after an nginx upgrade.(It will automatically get the right version of the GeoIP2 NGINX module)#!/bin/bash
################
# To be run after an nginx upgrade.(it will automatically get the right version of the GeoIP2 NGINX module)
# Build against a specific nginx.org NGINX version (nginx -v).
# Intended to run inside an Ubuntu container
# matching the target distribution.
# Compiles GeoIP2 as a dynamic module (.so file)
#
# Must be run as root
if ! id | grep -q "uid=0(root)"; then
echo "Must be run as root"
exit 1
fi
# Make executable ##
# cd /opt/nginx-upgrade
# chmod +x nginx_geoip_update.sh
## Run ##
# ./nginx_geoip_update.sh
##
cd /opt/
if [ ! -d /opt/nginx-upgrade ]; then
mkdir -p /opt/nginx-upgrade
fi
cd /opt/nginx-upgrade
# Set log file
scriptdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
logname=`basename "$0"`
logname+=".log"
logfile=$scriptdir/$logname
touch "$logfile"
# Functions
logger(){
echo "$(date): $@" >> $logfile
echo "## $@"
}
logger "Starting script"
# Best practice settings for running bash scripts:
# Exit the script when an error is encountered
set -o errexit
# Exit the script when a pipe operation fails
set -o pipefail
# Exit the script when there are undeclared variables
set -o nounset
# Uncomment this to see a log to the screen of each command run in the script
# set -o xtrace
# Credit: nginx.org 2020-10-05 https://gist.github.com/nginx-gists/bdc7da70b124c4f3e472970c7826cccc
# Back up Your Current Configuration
cp -r /etc/nginx /etc/nginx_backup
# Prerequisites
apt-get -qq update
apt-get -qq install -y \
libpcre2 \
libpcre2-dev \
libssl-dev \
zlib1g-dev \
libmaxminddb0 \
libmaxminddb-dev \
mmdb-bin
# Install the module
## Get installed Nginx version number
NGINX_VER=$(nginx -v |& sed 's/nginx version: nginx\///' | sed 's/\s.*$//')
# Create a workspace and download the exact matching Nginx ${NGINX_VER} source code:
cd /opt/
if [ ! -d /opt/nginx-upgrade ]; then
mkdir -p /opt/nginx-upgrade
fi
cd /opt/nginx-upgrade
if [ ! -f /opt/nginx-upgrade/nginx-${NGINX_VER}/configure ]; then
curl -O https://nginx.org/download/nginx-${NGINX_VER}.tar.gz
tar -zxf nginx-${NGINX_VER}.tar.gz
logger "nginx-${NGINX_VER} source downloaded"
fi
# Clone Module Repositories
# Download the source code for the Brotli GeoIP2 ModSecurity-nginx modules into your workspace.
# delete previous clone directory
if [ -d /opt/nginx-upgrade/ngx_http_geoip2_module ]; then
rm -r /opt/nginx-upgrade/ngx_http_geoip2_module
fi
# Clone GeoIP2 module
git clone https://github.com/leev/ngx_http_geoip2_module.git
cd ngx_http_geoip2_module
git submodule update --init --recursive
cd /opt/nginx-upgrade
logger "GeoIP2 module cloned"
# Configure and Compile Dynamic Module
cd /opt/nginx-upgrade/nginx-${NGINX_VER}
# Remove previous configs
if [ -d /opt/nginx-upgrade/nginx-${NGINX_VER}/objs ]; then
make clean
logger "make clean invoked"
fi
# Run configure with the --add-dynamic-module flags appended to your configuration:
./configure --with-compat --add-dynamic-module=../ngx_http_geoip2_module
logger "GeoIP2 dynamic module completed"
# Compile only the modules:
make modules
logger "GeoIP2 module compiled"
# Copy the freshly compiled .so files into your system’s Nginx modules directory:
if [ ! -d /etc/nginx/modules/ ]; then
mkdir -p /etc/nginx/modules
fi
cp objs/ngx_http_geoip2_module.so /etc/nginx/modules/
logger "GeoIP2 dynamic module copied to /etc/nginx/modules/"
# Verify
# nginx -t
if [ "$(command nginx -t) | grep 'ok'" ]; then
logger "Nginx configuration ok, reloading.."
systemctl reload nginx
else
logger "Nginx errors"
fi