Redirecting EU visitors in Apache

At $work a client requested the ability to easily detect visitors to their site coming from within the EU so that they could redirect them accordingly.

Fortunately, this was pretty simple to do via use of mod_maxminddb which parses maxmind databases to provide a rather large amount of possible information.

You should follow the guide within their git to get it installed and acquire a maxmind database, of which both free and commerical copies exist, linked to on the module's git page.

Once installed and correctly using your maxmind DB within the apache config, we want to set it to both detect your visitor's country ISO code and from there check if they're within the EU. To grab their ISO code you would specify the following in your apache config:

MaxMindDBEnv MM_COUNTRY_CODE COUNTRY_DB/country/iso_code

This will create an apache variable called MM_COUNTRY_CODE which contains the 2 letter ISO code of your visitor. From this we can set another variable if this is code matches a defined EU state, like so:

SetEnvIf MM_COUNTRY_CODE ^(AT|BE|BG|CZ|DE|DK|EE|ES|FI|FR|HR|GB|GR|IE|IT|CY|LV|LT|LU|HU|MT|NL|PL|PT|RO|SI|SK|SE) EUROPEANUNION

So when you're done, your httpd.conf should contain lines that look like this:

MaxMindDBEnable On
MaxMindDBFile COUNTRY_DB /usr/local/share/GeoIP/GeoLite2-Country.mmdb
MaxMindDBFile CITY_DB    /usr/local/share/GeoIP/GeoLite2-City.mmdb
MaxMindDBEnv MM_COUNTRY_CODE COUNTRY_DB/country/iso_code
SetEnvIf MM_COUNTRY_CODE ^(AT|BE|BG|CZ|DK|EE|ES|HR|GR|IE|IT|CY|LV|LT|LU|HU|MT|NL|AT|PL|PT|RO|SI|SK|FI|SE) EUROPEANUNION

This can now be used within your .htaccess file to redirect customers who are in the EU as follows:

RewriteEngine On
RewriteCond %{ENV:EUROPEANUNION} ^1$
RewriteRule ^(.*)$ http://www.yourawesomesite.com/eu/ [R=301,L]

PHP 5.3 in EasyApache 4

N.B. PHP 5.3 has not been supported now for almost 3 years, the best approach really would be to port any code over to a newer version, as the provided versions in EA4 are having fixes backported into them.

With the advent of EasyApache 4, cPanel have made management of multiple PHP versions so much easier, with generally no more needing to hack at custom apache configs or having to keep old, unsupported modules, like mod_suphp, to hand.

However, at $work, we are currently migrating client servers away from Centos 5 due to its imminent EoL and some of who still have requirements for PHP 5.3, but cPanel no longer provide EA3 on a newly provisioned box, cutting off access to PHP 5.3 as standard. Getting PHP 5.3 added as a CGI handler is pretty easy though and it mostly plays nice with cPanel's built in MultiPHP tools. For example if a user is using PHP 5.3 and makes a change in cPanel's MultiPHP ini that change will apply to the 5.3 instance.

Most of the required dependencies are already provided by cPanel but there's a few things you'll want to get installed, so run the following commands to install your dev tools, epel (needed for one of the dependencies) and the dependencies themselves:

yum groupinstall 'Development Tools'
yum install epel-release
yum install sqlite-devel libxml2-devel bzip2-devel libcurl-devel libc-client-devel libmcrypt-devel aspell-devel libedit-devel libtidy-devel

Then acquire PHP 5.3 (the newest build is 5.3.29 and at the time of writing can be gotten from: http://php.net/get/php-5.3.29.tar.gz/from/a/mirror) and extract it into /usr/src before cd'ing in.

To get this to build successfully, I took the ./configure line from an EA3 server and modified it to use system libraries rather than the custom ones bundled with EA3. You can use this as-is or feel free to modify it for your own needs:

./configure  --enable-bcmath --enable-calendar --enable-exif --enable-ftp --enable-gd-native-ttf --enable-libxml --enable-mbstring --enable-pdo=shared --enable-sockets --enable-zip --prefix=/opt/php53  --with-bz2 --with-curl=/usr --with-freetype-dir=/usr --with-gd --with-imap=/usr --with-imap-ssl --with-jpeg-dir=/usr --with-kerberos --with-libdir=lib64 --with-libexpat-dir=/usr --with-libxml-dir=/usr --with-mcrypt=/usr --with-mysql=/usr --with-mysql-sock=/var/lib/mysql/mysql.sock --with-mysqli=/usr/bin/mysql_config --with-openssl=/usr --with-openssl-dir=/usr --with-pcre-regex=/usr --with-pdo-mysql=shared --with-pdo-sqlite=shared --with-pic --with-png-dir=/usr --with-sqlite=shared --with-tidy=/usr --with-xmlrpc --with-xpm-dir=/usr --with-zlib --with-zlib-dir=/usr

Once the configure is done, and you've done your make, make test and make install, you'll have your shiny new PHP in /opt/php53 and you're ready to get apache up and running.

You'll want to edit /etc/apache2/conf.d/includes/pre_main_global.conf and add the following lines to it:

ScriptAlias /local-bin /opt/php53/bin
Action application/x-httpd-php53 /local-bin/php-cgi

<Directory "/opt/php53/bin">
    Order allow,deny
    Allow from all
</Directory>

At this point, if you want PHP 5.3 to be the default serverwide version, you would also need to add the following line after the ones above:

AddHandler application/x-httpd-php53 php

Otherwise you can put it in the .htaccess for the site that needs PHP 5.3 support.

Caveat
With this method, if you have PHP 5.3 set to the system default version, the standard cPanel .htaccess line to change versions won't work, so if you want another version, after selecting it you need to edit the user's .htaccess, changing the following:

# php -- BEGIN cPanel-generated handler, do not edit
# Set the “ea-php70” package as the default “PHP” programming language.
<IfModule mime_module>
  AddType application/x-httpd-ea-php70 .php .php7 .phtml
</IfModule>
# php -- END cPanel-generated handler, do not edit

To:

# php -- BEGIN cPanel-generated handler, do not edit
# Set the “ea-php70” package as the default “PHP” programming language.
<IfModule mime_module>
  AddHandler application/x-httpd-ea-php70 .php .php7 .phtml
</IfModule>
# php -- END cPanel-generated handler, do not edit

(changing the AddType to AddHandler)

Fatal error: Illegal or unknown default time zone in MySQL

MySQL lets you specify which timezone to use in the my.cnf file, using the following config line:

default-time-zone=Europe/London

However, you might find, after you do this, that it ends up failing to restart the service with the following error in the logs:

Fatal error: Illegal or unknown default time zone

Obviously Europe/London is a valid timezone name, so why does it not work?

Basically this error is caused when MySQL hasn't populated the timezone table within the mysql database, so it doesn't know what is or isn't a valid timezone name.

The way to fix this is, simply, to populate the timezone table, which can be done using the following command via ssh (You will need root access in mysql for this, and to have removed the line and gotten mysql back up and running of course):

mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql -p

Pop in your mysql root password and wait for it to finish. Re-add the line to the my.cnf, restart the service and you should be all set!