Using variables in Apache config files to reduce duplication?

You could use mod_macro, which has been included in Apache httpd since version 2.4

Before that it had to be installed separately, see mod_macro. For example on Debian: apt-get install libapache2-mod-macro; a2enmod macro.

Example configuration

/etc/apache2/conf.d/vhost.macro

<Macro VHost $host $port>
  <VirtualHost $host:$port>

    ServerName $host
    DocumentRoot /var/vhosts/$host

    <Directory /var/vhosts/$host>
      # do something here...
    </Directory>
  </VirtualHost>
</Macro>

/etc/apache2/sites-available/vhost.mysite.com

Use VHost vhost.mysite.com 80

Much simpler using Define keyword. See Define Directive.

Define RVM_ROOT /opt/rvmdir/gems
Define RUBY_18 ruby-1.8.7-head

...

SetEnv GEM_HOME ${RVM_ROOT}/${RUBY_18}@typo55
SetEnv GEM_PATH ${RVM_ROOT}/${RUBY_18}@typo55:${RVM_ROOT}/${RUBY_18}@global

You can enable or disable bits of configuration with IfDefine but that probably won't do what you want. Instead, You can set environment variables in your Apache init script to access within the configuration. For example, adding:

HOSTNAME=$(hostname)

to /etc/init.d/httpd (before the line that calls httpd!) on a RHEL machine passes the machine's hostname in as a variable. It doesn't have to be the output of a command -- anything that sets a variable in the environment which launches httpd is fine. Variables can be used in the configuration like so:

[root@dev ~]# cat /etc/httpd/conf.d/test.conf
Header set X-Hostname ${HOSTNAME}

[root@dev ~]# GET -Sed http://localhost
GET http://localhost --> 200 OK
Connection: close
Date: Fri, 11 Sep 2009 20:47:13 GMT
Server: Apache/2.2.3 (Red Hat)
Content-Length: 525
Content-Type: text/html;charset=ISO-8859-1
Client-Date: Fri, 11 Sep 2009 20:47:13 GMT
Client-Peer: 127.0.0.1:80
Client-Response-Num: 1
Title: Index of /
X-Hostname: dev.local

Of course, you're not restricted to the Header directive. The variables can be used anywhere, like <Directory ${FOO}> etc.

If you don't like this (and it's not that nice..) you can generate a configuration from a template using m4 or some other template language.

ADDITIONAL:

Hrm, one way to make it better would be to store all the variables in an external file, perhaps /etc/httpd/conf/variables.txt:

FOO=/path/to/dir
ROLE=development

and then include these into your Apache init.d script with:

. /etc/httpd/conf/variables

before calling httpd. Still not brilliant but at least it separates the startup script and variables.