Setup automatic per-folder subdomains on your local linux based computer

WARNING: this is a fully linux-based tutorial. I’m pretty sure that this is possible on Micro$oft Windows and OS/X, but unfortunately I’m not using them, neither I know a good DNS server for them and the impact on XAMPP and MAMP.

As you probably already know, one of the main problems when you’re doing multiple projects is to organize them properly, first for fast local testing of changes, second for your own sake, to not get lost on your own computer.
One more problem are the testing local domains. Well, the easiest way when you create a project is to create a new project folder, put a new domain (and every subdomain you’ll use) into your /etc/hosts file, create a new virtual host in the apache config, run a2ensite #### (or however you enable a new site on your distribution), restart the webserver… Which means, you need to do that everytime when you’re creating a new project. Not a very convenient way if you ask me, as you’re bloating your /etc/hosts file and your Apache2 virtualHost file(s).

So, one day, I was thinking about that and looking for a solution for it. I’m sure there are a bunch of ways to get rid of this problem, and this solution which I’ll show you is how I managed to do it.

In the end of this tutorial, you’ll have a automatic way to create local subdomains entirely by only creating a new folder (or linking your project) and adding 1 line to the htaccess file.
No more a2ensite, no more apache restarts/reloads, no more bloating of any hosts files, and no more boring c/p and editing of vhost files.

Btw, we’re using this method too on a internal development server the past few months, without any problems, althrough I don’t recommend this for production servers.

Well, first thing to know is what I’ll use to accomplish this.
– a main local domain. Mine is test.loc . Use any name you want.
– DNSMasq: a small dns daemon which is really easy to configure. This’ll be used for wildcard subdomain domain names.
– Apache2 vhost_alias module: while not used very often, it’s a relatively easy way (and yes, I know you can do that with mod_rewrite too, but I didn’t take the time to investigate, as my method is working) to tell your apache server how to handle the subdomains.
– the .htaccess file of your project: a oneliner so apache doesn’t mix up the root folder of the project
– read/write privileges to the /var/www folder (it’s on you to properly manage the folder/file privileges, so it’s not in the scope of this tutorial. I can make another one about it if somebody wants to know)

Let’s start with the DNS server. I’m using a Ubuntu based derivative, so my package manager is apt-get.

sudo apt-get install dnsmasq

After the install passes, you need to create a file in the folder /etc/dnsmasq.d (name it after your domain) for the subdomain wildcard to work.

My /etc/dnsmasq.d/test file:

address=/.test.loc/127.0.0.1

Now restart dnsmasq:

sudo service dnsmasq restart

That’s about it for your subdomains to work. Pretty straightforward, don’t you think?

Now the apache configuration. I don’t like to have all the projects directly in the /var/www folder, so I created the folder /var/www/test. You can use the /var/www folder or any other you like.

Enable the vhost_alias module:

sudo a2enmod vhost_alias

Edit a new vhost file (like /etc/apache2/sites-available/test.loc):

<VirtualHost *:80>
ServerAdmin webmaster@localhost
 
ServerName test.loc
ServerAlias *.test.loc
 
# This will be the wildcarded document root. Any folder you create in /var/www/test will be automatically a subdomain name.
VirtualDocumentRoot /var/www/test/%-3
 
# For symlinking your projects and htaccesses to work
<Directory />
Options FollowSymLinks
AllowOverride All
</Directory>
 
ErrorLog /var/log/apache2/vhosts-error.log
 
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn
 
CustomLog /var/log/apache2/vhosts-access.log combined
</VirtualHost>

Disable the main vhost site (named default):

sudo a2dissite default

Enable your site (enter the right vhost filename)

sudo a2ensite test.loc

Create a new webserver root folder. This will be the folder which’ll be called if you just call http://test.loc/ (please pay attention for the folder named _ (underscore), it’s not a typing mistake)

mkdir /var/www/test/_

Almost done!

Before going further, I’d like to explain to you the VirtualDocumentRoot directive a bit more. The %-3 means ‘give me the third dot-splitted string of the domain from right to left’. This way you can pick any level deep subdomain you want.

Let me give you another more ‘advanced’ example with two-level deep subdomains (like bar.foo.test.loc):

VirtualDocumentRoot /var/www/test/%-3/%-4

Which would mean that if you enter a domain like bar.foo.test.loc apache will try to find the folder /var/www/test/foo/bar/ and serve this one as the main domain.

Some people would ask ‘Alright smarta.. uhm.. smart guy, but I want to access foo.test.loc too, without the bar. How do I do that?’.

Well, that’s done with the ‘magic’ folder _

For example, if you’d want foo.test.loc, you’d create the folder /var/www/test/foo/_ which would be the server root for it.

Unfortunately, there’s one little catch in this example: while calling bar.foo.test.loc, it won’t automatically fallback to foo.test.loc if you don’t have the /var/www/foo/bar folder, but it will always fallback to bar.foo.test.loc from anything.bar.foo.test.loc, because you didn’t explicitly tell vhost_alias for the deeper level (which’d btw be %-5, as the fifth string from right).

If you’re a mazochist, you can always take a look on the documentation for vhost_alias which has a few more examples and explanations about it.

Next thing: the .htaccess file in your project folder. Why, you ask? It’s because without it apache2 thinks without it that the webserver root is /var/www and you can forget your precious url rewrites.
So, open up the main .htaccess file of your project and just put this line into it:

RewriteBase /

That’s it, folks!

Now all you’ve got to do is copy/symlink the project folder every time to a according folder under /var/www/test, put the oneliner into your htaccess file, and have fun with developing. No more vhosts, /etc/hosts or any other boring *hosts. The folder /var/www/test/project_a magically becomes http://project_a.test.loc/, /var/www/test/project_b becomes http://project_b.test.loc/, and so on.

I hope somebody finds it useful, as I couldn’t find any tutorials which cover all of it properly with this folder structure.

As the subsubdomains and subdomain stuff with vhost_alias are a bit confusing, please feel free to ask me any questions.