Geolocation detection on the web can be handy. You can locate where your visitors are coming from, and direct them to local content, or run a promotion in a specific country, or city. One of the best, and simplest solutions out there is the MaxMind geoIP database (www.maxmind.com). This article covers installing MaxMind on Centos5 (or RHEL), however most of these instructions apply to other Linux distributions as well.
1) Before we start, we need to make sure that both Apache (httpd) and the Apache Development packages are installed:
yum install httpd yum install httpd-devel
Be aware, that on a 64bit system, you may need to add .x86_64 to the end of these packages to get the 64bit install.
2) Now we can being by installing the GeoIP API Libraries, which have already been packaged up for us by the CentOS community.
yum install GeoIP*
3) Now, we need to donwload and install the apache module from maxmind:
cd /tmp wget http://www.maxmind.com/download/geoip/api/mod_geoip2/mod_geoip2_1.2.5.tar.gz tar xvzf mod_geoip2_1.2.5.tar.gz cd mod_geoip2_1.2.5 apxs -i -a -L/usr/lib -I/usr/include -lGeoIP -c mod_geoip.c
This will install the Apache 2 module. If for some reason you’re running Apache 1.3, any time you see “mod_geoip2”, simple change this to “mod_geoip” in the above commands. What we’ve done here is download, and compile the apache module for the GeoIP lookups.
4) The installation above will get you all setup with a country level database. If you don’t need any more than that, you can skip this step. If you’d like to have a city level lookup, then do the following:
cd /tmp wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz gunzip GeoLiteCity.dat.gz cp GeoLiteCity.dat /var/lib/GeoIP/GeoLiteCity.dat
5) Next, lets remove the module from the main httpd.conf file and create it’s own config file. In your httpd.conf file (which should be located in: /etc/httpd/conf/httpd.conf), find and either remove or comment out the line that starts with “Load Module geooip_module“. Then create the following file: /etc/httpd/conf.d/geoip.conf containing the following:
LoadModule geoip_module /usr/lib64/httpd/modules/mod_geoip.so <IfModule mod_geoip.c> GeoIPEnable On GeoIPDBFile /var/lib/GeoIP/GeoIP.dat MemoryCache GeoIPDBFile /var/lib/GeoIP/GeoLiteCity.dat MemoryCache GeoIPOutput Notes # GeoIPOutput Env # GeoIPOutput All </IfModule>
You’ll notice that both the GeoIP and GeoLiteCity databases are loaded. Comment out the GeoLiteCity database if you don’t need it. Below this, you’ll see three lines for GeoIPOutput. You have the choices of Apache notes, Environment variables, or both (all). Comment out the two lines you don’t need and enable the appropriate one for your use. In this case we have turned on Apache notes. You’ll also notice that beside the database lines, we’ve marked the file as “Memory Cache”. This does use additional RAM to cache the database, but speeds up access. For a small Database like the GeoIP Country database (which is 1MB), memory caching should be used. If you’re tight on memory in your server and can suffer the performance hit, you can change “Memory Cache” to “Standard” to turn caching off.
6) Now lets reload apache and pickup our changes:
apachectl -k graceful
7) Lastly, lets give it a test! Create a file in a web accessable directory, with the following code (eg: I created geotest.php):
<?php /* Uses mod-geoip to query the MaxMind GeoLite City binary database and returns geographic information based on the client's IP address */ $country_code = apache_note("GEOIP_COUNTRY_CODE"); $country_name = apache_note("GEOIP_COUNTRY_NAME"); $city_name = apache_note("GEOIP_CITY"); $region = apache_note("GEOIP_REGION"); $metro_code = apache_note("GEOIP_DMA_CODE"); $area_code = apache_note("GEOIP_AREA_CODE"); $latitude = apache_note("GEOIP_LATITUDE"); $longitude = apache_note("GEOIP_LONGITUDE"); $postal_code = apache_note("GEOIP_POSTAL_CODE"); echo 'Country code: '.$country_code.'<br>'; echo 'Country name: '.$country_name.'<br>'; echo 'City name: '.$city_name.'<br>'; echo 'Region: '.$region.'<br>'; echo 'Metro code: '.$metro_code.'<br>'; echo 'Area code: '.$area_code.'<br>'; echo 'Latitude: '.$latitude.'<br>'; echo 'Longitude: '.$longitude.'<br>'; echo 'Postal code: '.$postal_code.'<br>'; print_r($_SERVER); ?>
Now, simply go to your webpage and you can check out the results! Use the php code in the above example to call this information in your web application.