Geolocation routing is a technique that enables websites to route incoming traffic to different resources based on the geographical location of the user’s IP address. This means that users from different countries or regions can be directed to different servers or content, optimizing their experience.

Getting Started

To get started, follow these steps:

Step 1: Compiling Nginx with GeoIP2 Module

To enable geolocation routing, we’ll first need to compile Nginx from source with the GeoIP2 module. Here’s how we can do it:

  1. Update our package list and install essential build tools:

     apt-get update -y
     apt-get install -y build-essential
    
  2. Add the MaxMind repository and install required libraries:

     add-apt-repository -y ppa:maxmind/ppa
     apt-get update
     apt-get install -y libmaxminddb0 libmaxminddb-dev mmdb-bin geoipupdate
     apt-get install -y libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl-dev
    

Step 2: Setting Up MaxMind Account

GeoIP2 module uses a GeoIP database to map IP addresses to locations. To access the database, we’ll need to create an account on the MaxMind website. Here’s what we need to do:

  1. Create an account on MaxMind.

  2. Obtain our Account ID and License Key.

  3. Edit the /etc/GeoIP.conf file and add our Account ID, License Key, and desired Edition IDs:

    AccountID YOUR_ACCOUNT_ID
    LicenseKey YOUR_LICENSE_KEY
    EditionIDs GeoLite2-ASN GeoLite2-City GeoLite2-Country
    
  4. Update the GeoIP database using geoipupdate command.

Step 3: Downloading and Compiling Nginx with GeoIP2 Module

Now, let’s download and compile Nginx with the GeoIP2 module:

  1. Navigate to the source directory:

    cd /usr/local/src
    
  2. Download Nginx and extract it:

    NGINX_VERSION=1.21.4
    NGINX_MODULE_PATH=/usr/local/src/ngx_http_geoip2_module
    wget https://nginx.org/download/nginx-$NGINX_VERSION.tar.gz
    tar xzvf nginx-$NGINX_VERSION.tar.gz
    
  3. Clone the ngx_http_geoip2_module repository:

    git clone https://github.com/leev/ngx_http_geoip2_module $NGINX_MODULE_PATH
    cd nginx-$NGINX_VERSION
    
  4. Configure and install Nginx with the GeoIP2 module:

    ./configure \
        --add-dynamic-module=$NGINX_MODULE_PATH \
        $(nginx -V) --with-compat \
        --with-http_ssl_module
    make
    make install
    
  5. Add cronjob to update geoip database weekly:

    echo "0 0 * * 0 geoipupdate -f /etc/GeoIP.conf" | crontab -
    

Step 4: Configuring Nginx for Geolocation Routing

Now it’s time to configure Nginx to use geolocation routing:

  1. Create a systemd service for Nginx in /lib/systemd/system/nginx.service. Fill its service config as:
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target
  1. Edit the Nginx configuration file /usr/local/nginx/conf/nginx.conf and add the following:

    • Configure the geoip2 module to use the GeoIP database.

    • Define a mapping between countries and backend servers.

    • Create a server block with the desired routing logic.

Sample nginx.conf would be:

worker_processes  1;
load_module modules/ngx_http_geoip2_module.so;
pid        /run/nginx.pid;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
        $geoip2_data_country_code country iso_code;
    }

    map $geoip2_data_country_code $backend {
        default <DEFAULT DESTINATION IP ADDRESS>;
        US <DESTINATION IP ADDRESS FOR US>;
        NP <DESTINATION IP ADDRESS FOR NEPAL>;
    }

    server {
        listen 80;
        server_name <YOUR DOMAIN>;
        location / {
            proxy_pass $backend;
        }
    }
}

Populate YOUR_DOMAIN and DESTINATION IP ADDRESSes with desired values

  1. Enable and start the Nginx service:
     systemctl unmask nginx.service
     systemctl start nginx
    

FINAL Script to setup nginx + geoip2 looks like this: script.sh

Conclusion

With Nginx and the GeoIP2 module, we can now route traffic to different resources based on our users’ geographical locations. This enhances user experience by directing them to servers that are closer to them or serve content relevant to their region. By following the steps outlined in this guide, you’ll have a powerful geolocation routing system up and running on our Ubuntu server in no time!