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

rusek@sxc.hu © rusek@sxc.hu

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.


16 comments

  1. My URL rewriting doesn’t work at all a little help would be appreciated

    Here is my vhost :

    <VirtualHost *:80>
    ServerAdmin webmaster@localhost
    
    ServerName local.dev
    ServerAlias *.local.dev
    
    # This will be the wildcarded document root. Any folder you create in /var/www/test will be automatically a subdomain name.
    VirtualDocumentRoot /var/www/local/%-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>

    And I have the subfolder : “app”, I can access it via http://app.local.dev
    And I have this htaccess file in the app folder :

    RewriteEngine on
    RewriteBase /
    RewriteCond $1 !^(index\.php|assets|robots\.txt)
    RewriteRule ^(.*)$ /index.php/$1 [L]

    And of course mod_rewrite is activated

    Thanks

    1. I fixed it !

      Just have to change the line

      <Directory />

      to

      <<Directory /var/www>
  2. I don’t know man, I’d rather know what I’m doing and just edit or cp a file. This is really more trouble than it’s worth. Seems the instructions as given don’t work either but I’m going to look up vhost alias and see what the config options are. Thanks for sharing in any case. Having multiple test sites is never an easy thing to manage.

  3. Really nice tutorial.

    Unfortunately instead of successful using vhosts all requests return the old /var/www directory. Apparently I’m doing something wrong.

    mod_rewrite is on, so is vhost_alias

  4. I’ve been experimenting with this confuration for a while and it works pretty good. One observation that I recently made is that when I’m running the debugger the debugger does not stop at any breakpoints in the “subdomains”.

  5. For what’s worth, I was able to fully implement the process on another computer so any errors I’m getting are probably a configuration issue that I will eventually sort out.

    Thank you, this works great!

    You indicated that you wouldn’t recommend this for a production environment. Is there something other than it has not been throughly tested driving this statement? Are there potential security or scalability issues?

  6. When I execute the command:
    sudo service dnsmasq restart
    I get an error message saying:
    dnsmasq: failed to create listening socket for port 53: Address already in use

  7. Hey, I’m having trouble getting the site to redirect to anywhere other than the “_” directory in my subdomain directory. Why would this happen? I just replaced everything that had ‘test’ in it with my own name.

    Please help!

  8. A few additions:

    1. VirtualDocumentRoot /var/www/%2+/%1

    This will make it really easy to organize your domains and subdomains in one step. I like to keep all my dev top level domains in one folder. Each domain can have as many subdomains as you like:

    /var/www/example.com.dev
    /var/www/example.com.dev/www
    /var/www/example.com.dev/anothersubdomain

    So these will work:

    http://www.example.com.dev
    http://anothersubdomain.example.com.dev

    And so on. Really convenient.

    2. Fix DOCUMENT_ROOT in $_SERVER

    By default $_SERVER[‘DOCUMENT_ROOT’] will be ‘/etc/apache2/htdocs’ (or wherever apache resides). This is not true and will eventually cause trouble with scripts.

    This command in the VirtualHost directive will correct this:

    php_admin_value auto_prepend_file /etc/apache2/setdocroot.php

    setdocroot.php:

    <?php
    $_SERVER['DOCUMENT_ROOT'] = str_replace($_SERVER['SCRIPT_NAME'], '', $_SERVER['SCRIPT_FILENAME']);

    My full vhost config:

    <Directory /var/www/>
        Options All
        AllowOverride All
        Order allow,deny
        Allow from all
    </Directory>
    
    <VirtualHost *:80>
        UseCanonicalName off
        VirtualDocumentRoot /var/www/%2+/%1
        DirectoryIndex index.html index.htm index.php
    
        ErrorLog ${APACHE_LOG_DIR}/error.log
    
        LogLevel warn
        CustomLog ${APACHE_LOG_DIR}/access.log combined
    
        php_admin_value auto_prepend_file /etc/apache2/setdocroot.php
    </VirtualHost>
  9. Hello,

    first of all thanks,
    I think I am going to setup VirtualBox, Ubuntu, AMP and this one to do developing instead of doing it on my MacBook nativly. Should make deployment to linux hosts much smoother and keep constraints seperated.

    A question though: could I not add RewriteBase to apache.conf/httpd.conf instead of .htaccess?
    I dont’ like .htaccess files spread around.

    And: while I saw you do magento development: any tips on what to read if you are already an experienced php/sql/html/css developer?

    1. Hi Jonas,
      thank you for your reply.

      The RewriteBase directive’s context is directory based. That means you either need to create/edit the .htaccess file in the root folder of your project and add it there, or you can put everytime you create a new subdomain-folder something like that into the httpd.conf (I didn’t try that out, just writing from memory):

      <Directory /path/to/your/subdomain/folder>
      RewriteBase /
      </Directory>

      Which isn’t very convenient, and quite opposite to the theory that you don’t want to edit your apache files every time you create a new subdomain.

      If you don’t want to edit the .htaccess of your root project folder every time and are using something like magento/wordpress/any-other-solution-available, copy the htaccess file from the project root somewhere safe, put the ‘RewriteBase /’ into it, and copy it every time into the subdomain folder after you create the new subdomain.

      About the tips for reading, I’d suggest you browse a bit in the archives of Inchoo, and the magento knowledge base has good tutorials for magento starters ( http://www.magentocommerce.com/knowledge-base/categories/category/development/ ).

      Good luck with setting up the environment.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <blockquote cite=""> <code> <del datetime=""> <em> <s> <strike> <strong>. You may use following syntax for source code: <pre><code>$current = "Inchoo";</code></pre>.