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:
- Setup your DNS entries for the domain you wish to use.
- Setup Apache, or Apache2, to handle the domains.
- Optionally use mod_rewrite to point particular domains at different content.
Apache SetupThe 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.1Add 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.1Here 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.
mod_rewrite setupOnce 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.
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!
[ Parent | Reply to this comment ]
[ Send Message | 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.
[ Parent | Reply to this comment ]
<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 ]
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 ]
<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 ]
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
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 ]
[ Parent | Reply to this comment ]