What follows is what I consider to be best practice for my personal sites and a guide for those who wish to do the same. Months ago I dropped the www.
prefix from my domain in part because I think it’s redundant and also because I wanted to experiment with how Google treated valid HTTP redirect codes. The experiment has been a great success. Google seems to fully respect 301 Permanent Redirects and the change has taken my previously split PageRank has been combined and now I am at 7. There are other factors that have contributed to this, of course, and people still continue to link to my site and posts with a www.
(or worse) in front of it, but overall it just feels so much cleaner to have one URI for one resource, all the time. I’m sure that’s the wrong way to say that, but the feeling is there nonetheless.
Now for the meat. What’s a good way to do this? Let’s look at our goals:
- No links should break.
- Visitors should be redirected using a permanent redirect, HTTP code 301, meaning that the address bar should update and intelligent user agents may change a stored URI
- It should be transparent to the user.
- It should also work for mistyped “sub domains” such as
ww.
orwwww.
(I still get hits from Carrie’s bad link)
So we need a little magic in DNS and in our web server. In my case these are Bind and Apache. I am writing about this because at some point the code I put in to catch any subdomain stopped working and while I reimplemented it I decided to write about what I was doing. This method also works with virtual hosts on shared IPs where my previous method did not.
In Bind you need to set up a wildcard entry to catch anything that a misguided user or bad typist might enter in front of your domain name. Just like when searching or using regular expressions you use an asterisk (or splat) to match any number of any characters the same thing applies in Bind. So at the end of my zone DB file (/var/named/photomatt.net.db
) I added the following line:
*.photomatt.net. 14400 IN A 64.246.62.114
Note the period after my domain. The IP is my shared IP address. That’s all you need, now restart bind. (For me /etc/init.d/named restart
.)
Now you need to set up Apache to respond to requests on any hostname under photomatt.net. Before I just used the convinence of having a dedicated IP for this site and having the redirect VirtualHost entry occur first in my httpd.conf
file. That works, but I have a better solution now. So we want to tell Apache to respond to any request on any subdomain (that does not already have an existing subdomain entry) and redirect it to photomatt.net. Here’s what I have:
<VirtualHost 64.246.62.114>
DocumentRoot /home/photomat/public_html
BytesLog domlogs/photomatt.net-bytes_log
ServerAlias *.photomatt.net
ServerName www.photomatt.net
CustomLog domlogs/photomatt.net combined
RedirectMatch 301 (.*) http://photomatt.net$1
</VirtualHost>
The two magic lines are the ServerAlias
directive which is self explanitory and the RedirectMatch
line which redirects all requests to photomatt.net in a permanent manner.
There is a catch though. The redirecting VirtualHost
entry must come after any valid subdomain VirtualHost
entries you may have, for example I have one for cvs.photomatt.net
and I had to move that entry up in the httpd.conf
because Apache just moves down that file and uses the first one it comes to that matches, so the wildcard should be last.
That is it, I’m open to comments and suggestions for improvement.