Easily Automate Mass Virtual Hosting With Apache & mod_macro

How do I configure Apache2 with mod_macro to automate VirtualHost configs?

Virtual Hosting is great fun once you've mastered the Virtual Host directive in Apache. It's quick to then realise that most sites basically require the same virtual host settings with few changes bar their directory, and domain etc.

mod_macro allows you to simplify the creation of VirtualHost configs by specifying the variables that changes and simply listing each site in a text file. mod_macro then loops through each host you've specified and creates the VirtualHost configs for you when the server starts up.

Standard VirtualHost Configs

Take a look at a typical VirtualHost config in Apache:

<VirtualHost *:80>
    ServerName example-one.com
    ServerAlias www.example-one.com
    DocumentRoot "/var/www/vhosts/example-one.com"
    ErrorLog "/var/log/httpd/example-one.com.error_log"
    CustomLog "/var/log/httpd/example-one.com.access_log" combined
</VirtualHost>
<VirtualHost *:80>
    ServerName example-two.com
    ServerAlias www.example-two.com
    DocumentRoot "/var/www/vhosts/example-two.com"
    ErrorLog "/var/log/httpd/example-two.com.error_log"
    CustomLog "/var/log/httpd/example-two.com.access_log" combined
</VirtualHost>
...
.. Another <VirtualHost>... etc.. etc..
. 

Notice the repetition in the above VirtualHost configs.

A typical scenario is that you would have many VirtualHost files for each of your sites. Alternativly, you migh thave all your VirtualHost definitions in one file with a <VirtualHost> directive repeated for each website like in the example above.

On the Ubuntu flavor of Linux the virtual hosts directory the sites available config files are found under /etc/apach2/sites-available/ and enabled using the a2ensite tool. For example: a2ensite /etc/apach2/sites-available/myVirtualHosts.conf would enable the site(s) described in myVirtualHosts.conf

This isn't necessary when using mod_macro.

How to use mod_macro to automate VirtualHosts

Your web server might be hosting many Wordpress blogs, a few Drupal sites for example. Notice these are all PHP based website, but the concept can be applied to other blogging & content management systems too. It would be nice to be able to create new sites without repetitive VirtualHost configs. With mod_macro you can do this.

Notice the basic variables of a typical VirtualHost config:

  • ServerName
  • ServerAlias
  • DocumentRoot
  • ErrorLog
  • CustomLog

A basic mod_macro config might look like this:
Make a backup of your configs before trying any of this.

## Define a VHost Macro for repetitive configurations
<Macro VHost $host $port $dir>
  Listen $port
  <VirtualHost *:$port>
    ServerName $host
    DocumentRoot "$dir"

    # Public document root
    <Directory "$dir">
      Require all granted
    </Directory>
  </VirtualHost>
</Macro>
## Use of VHost with different arguments.
Use VHost example-one.com 80 /vhosts/example-one.com/htdocs
Use VHost example-two.com 80 /vhosts/example-two.com/htdocs
Use VHost abc-example.com 80 /vhosts/abc-example.com/htdocs

Creating new sites using mod_macro

The example above creates a macro which (when enabled using a2enconf <name of conf file>) would cause this configuration to be loaded in by Apache2 during start-up. Cool eh?

You would then use: service apache2 reload to tell apache to load in this new configuration. Telling Apache to reload gracefully rather than stopping the web server - Apache might currently be serving requests for example.

"The USR1 or graceful signal causes the parent process to advise the children to exit after their current request (or to exit immediately if they're not serving anything). The parent re-reads its configuration files and re-opens its log files. As each child dies off the parent replaces it with a child from the new generation of the configuration, which begins serving new requests immediately." - Apache Docs

In short- it's a much more graceful way of reloading your new Apache configurations. This is preferred on busier sites.

Note: after reloading configs your existing configs still apply, so if you have a '000-default.conf' or similar enabled, they are still active. You might want to move these sites into your new shiny mod_macro config.

Use a2dissite <name of conf> to disable and currently enabled site configs if you like. Use a2disconf <name of conf> to disable any conf files you created (you probably don't need to do this unless you have previously created your own configs which conflict.

Prepare for adding a new site

Now that you have a basic VirtualHost macro, it's simple to add a new site in a few easy steps:

  1. Add a new line describing the site to your config
  2. Create the directory to store the website's files
  3. Configure your DNS accordingly to point to your web server

For example, you want to add a new website example-three.co.uk to your virtual hosts. You chose to store your sites under the /var/vhosts/<domain> directory.

Step one

Edit your mod_macro config file to add the new website. e.g.
sudo nano /etc/apache2/conf-available/mymacros.conf

Then add additional site to the bottom of the macro file:

## Define a VHost Macro for repetitive configurations
<Macro VHost $host $port $dir>
  Listen $port
  <VirtualHost *:$port>
    ServerName $host
    DocumentRoot "$dir"

    # Public document root
    <Directory "$dir">
      Require all granted
    </Directory>
  </VirtualHost>
</Macro>
## Use of VHost with different arguments.
Use VHost example-one.com 80 /vhosts/example-one.com/htdocs
Use VHost example-two.com 80 /vhosts/example-two.com/htdocs
Use VHost abc-example.com 80 /vhosts/abc-example.com/htdocs
Use VHost example-three.co.uk 80 /vhosts/example-three.co.uk

Notice the additional line at the end of the config file, it reads:

"Use VHost example-three.co.uk 80 /vhosts/example-three.co.uk"

Create your virtual host directories

Note: Do not blindly give Apache permissions to directories, this will lead an insecure configuration. See the Apache Directory Docs for more information.

Creating the directory

In this article, we chose to use the directory /vhosts/<domain> but you might choose to use another directory which is fine. Just make sure Apache has access to the directory you wish to use.

Create the directory: mkdir /vhosts/example-three.co.uk

Add a simple 'hello world' file for your site. For example
echo "Hello world:example-three.co.uk" > /vhosts/example-three.co.uk/index.html

Assign apache owner*: sudo chown -R www-data /vhosts/example-three.co.uk

'www-data' is presuming you are running Ubuntu, which usually creates and runs apache as that user upon installing Apache.

*Note: This causes all different sites' files to be owned by the same user which may or may not be the configuration you want for your server. An improvement upon this configuration could be to use mod_privileges which allows different VirtualHosts to run as different users thus allowing the ownership of files to be only to those VirtualHosts.

Reload Apache's new Vhost mod_macro configuration

Now you should ask Apache to load in this new configuration:
sudo service apache2 reload
If the above command doesn't report any errors, your're confident that Apache has accepted this config as valid.

If not, check your syslog & apache error log for any erors:

#######Check Apache's error log
tail -f /var/log/apache2/error.log - Read the last new lines, is Apache mentioned anywhere, are there any distinct error messages?
#######Check the server's syslog (if needed)
tail -f /var/log/syslog

Test your site in the browser

After reviewing your logs, and resolving any issues there you should be able to load this new website and see the 'hello world' page created earlier.

The process can be repeated for additional sites which greatly simplifies mass VirtualHost hosting using Apache.