CNAMEs and vhosts
Have you ever…
- felt like just one web server isn’t quite cutting it?
- wanted to alias servers on your home network so you can tell your friends a simple, memorable hostname, but keep the real name within your naming scheme?
- gotten a steaming pile of code dumped on you that relies on requested hostname for important session information?
I actually ran into all three of these problems this week (the last was particularly nasty - PHP’s $_SERVER['host']
has no business being used the way I saw it).
In any event, there’s a relatively simple way around these issues with an Apache webserver and custom DNS resolver (this post uses dnsmasq, but BIND and the other major DNS daemons should have equivalents).
First, solving the hostname problem: tell your DNS resolver to provide a CNAME record for the aliased hostname that points to the target hostname. In dnsmasq, this is as simple as adding
cname=alias,target
to your config file. A couple caveats, though, especially if you’re in a mixed environment: some DNS clients on some systems will automatically append the local domain name (if your DNS server provides one) or, even stranger, the suffix .local
to a hostname when resolving. So in a setup with a domain name, you should have three cname lines:
cname=alias,target
cname=alias.local,target
cname=alias.your.domain,target
When resolving this (using dig
or similar), the CNAME record will provide a sort of DNS “redirect” to the real DNS A record with an IP.
Now for the server part. Apache comes with good vhost support in the form of a standard module; make sure that module (mod_vhost_alias
) is installed and enabled in your config file, then define a vhost. In the simplest scenario, the vhosts will all listen on whatever addresses the server listens on, and will share port 80. All that remains is to provide a per-host document root and some basic contact info. Add the following to your httpd.conf
:
<VirtualHost *:80>
ServerAdmin you@example.com
DocumentRoot "/htdocs/vhosts/target"
ServerName target.your.domain
ServerName target
ServerName localhost
ErrorLog "logs/vhosts/target/error.log"
CustomLog "logs/vhosts/target/access.log" common
</VirtualHost>
<VirtualHost *:80>
ServerAdmin you@example.com
DocumentRoot "/htdocs/vhosts/alias"
ServerName alias.your.domain
ServerName alias
ErrorLog "logs/vhosts/alias/error.log"
CustomLog "logs/vhosts/alias/access.log" common
</VirtualHost>
Note that we have two separate document roots and log files, and that the vhost for “target” - the machine’s original hostname - retains the “localhost” alias in its vhost, so anyone on that machine querying http://localhost
will get the right documents.