Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I have a personal web site with a slightly nontrivial Apache configuration. I test changes on my personal machine before uploading them to the server. The path to the files on disk and the root URL of the site are of course different between the test and production conditions, and they occur many places in the configuration (especially <Directory> blocks for special locations which have scripts or no directory listing or ...).

What is the best way to share the common elements of the configuration, to make sure that my production environment matches my test environment as closely as possible?

share|improve this question
add comment

5 Answers

My own answer: What I've thought of is to use SetEnv to store the paths for the current machine in environment variables, then Include a common configuration file with ${} everywhere there's something machine specific. But I have never used these facilities before, and I don't know if there's some caveat.

share|improve this answer
    
Turns out that this feature, which I thought I read about somewhere, doesn't actually exist. Never mind! –  Kevin Reid May 31 '10 at 20:18
add comment

Now this is no direct answer to your question, because it involves a change of setup, but to avoid exactly this problem, I will virtualize both my test system and my production server. I hope that this will give me less hassle with configuration as i will run identical images and add easy scalability or redundancy in the future.

Maybe you have the opportunity to run virtualized....

You should also have a look at those two threads about versioning and duplicating server configurations and moving installed linuxes between platforms

share|improve this answer
add comment

It could be possible to just set up some scaffolding using sym/hardlinks, change mountpoints etc so that the test environment paths match production. Depending on your particular setup it could be quite easy, or it might be both ugly and complicated..

To access the test environment, use it's IP, or you could add an extra ServerAlias with a name that points to your test environment, or you might just configure the same name for both machines and use your local /etc/hosts to switch which one you want to access.

share|improve this answer
    
The machines are very different platforms; making them similar would be messy for both. I want a way to vary the Apache config, not everything else. And using /etc/hosts in particular would be too broad since I want to be able to access my own live site from my personal machine. –  Kevin Reid May 23 '10 at 15:51
    
Ok, then using some form of variable substitution is most likely a good idea. I can not really help much with that though, but good luck to you! If that fails for some reason, you could always use a sed script or similar to automate search-replace edits.. :) –  sajb May 23 '10 at 16:10
add comment
up vote 0 down vote accepted

I ended up using a configuration template file and a small Python program using the string.Template facility to generate two different configurations. I have included it below.

This substitutes the configuration values into generic.tmpl.conf (which is the site internal configuration), then makes the result available as ${conf} for use in test.tmpl.conf and production.tmpl.conf, which have the VirtualHost block containing ${conf}, log files, and other such host-specific information.

#!/usr/bin/python

import string
from optparse import OptionParser

# ---

parser = OptionParser()
parser.add_option("--clean", dest="clean", action="store_true", default=False,
                  help="Clean files instead of creating them.")
(options, args) = parser.parse_args()
if len(args) != 0:
  parser.error("No non-option arguments expected.")

# ---

def readconf(name):
  return string.Template(open(name).read())

def writeconf(out, outer, inner, fields):
  outerfields = fields.copy()
  outerfields["conf"] = inner.substitute(fields).replace("\n", "\n\t")
  out.write(outer.substitute(outerfields))
  out.close()

# ---

if options.clean:
  os.remove("production.conf")
  os.remove("test.conf")
else:
  commonconf = readconf("generic.tmpl.conf")
  liveconf = readconf("production.tmpl.conf")
  testconf = readconf("test.tmpl.conf")

  writeconf(open("production.conf", "w"), liveconf, commonconf, {
    # ... configuration values redacted ...
  })

  writeconf(open("test.conf", "w"), testconf, commonconf, {
    # ... configuration values redacted ...
  })
share|improve this answer
add comment

Try using <Location> instead of <Directory> where possible, so that changing the DocumentRoot will cover most of your changes. That's probably the easiest way to take care of it.

The Include directive can also be your friend -- you can stick it inside a <Directory> or <Location> block to include the parts of the configuration that won't change between machines.

This is a little more of a hack, but you could also use DirectoryMatch to match both your testing and production directories in one section.

share|improve this answer
    
Using <Location> seems a good idea independently, but it won't actually help here, because the testing setup is http://localhost/test-site/foo as opposed to http://live-site.example.com/foo. –  Kevin Reid May 24 '10 at 2:50
    
In that case, maybe something like <LocationMatch /(test-site/)?foo> would work. A better option might be to set up test-site.localhost as a domain alias, so you can have /foo be the same throughout. I don't envy a setup that has different paths in testing vs. live. –  Steve Simms May 25 '10 at 0:40
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.