Macroify your Apache Virtual Hosts
If you’re on Windows, chances are you don’t have a handy package like Valet to make your development-workflow easier. If you’re using a standard Apache installation, this might go a long way in speeding things up.
Published 20 December 2020 in Tidbits
Jan 2020 Update: I’ve since moved on to the world of MacOS, and I use Valet (as of 2017 – 18). If you develop on Windows, I’m keeping this here in case it’s of any help.
Ever since I started developing for the web and discovered Apache, it was tedious for me to have to create a new virtual host every time I wanted to work on a new site – as if editing the hosts file was bad enough.
At the onset, I searched for a way to make a wildcard virtual host that would shorten the process of starting up a new development domain considerably. Since then, I’ve been through several iterations of this, and would like to share my current setup with you.
For starters, I’m not using the default
httpd-vhosts.conf file – for some reason, I wanted my virtual hosts to be called ‘virtuals’, and so I created a new config file for that, and included it in
Before I begin with the code, here’s the virtual host tree I’m working with now:
/var/www/ - domain - public_html (document root, maps to domain.local) - subdomain - public_html (subdomain document root, maps to subdomain.domain.local)
subdomain are ‘site-roots’, which are handy for apps that need to access one level above the document root.
To begin, we need to define two macros in the virtuals.conf file.
The first macro defines the structure of our directory configuration:
<Macro Directory $dir> <Directory "z:/var/www/$dir/public_html"> Require all granted Options Includes Indexes FollowSymLinks AllowOverride All </Directory> </Macro>
This is the simplest directory config you’d need, and covers most situations – it’s obviously easy enough to override. Note how
$dir is pulled into the path from the macro parameter (just after the name definition).
Now, the next macro is for subdomains. Unfortunately, this is required as the wildcard approach doesn’t seem to work for me, keeping in mind that I prefer subdomain document roots to be located in the main domain’s directory (one up from its document root).
<Macro LocalSub $sub $domain> <VirtualHost 127.0.0.1> ServerName $sub.$domain.local DocumentRoot "z:/var/www/$domain/$sub/public_html" Use Directory $domain/$sub </VirtualHost> </Macro>
This macro is called
LocalSub, and pulls in two variables: one for the main domain, and the other for the subdomain. This is provided to
DocumentRoot. And lastly, this virtual uses the
Directory macro we defined above.
Much like the Use directive above, we’ll need this for declaring subdomains on an individual basis as well. Unfortunately, this means an Apache-restart is required.
To create a virtual for a subdomain, simply call the
Use LocalSub blog rockettpw
blog is the subdomain, and
rockettpw is the main domain, resulting in blog.rockettpw.local.
The main virtual host
Now that’s out of the way, we can proceed to create the main virtual host, which captures
*.local (this should go underneath your subdomain imports):
<VirtualHost 127.0.0.1> UseCanonicalName Off ServerAlias *.local VirtualDocumentRoot "z:/var/www/%-2/public_html" Use Directory * </VirtualHost>
If you’re not sure what
%-2 is, it’s simply telling Apache to pull the
* from the server alias (we need to use an alias and not a name due to the wildcard – also note that we do not need
UseCanonicalName for the same reason). Specifically, it means the second last portion of the alias, where each portion is separated by a period (.).
Lastly, we import the directory config, using the macro once again. This time, however, we declare a wildcard for the directory, which would result in
z:/var/www/*/public_html. This does not apply the configuration to all th directories – it is specific to the virtual being requested.
As you can see, the process is quite straight-forward. Once you’ve set this up, all you need to do is add a directory and document root for a new site, and don’t forget to add the entry to the hosts file.
You could, as an alternative, use Acrylic, which allows you to use wild-card hosts, like
127.0.0.1 *.local. I’m unable to get it working on my end, but it’s more than likely due to my network adapter configuration (unable to diagnose).