Do you use let's encrypt?





1009 votes ~ 8 comments

 

Simplifying repetitive Apache configuration with mod_macro

Posted by Steve on Wed 9 Dec 2015 at 12:34

Apache is one of the more flexible webservers, and most of this is achieved via the use of various extension modules bundled with it, or externally available. mod_macro is a great module allowing you to simplifying configuration of multiple virtual hosts enormously.

Some of the available Apache modules, such as as mod_rewrite, are well-known, but others seem to be little-loved. In my opinion mod_macro is one module that should be much more popular than it seems to be!

The goal of mod_macro is two-fold:

  • To allow you to define macros.
  • To allow you to expand previously defined macros.

Why might you do this? Just to cut down on configuration inside your virtual hosts. This is particularly useful if you've started using the Let's Encrypt SSL provider, for example, but even without that if you have many virtual host definitions that contain repetition it is worth taking a look at it.

Imagine you have a webserver hosting multiple sites, you probably have a bunch of files beneath /etc/apache2/sites-enabled/, each one looking like this:

<VirtualHost 1.2.3.4:443>

  ServerName www.example.com

  SSLEngine On
  SSLProtocol all -SSLv2 -SSLv3
  SSLHonorCipherOrder On
  SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH EDH+aRSA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4"

  SSLCertificateFile    /etc/apache2/ssl/example.com.crt
  SSLCertificateKeyFile /etc/apache2/ssl/example.com.key
  SSLCertificateChainFile  /etc/apache2/ssl/le/bundle.pem

  Redirect / https://example.com/
</VirtualHost>

<VirtualHost 1.2.3.4:443>
  ServerName example.com

  SSLEngine On
  SSLProtocol all -SSLv2 -SSLv3
  SSLHonorCipherOrder On
  SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH EDH+aRSA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4"

  SSLCertificateFile    /etc/apache2/ssl/example.com.crt
  SSLCertificateKeyFile /etc/apache2/ssl/example.com.key
  SSLCertificateChainFile  /etc/apache2/ssl/le/bundle.pem

  DocumentRoot /srv/example.com/public/htdocs
</VirtualHost>

Wouldn't it be simpler if you could replace those big blocks of SSL configuration with just a single line? After all the only thing that would vary across sites is the path to the certificate file(s).

mod_macro allows you to do that exact thing, and can be used pretty simply, we just need to enable the module, then define the macros we're going to use. To enable the module run:

# a2enmod macro

Then define our macros in a suitable configuration-file:

  • For Apache 2.2.x - on wheezy:
    • /etc/apache2/conf.d/macro.conf
  • For Apache 2.4.x - on jessie:
    • /etc/apache2/conf.enabled/macro.conf

Here's a simple definition of an SSL-macro:


<Macro SSL $file>
    SSLEngine On
    SSLProtocol all -SSLv2 -SSLv3
    SSLHonorCipherOrder On
    SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH EDH+aRSA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4"
    SSLCertificateFile    /etc/apache2/ssl/$file.crt
    SSLCertificateKeyFile /etc/apache2/ssl/$file.key
    SSLCertificateChainFile  /etc/apache2/ssl/le/bundle.pem
</Macro>

Notice how the macro definition has the argument "$file" used in the definition, and then inline in the body? That's how you pass "variables" to your macro.

With this defined we can now simplify our previous configuration file to read:

<VirtualHost 1.2.3.4:443>
  ServerName www.example.com
  use SSL example.com
  Redirect / https://example.com/
</VirtualHost3>

<VirtualHost 1.2.3.4:443>
  ServerName example.com
  use SSL example.com
  DocumentRoot /srv/example.com/public/htdocs
</VirtualHost3>

My personal Apache deployment tends to have a bunch of virtual hosts which just proxy to servers running on localhost, for that I've defined the following macro:

<Macro Proxy $port>
    <Proxy *>
        Order allow,deny
        Allow from all
    </Proxy>
    ProxyPass        / http://localhost:$port/
    ProxyPassReverse / http://localhost:$port/
    <Location />
        Order allow,deny
        Allow from all
    </Location>
    ProxyPreserveHost on
    ProxyBadHeader ignore
</Macro>

Now I can define some hosts using it like so:

# All traffic goes to 127.0.0.1:2013
<VirtualHost 80.68.84.111:80 [2001:41c8:10b:103::111]:80>
   ServerName blog.steve.org.uk
   Use Proxy 2013
</VirtualHost>

# All traffic goes to 127.0.0.1:2004
<VirtualHost 80.68.84.111:80>
   ServerName ipv4.steve.org.uk
   Use Proxy 2004
</VirtualHost>

This setup is very simple to understand, use, and cuts down enormously on configuration.

For further details on using the module please do consult the Apache documentation.

 

 


Re: Simplifying repetitive Apache configuration with mod_macro
Posted by Anonymous (82.69.xx.xx) on Fri 4 Mar 2016 at 11:51
Interesting, I wasn't aware of this functionality. I'll have to take a look and see whether it's an alternative to using Jinja templates in Ansible.

[ Parent | Reply to this comment ]