Advanced vhosts Configuration

This post assumes you know a little bit about setting up your own Apache configuration and want to configure your vhosts (virtual hosts).

When I first set up my vhosts, this is all I really had in my httpd-vhosts.conf file:

VirtualDocumentRoot /Users/cameron/Sites/%0

That's great if all I want to do is create a directory, such as cameronspear.test in my ~/Sites folder, but if I want anything a little more advanced, I have to make some changes.

Problem

I knew you could set your own <VirtualHost> setting in your httpd-vhosts.conf, but if I did that, I'd lost my VirtualDocumentRoot setting, so if I have 40 directories in my ~/Sites directory, then I would have to create 40 entries in my httpd-vhosts.conf, which is lame. I can no longer just create a folder and be done. I have to open another file and create a new <VirtualHost> entry.

Solution

Create a bogus entry. Apparently, if you don't have a <VirtualHost> node that matches, it will use the settings in the first <VirtualHost> node it encounters.

For example, here's what the first entry looks like:

# this is the default if it does not match any of the other VirtualHost entries (must remain FIRST in the list)
<VirtualHost *:80>
     ServerName bogusname.bogus
     UseCanonicalName Off
     VirtualDocumentRoot /Users/cameron/Sites/%0
     LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon
     CustomLog /var/log/apache2/access_log vcommon

     # stop favicon errors!
     Redirect 404 /favicon.ico
     <Location /favicon.ico>
         ErrorDocument 404 "No favicon"
     </Location>
</VirtualHost>

No if I go to cameronspear.test, and there isn't another entry, it will look in /Users/cameron/Sites/cameronspear.test for the document root.

Now, in any other custom entries I create, I just have to set VirtualDocumentRoot none and then define a specific DocumentRoot.

Why is this useful?

Let's say you are working with a framework, and the framework isn't in the document root. Many frameworks can configure themselves so pretty much all the PHP is outside the document root, and only public resources, like CSS and JS are in the document root (with the exception of an index.php, which all traffic is commonly driven through).

For example, by default, the Laravel framework puts the application directory, system files and bundles directory in a directory above the public document root. So under the old method, we would want laravel.test to be the document root, but to get to what Laravel expects to be the document root (be default), we'd have to go to lavavel.test/public, which isn't what we want.

So what we can do is create a new entry in httpd-vhosts.conf making sure it's after our bogus entry:

# Laravel's dir is one level above public index
<VirtualHost *:80>
    ServerName laravel.test
    DocumentRoot /Users/cameron/Sites/laravel.test/public
    VirtualDocumentRoot none
</VirtualHost>

Now, (after restarting apache), laravel.test will point where we want it to (to the public folder).

What else cool can you do?

Another thing I have set up, is I have a subdomain forwarded completely to my local machine (i.e. *.dummy.cameronspear.com would all forward to my IP address). I can create an entry and add the following:

ServerAlias laravel.dummy.cameronspear.com

And now someone from the outside world could see a site on my local computer by going to laravel.dummy.cameronspear.com. Great for showing someone a project you're working on without having to first upload it to a remote server, etc.

Just make sure your site is secure, or else people could gain access to your personal computer.

It's also nice, because you can set a different ErrorLog path for a specific site or suite of sites, or set up any other customizations you might need for a specific site, without loosing the ability to just create a new directory and have the site just work.