Dyanamic Subdomain Using Apache

by Stephen Fluin 2007.12.09

One of the many issues that I have pondered over the years is how to create a server setup that allows the user to use an arbitrary number of subdomains, and the subdomain information is passed to a script or CGI that can use the subdomain information in its processing. This type of thing is done on many sites, such as deviantart.com.

The first step to accomplish this goal is that you need to set up DNS to handle any subdomain correctly. If your DNS isn't set up right, users aren't going to be able to find your server with an arbitrary subdomain, and there is no chance for your server to understand and process the request.

I will use GoDaddy for this example, but this would apply to any DNS host including BIND. Typically you would set up each subdomain as an Alias or CNAME, such as www, ftp, mail, etc. This would allow you to point each subdomain to a different IP. We don't want this, we want to allow ANY subdomain, and for all requests to return the same server IP. We do this by setting up an A name. Typically you will already have an A name "@" set up. You want to add an A name called "*" to your domain, and ensure that it points to the IP of your server. This will ensure that all requests involving that domain will be forwarded, regardless of their IP.

Now that we have DNS set up to forward the requests, we need to ensure that the server doesn't attempt to use the subdomain for virtual hosting. I have used this technique successfully on a single domain hosted along with numerous other domains at a single IP. The entry in the Apache VirtualHost directive will look like this:

<VirtualHost *:80>
        DocumentRoot "/path/to/folder"
        ServerName domain.tld
        ServerAlias  domain.tld *.domain.tld
        ErrorLog /error-log/path
        CustomLog /access-log/path combined

To ensure that this entry works, replace "domain.tld" with your domain name, and the paths with the correct paths for your server.

Now apache is set up to respond to all requests regardless of subdomain for this domain from a single location. The final step is to ensure that the subdomain will get passed to your scripts or applications correctly. I will be using PHP for this example.

I created a .htaccess file and placed it in the root folder for this domain. This .htaccess file uses mod_rewrite to match the subdomain, if given, and to translate the request into a new URL that enables a target script to read the subdomain. My file looks similar to this:

RewriteEngine On
RewriteCond %{HTTP_HOST} !^$ [NC]
RewriteCond %{HTTP_HOST} !^www. [NC]
RewriteCond %{REQUEST_URI} !i.php
RewriteCond %{HTTP_HOST} ^([^.]+).
RewriteRule ^(.+) /index.php?a=%1&b= [L]

The RewriteCond rules are responsible for determining that if no subdomain is given, or if the "www" subdomain is given, pages are loaded as normal. The third rule ensures that we don't enter an infinite loop of forwarding.

The total effect of these lines is that normal requests are passed through as normal, but if someone gives a custom subdomain such as "google.domain.tdl", the user remains on what appears to be "google.domain.tld", but a variable is set informing your system that the user is on the "google" subdomain

Feel free to add a comment if you have any questions. I hope this saves others the time and frustrations I went through to find this.