Wildcard hosting with Apache and Bind

Posted by Steve on Thu 23 Feb 2006 at 09:35

If you have control over your DNS you can setup 'wildcard hosting', which means you can have a webserver accept connections for any given subdomain. This can be enormously useful for community websites, or other hosting purposes.

One popular site which uses this technique is Livejournal, another less obvious one is Slashdot.org.

The end goal of using wildcard hosting is that you'll be able to setup a webserver for a domain, such as example.com which will serve requests for any subdomain. For example the following would all be valid hosts:

  • foo.example.com
  • private.example.com
  • cvs.example.com
  • some.really.really.long.example.

You can even have each domain point to different pages if you use mod_rewrite. This kind of hosting can be setup fairly easily, with just a couple of small steps:

  1. Setup your DNS entries for the domain you wish to use.
  2. Setup Apache, or Apache2, to handle the domains.
  3. Optionally use mod_rewrite to point particular domains at different content.
Wildcard DNS

The setup of wildcard DNS is something that should be simple if you have control over the DNS server(s) which are in use for your domains.

If you use your domain-resellors control panel there may be an option for it, if not you might need to have somebody else host your DNS for you. (I'll do it for a fee ;)

Using the common bind package you can setup wildcard entries by the addition of a record with the name "*".

Here is an example of the entry you'll need to add:

*.example.com.    IN      A       192.168.1.1

Add this to the bottom of your zone file taking care that you add it beneath any static subdomain entries you might have. Here is a full example:

example.com. 86400     IN      SOA     example.com. hostmaster.example.com. (
                                        2005100804      ; Serial YYYYMMDDXX
                                        10800           ; Refresh
                                        3600            ; Retry
                                        3600000         ; Expire
                                        86400 )         ; minimum
                        IN      NS      ns1.example.com.
                        IN      NS      ns2.example.com.
                        IN      MX      10      mail.example.com.
                        IN      A       192.168.1.1
mail                    IN      A       192.168.1.1
ns1                     IN      A       192.168.1.1
ns2                     IN      A       10.0.0.2
*.example.com.		IN      A       192.168.1.1

Here we see the wildcard entry at the bottom which causes any query of *.example.com to return the address 192.168.1.1 (except for those static ones ns1, ns2, and mail in this example).

Note that this will mean your DNS server will receive more traffic.

Apache Setup

Once you have your DNS entries setup you can alter your Apache virtual hosts to add an appropriate ServerAlias entry. This will allow Apache to treat a number of hostnames as equivilent.

A typical VirtualHost would look something like this:

<VirtualHost *>
        ServerName  www.example.com

        DirectoryIndex index.html 
        DocumentRoot /home/www/www.example.com/htdocs

	....
</VirtualHost>

To allow this server to serve multiple other valid hostnames we simply add a ServerAlias setting:

<VirtualHost *>
        ServerName  www.example.com
	ServerAlias *.example.com

        DirectoryIndex index.html 
        DocumentRoot /home/www/www.example.com/htdocs

	....
</VirtualHost>

This will tell Apache that any host with the .example.com suffix will match this virtual host too.

mod_rewrite setup

With a setup as described so far you'll end up with a server which is capable of serving the same contents to clients, regardless of the hostname used to connect.

Frequently it is useful to send clients to a different location, and this is something that mod_rewrite can handle.

Assuming that you're using Apache2 you can enable mod_rewrite by running:

a2enmod rewrite

(If mod_rewrite is new to you then you should refer to our earlier article mod_rewrite for Apache and Apache2 under Debian.)

As an example we'll consider a site which uses several subdomains:

  • linux.example.com
  • solaris.example.com
  • bsd.example.com

These sites should each point to a particular set of contents:

  • linux.example.com should point to http://example.com/linux/
  • solaris.example.com should point to http://example.com/solaris/
  • bsd.example.com should point to http://example.com/bsd/

To do this we can use mod_rewrite to match against the Host: header that client browsers will send. The following rules will do the job:

RewriteEngine on
RewriteCond %{http_host} .
RewriteCond %{http_host} !^www.example.com [NC]
RewriteCond %{http_host} ^([^.]+)\.example.com [NC]
RewriteRule ^(.*) http://www.example.com/%1/ [R=301,L,QSA] 

Taking these lines one by one we can see how they work. The first line simply enables the use of the mod_rewrite engine.

The second line instruct the module that we wish to match against the http_host, or Host:, header.

In the third line we test that the requested host is not www.example.com. If that is true then the fourth line wil determine the hostname used in the request and store the part before .example.com in a variable "%1".

The last line simply redirects visitors to a new path with the result of this capture.

Note that with this setup a request for foo.example.com will redirect visitors to example.com/foo - which most likely won't exist. So make sure you have a good error page!

 

 


Posted by cswd (195.172.xx.xx) on Thu 23 Feb 2006 at 12:07
Very handy - always wondered how to do this. Thanks for the great article

[ Parent | Reply to this comment ]

Posted by Steve (82.41.xx.xx) on Thu 23 Feb 2006 at 12:14
[ View Steve's Scratchpad | View Weblogs ]

You're welcome.

It is basically a clone of the setup that I did for my CVS repository, and it seems to work well.

Steve

[ Parent | Reply to this comment ]

Posted by gautamlohar (59.98.xx.xx) on Fri 27 Nov 2009 at 09:56
the IP in which we are going to run the virtual subdomains is shared by multiple websites. And there was no vhost.conf file on the server, we have created it through putty and typed the all the above lines mentioned by you for apache setup.
<VirtualHost *>
ServerName www.example.com
ServerAlias *.example.com

DirectoryIndex index.html
DocumentRoot /home/www/www.example.com/htdocs

....
</VirtualHost>

We have also entered the wildcard DNS

AND uploaded the .htaccess file
RewriteEngine on
RewriteCond %{http_host} .
RewriteCond %{http_host} !^www.example.com [NC]
RewriteCond %{http_host} ^([^.]+)\.example.com [NC]
RewriteRule ^(.*) http://www.example.com/%1/ [R=301,L,QSA]
-------------------------------------

But Still my virtual subdomain is not working. Please help.

[ Parent | Reply to this comment ]

Posted by TokenGoth (193.195.xx.xx) on Thu 23 Feb 2006 at 12:27
I use this in my apache (1.3) config:

RewriteCond %{REQUEST_URI} !^/mailman/.*
RewriteCond %{REQUEST_URI} !^/pipermail/.*
RewriteCond %{REQUEST_URI} !^/cgi-bin/.*
RewriteCond %{REQUEST_URI} !^/icons/.*
RewriteCond %{REQUEST_URI} !^/cacti/.*
RewriteRule ^(.+) %{HTTP_HOST}$1 [C]
rewriteRule ^([^.]+)\.([^/]+)\/(.*)$ /var/www/web/$2/$1/$3 [L]

Which maps http://one.two.three/four to /var/www/web/two.three/one/four

And I've got the following log file directives:

LogFormat "%{Host}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"
" vfull
CustomLog "|/sbin/vlogger -s access.log -u www-data -g www-data -t %Y%m%d-acces
s.log /var/log/apache" vfull


That complement that using vlogger (http://n0rp.chemlab.org/vlogger/)

Coupled with a script to autogenerate webalizer log files for selected hosts.

[ Parent | Reply to this comment ]

Posted by jermen (213.195.xx.xx) on Thu 23 Feb 2006 at 13:22
Other way how to do this is use mod_vhost_alias and directive VirtualDocumentRoot, for example:
<VirtualHost xxx.xxx.xxx.xxx>
UseCanonicalName off
VirtualDocumentRoot /var/www/%-2.0.%-1/%-3
</VirtualHost>
Now you can use /var/www/mydomain.com/whatever as a content for whatever.mydomain.com.

Main disadvantage is variable DocumentRoot which is taken from main configuration and it can be problem with some sites. It's also afaik impossible to log for each domain separately (only way is parse logfiles later).

[ Parent | Reply to this comment ]

Posted by Anonymous (206.111.xx.xx) on Mon 3 Apr 2006 at 09:27
This is basically how http://notlong.com traps all subdomains and redirects to the appropriate long URLs.

[ Parent | Reply to this comment ]

Posted by Anonymous (85.249.xx.xx) on Tue 26 Dec 2006 at 23:56
Thank you very much! Very, very useful article. Some other examples that I found have not given such a result.

[ Parent | Reply to this comment ]

Posted by mjh2000 (72.89.xx.xx) on Wed 2 Apr 2008 at 19:59
another great article steve!!!
Just want to clarify something, do need the .htaccess modification to in order for this to work??? I do not care about the subdirectory re-direction.

Also, I really do not want to redirected to a directory per say, but I just want the webserver to accept any url entered for the domain name: example.com. For example : if i enter: ddaadd.example.com , i want my website to just accept it and not change the url typed. What i mean by that is accept what ever the subdomain is entered.

thanks
mjh

[ Parent | Reply to this comment ]

Posted by Anonymous (60.242.xx.xx) on Wed 2 Nov 2011 at 06:38
I wasn't aware that named could do this. I tested it on bind-9.3.6-4.P1.el5 on RHEL5.5. It works beautifully!

[ Parent | Reply to this comment ]

Sign In

Username:

Password:

[Register|Advanced]

 

Flattr

 

Current Poll

What do you use for configuration management?








( 332 votes ~ 1 comments )

 

 

Related Links