nginx: Install GeoIP Module For Country / City Level Geo Targeting

by on October 5, 2010 · 13 comments· LAST UPDATED October 5, 2010

in

How do I install GeoIP nginx module for country and/or city level geo targeting?

nginx server version 0.7.63 and 0.8.6 above comes with ngx_http_geoip_module. It will match the IP-address of the client the MaxMind GeoIP databases i.e. ip/location lookups.

In this FAQ you will learn about deploying nginx based mod_geoip installation and php server side examples to determine visitors country under UNIX / Linux / *BSD like operating systems.

Install MaxMind C API

Type the following commands to install MaxMind C API:
# cd /tmp
# wget http://geolite.maxmind.com/download/geoip/api/c/GeoIP.tar.gz
# tar -zxvf GeoIP.tar.gz
# cd GeoIP-1.4.6
# yum install zlib-devel
# ./configure
# make
# make install

You need to configure dynamic linker run time bindings as follows:
# echo '/usr/local/lib' > /etc/ld.so.conf.d/geoip.conf
Run ldconfig to activate configuration:
# ldconfig
# ldconfig -v | less

Compile nginx With GeoIP Module

Get the latest source code:
# cd /tmp
# wget http://nginx.org/download/nginx-0.8.52.tar.gz
# tar -zxvf nginx-0.8.52.tar.gz
# cd nginx-0.8.52
# yum install gcc pcre-devel.x86_64 openssl-devel.x86_64
# ./configure --without-http_empty_gif_module --with-poll_module --with-http_stub_status_module --with-http_ssl_module --with-ipv6 --with-http_geoip_module
# make
# make install

Make sure you ./configure nginx with --with-http_geoip_module option.

Grab MaxMind Databases

Type the following command to get the free database of geo_city:
# wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz -O /usr/local/share/GeoIP/GeoLiteCity.dat.gz
# gunzip /usr/local/share/GeoIP/GeoLiteCity.dat.gz

Get the free database of geo_country:
# wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz -O /usr/local/share/GeoIP/GeoIP.dat.gz
# gunzip /usr/local/share/GeoIP/GeoIP.dat.gz

A Note About MaxMind Paid Version

If you need 99.8% accuracy about IP address use the paid version. Edit /usr/local/etc/GeoIP.conf, enter:
# vi /usr/local/etc/GeoIP.conf
Update config as follows:

 
# see https://www.maxmind.com/app/license_key_login
# Enter your license key here
LicenseKey YOUR_LICENSE_KEY_HERE
 
# Enter your User ID here
UserId YOUR_USER_ID_HERE
 
# Enter your Product ID here i.e. 106 geoip country
ProductIds 106
 

Save and close the file. Get latest licensed version database, enter:
# /usr/local/bin/geoipupdate

nginx Configuration

Edit nginx.conf, enter:
# vi /usr/local/nginx/conf/nginx.conf
Locate http section and update it as follows for geoip country lookup:

 
  ### SET the path to the .dat file used for determining the visitor's country from the IP-address ###
  geoip_country /usr/local/share/GeoIP/GeoIP.dat;
 
  ### SET FASTCGI Variables ###
  fastcgi_param GEOIP_COUNTRY_CODE $geoip_country_code;
  fastcgi_param GEOIP_COUNTRY_CODE3 $geoip_country_code3;
  fastcgi_param GEOIP_COUNTRY_NAME $geoip_country_name;
 

Save and close the file. If you want city level geo targeting set it as follows:

 
  ### SET the path to the .dat file used for determining the visitor's country from the IP-address ###
  geoip_city  /usr/local/share/GeoIP/GeoLiteCity.dat;
 
  ### SET FASTCGI Variables ###
  fastcgi_param GEOIP_CITY_COUNTRY_CODE $geoip_city_country_code;
  fastcgi_param GEOIP_CITY_COUNTRY_CODE3 $geoip_city_country_code3;
  fastcgi_param GEOIP_CITY_COUNTRY_NAME $geoip_city_country_name;
  fastcgi_param GEOIP_REGION $geoip_region;
  fastcgi_param GEOIP_CITY $geoip_city;
  fastcgi_param GEOIP_POSTAL_CODE $geoip_postal_code;
  fastcgi_param GEOIP_CITY_CONTINENT_CODE $geoip_city_continent_code;
  fastcgi_param GEOIP_LATITUDE $geoip_latitude;
  fastcgi_param GEOIP_LONGITUDE $geoip_longitude;
 

Save and close the file. Finally, reload nginx:
# /usr/local/nginx/sbin/nginx -s reload

PHP Test Script

Create a php test script as follows geoip.php

<html>
<head>
  <title>What is my IP address - determine or retrieve my IP address</title>
 </head>
<body>
 <?php
     if (getenv(HTTP_X_FORWARDED_FOR)) {
        $pipaddress = getenv(HTTP_X_FORWARDED_FOR);
        $ipaddress = getenv(REMOTE_ADDR);
        echo "Your Proxy IP address is : ".$pipaddress. " (via $ipaddress) " ;
    } else {
        $ipaddress = getenv(REMOTE_ADDR);
        echo "Your IP address is : $ipaddress";
    }
    $country = getenv(GEOIP_COUNTRY_NAME);
    $country_code = getenv(GEOIP_COUNTRY_CODE);
    echo "<br/>Your country : $country ( $country_code ) ";
?>
</body>
</html>
 

Sample outputs:

Fig.01: What is my ip address?

Fig.01: What is my ip address?


You can see working example here.

How Do I Find Out MaxMind Database Info?

Type the following command:
# /usr/local/bin/geoiplookup -v 1.2.3.4
Sample outputs:

GeoIP Country Edition: GEO-106 20101001 Build 1 Copyright (c) 2010 MaxMind Inc All Rights Reserved

How Do I Use Country Code in nginx Configuration?

You can use it as follows:

 
### USA specific config ###
 if ($geoip_country_code = US) {
    do something here for USA visitors;
    # e.g. set root path /var/www/html/content/usa/;
 }
 
### India specific config ###
 if ($geoip_country_code = IN) {
    do something here for Indian visitors ;
    # e.g. set root path /var/www/html/content/india/;
 }
 

How Do I Test City Level Geo Targeting?

Use the following php code:

<html>
<head>
 <title>What is my IP address - determine or retrieve my IP address</title>
</head>
<body>
<?php
    if (getenv(HTTP_X_FORWARDED_FOR)) {
        $pipaddress = getenv(HTTP_X_FORWARDED_FOR);
        $ipaddress = getenv(REMOTE_ADDR);
        echo "<br>Your Proxy IP address is : ".$pipaddress. " (via $ipaddress) " ;
    } else {
        $ipaddress = getenv(REMOTE_ADDR);
        echo "<br>Your IP address is : $ipaddress";
    }
  $geoip_city_country_code = getenv(GEOIP_CITY_COUNTRY_CODE);
  $geoip_city_country_code3 = getenv(GEOIP_CITY_COUNTRY_CODE3);
  $geoip_city_country_name = getenv(GEOIP_CITY_COUNTRY_NAME);
  $geoip_region = getenv(GEOIP_REGION);
  $geoip_city = getenv(GEOIP_CITY);
  $geoip_postal_code = getenv(GEOIP_POSTAL_CODE);
  $geoip_city_continent_code = getenv(GEOIP_CITY_CONTINENT_CODE);
  $geoip_latitude = getenv(GEOIP_LATITUDE);
  $geoip_longitude = getenv(GEOIP_LONGITUDE);
  echo "<br>Country : $geoip_city_country_name ( $geoip_city_country_code3 , $geoip_city_country_code ) ";
  echo "<br>Region :  $geoip_region";
  echo "<br>City :  $geoip_city ";
  echo "<br>Postal code :  $geoip_postal_code";
  echo "<br>City continent code :  $geoip_city_continent_code";
  echo "<br>Geoip latitude :  $geoip_latitude ";
  echo "<br>Geoip longitude :   $geoip_longitude ";
 
?>
</body>
</html>

Sample outputs:

Fig.02: GeoCity Database PHP Script Output

Fig.02: GeoCity Database PHP Script Output

Further readings:

TwitterFacebookGoogle+PDF versionFound an error/typo on this page? Help us!

{ 13 comments… read them below or add one }

1 TryThis October 5, 2010 at 5:48 am

o_O
kick ass bookmar?

Reply

2 nixCraft October 5, 2010 at 5:49 am

Want to kill some time or may be website?
http://erkie.github.com/

Haha

Reply

3 Vamsi October 6, 2010 at 4:04 am

Hi,
how to activate this on a existing Installation ?

thanks..

Reply

4 nixCraft October 6, 2010 at 9:43 am

You need to compile minimum with nginx version stable 0.7.63 or latest 0.8.6. Also use apt-get or yum to search for the same.

Reply

5 youzhny October 12, 2010 at 7:51 am

Thanks a lots!

Reply

6 Andy Symonds November 2, 2010 at 10:24 am

This looks exactly like what I was looking for so thank you very much for posting and if it works I will link to it etc to try and get you some more traffic!

Reply

7 Marten April 22, 2011 at 11:54 pm

Hello,

I followed the exact steps, everything went fine but i keep receiving the error:
PHP Fatal error: Call to undefined function geoip_country_code_by_code() in /var/www/vhosts/…
Please advice!
Thanks!

Reply

8 Luka May 7, 2011 at 2:04 am

This tutorial have a “bug”,it should be mentioned how this section:
### SET FASTCGI Variables ###
fastcgi_param GEOIP_COUNTRY_CODE $geoip_country_code;
fastcgi_param GEOIP_COUNTRY_CODE3 $geoip_country_code3;
fastcgi_param GEOIP_COUNTRY_NAME $geoip_country_name;
goes to fastcgi_params file,not nginx.conf.Didn’t worked because of that.

Reply

9 SiNSoLe October 5, 2011 at 11:07 pm

Thanks for your reply!

Reply

10 Lacex November 19, 2012 at 4:57 pm

NOT WORKING!! :(

Reply

11 Llex March 21, 2014 at 8:02 am

It must be ยทยท

Reply

12 Aryocosmo November 21, 2012 at 4:29 pm

You was missed something in installing maxmind class C which it’s required gcc-libs

Reply

13 debedb October 21, 2013 at 4:52 pm

This works on IP addresses taken from the User’s IP or a header (With realIP module). Any way to look up an arbitrary address this way?

Reply

Leave a Comment

Tagged as: , , , , , , , , , ,

Previous Faq:

Next Faq: