Rewrite rule to bulk redirect domains using Apache’s RewriteMap

Birds eye view of congested highway intersection.
Imagine redirecting traffic with rewrite rules.

A component of the server migration I’m currently working on is to move all of the existing virtual host files. Unfortunately, they’re not all consistently setup, which makes them difficult to overview, and from past experience, difficult to manage.

There is also no easy way to tell which of them represent real sites, and which are purely for redirection. Some even have a document root, implying there may actually be a site there, but often I found only a single .htaccess file that redirected the domain to another site.

In a previous blog post, I proposed several guidelines to effectively manage virtual host files going forward, and one aspect of that, which I’ll talk about more deeply in this blog post, is how to organize and manage the redirects in bulk.

Goals

I’ve thought about what the ideal scenario would be and turned that into a list of actionable goals:

  1. If there are multiple servers in the farm, one server should be selected as the redirect server to handle all domain redirects.
  2. All domains pointing to the redirect server that have no specific virtual host file, should automatically be redirected to a predefined, default site.
  3. There should be a single file containing all redirects, one redirect per line, in the form of source domain followed by destination domain, e.g., old-domain.com new-domain.com.
  4. All redirects should automatically handle requests with and without the www prefix.

Let’s look at how to technically implement goals two through four.

Implementation

Using a virtual host architecture as described in my previous blog post (see Guidelines section), I’ll be using two files to implement this:

  1. default.conf — Contains the actual Apache rewrite rule.
  2. redirect_map_master — Contains where to redirect what domain.

default. conf

This file ensures that all domains pointing to the redirect server get redirected somewhere (goal #2) and that the redirect will occur with and without the “www” prefix (goal #4).

RewriteEngine On
RewriteMap redirect_map_master txt:vhosts.d/other/redirect_map_master
RewriteCond %{HTTP_HOST} ^(www\.)?(.+)
RewriteCond ${redirect_map_master:%2|domain.com} ^(.+)$ [NC]
RewriteRule ^/$ http://%1 [L,R=301]
  • Line 1: Enables the Apache rewrite engine.
  • Line 2: Tells Apache we’ll be using a file in vhosts.d/other called redirect_map_master to determine where to redirect what domain. The first reference of redirect_map_master is simply a name we assigned to the RewriteMap, which we’ll reference again on line 4.
  • Line 3: Checks for and removes, if existent, the www prefix from the domain. %1 holds www. and %2 holds our domain name without the www.
  • Line 4: Searches within the redirect_map_master file for the target domain. If the domain is found, it will pass along the destination domain, but if the domain is not found, it will pass along the default domain.com.
  • Line 5: Uses the domain that was passed from line 4 to redirect the user to the destination.

redirect_map_master

All this file contains are source and destination domains (goal #3). Each redirect is one its own line and source and destination domains are separated by a space.

domain.net domain.com
domain.org domain.com
blog.domain.com domain.com/blog
  1. Line 1: Redirect domain.net to domain.com
  2. Line 2: Redirect domain.org to domain.com
  3. Line 3: Redirect blog.domain.com to domain.com/blog

Conclusion

You now have one server, with one file, that’s responsible for all redirects. If you have 100+ domains pointing to your server, you can very quickly see or find (using grep) which domains are being redirected, and where they are being redirected to.

If you wanted, which is what I did, you can create a simple shell script to add, remove and view entries. That way you can sort the list before displaying it and prevent duplicates from being added.

Should you have any questions, concerns or suggestions, leave them in the comments below!

Featured image by Denys Nevozhai.