I have recently setup mass virtual hosting in Apache so that all we need to do is create a directory to create a new vhost. We're then also using wildcard DNS to map all subdomains to the server running our Apache instance.

This works excellently, however I'm now having trouble configuring it to fail-over to an appropriate default/error-page when the vhost directory does not exist.

The problem appears to be conflated between by my desire to handle the two error conditions:

  1. vhost not found i.e. there was no directory found matching the host supplied in the HTTP host header. I'd like this to display an appropriate site not found error page.
  2. The 404 page not found condition of the vhost.

Additionally I have a specialised "api" vhost in its own vhost block.

I've tried a number of variations and none seem to exhibit the behaviour I want. Here's what I'm working with right now:

NameVirtualHost *:80
<VirtualHost *:80>
    DocumentRoot /var/www/site-not-found
    ServerName sitenotfound.mydomain.org

    ErrorDocument 500 /500.html
    ErrorDocument 404 /500.html

<VirtualHost *:80>
    ServerName api.mydomain.org
    DocumentRoot /var/www/vhosts/api.mydomain.org/current
    # other directives, e.g. setting up passenger/rails etc...

<VirtualHost *:80>
    # get the server name from the Host: header
    UseCanonicalName Off
    VirtualDocumentRoot /var/www/vhosts/%0/current
    # other directives ... e.g proxy passing to api etc...
    ErrorDocument 404 /404.html

My understanding is that the first vhost block is used as the default, so I have this here as my catch all site. Next I have my API vhost, and then finally my mass vhost block.

So for a domain that doesn't match the first two ServerName's and has no corresponding directory in /var/www/vhosts/ I'd expect it to fall-over to the first vhost, however with this setup, all domains resolve to my default site-not-found. Why is this?

By putting the mass-vhost block first, I can get the mass-vhosts to resolve properly, but not my site-not-found vhost... and in this case I can't seem to find a way to distinguish between a page-level 404 in the vhost, and the case where the VirtualDocumentRoot fails to find a vhost directory (this appears to use the 404 also).

Any help out of this bind is much appreciated!


I'd expect it to fall-over to the first vhost, however with this setup, all domains resolve to my default site-not-found. Why is this?

There's no fail-over logic between different virtual hosts - once a request is assigned to one, it's final.

When you have no ServerName or ServerAlias in your dynamic vhost block, you're depending on the "first vhost to load is default" behavior to assign requests to that vhost. When it's not the first vhost to load, it's essentially inert; there's no way for it to get a request.

My recommendation for how to handle this is to have the "site not found" behavior be either a proxy or a redirect to a working site (which then serves up a "no content here!" page), instead of a variant of your 404 page.

Move the sitenotfound.mydomain.org vhost down, and get the dynamic one back at the top so that it's default. We'll use it to serve up our friendly "no site here" page.

Then, let's give the dynamic vhost the ability to check whether a site exists before serving content from it. Add to within its vhost:

RewriteEngine On
# If there's no directory where it should be for this host..
RewriteCond /var/www/vhosts/%{HTTP_HOST} !-d
# (or a symlink, we'll be ok with those too)
RewriteCond /var/www/vhosts/%{HTTP_HOST} !-l

# Then, we'll redirect the user to our friendly "no site here" page..
# Note that I'm setting it to 302 so that they won't be cached, since
# you might trigger this accidentally just before a new site goes live..
RewriteRule ^ http://sitenotfound.mydomain.org/invalid-site.html [R=302,L]

# Or if you wanted to proxy instead of redirecting, use this instead:
#RewriteRule ^ http://sitenotfound.mydomain.org/invalid-site.html [P,L]

So, the dynamic host will now check for the existence of the site directory before serving content from it, and either redirect or proxy the user to a friendly explanation page. Does this behavior sound like it'll fit your needs?

  • Thanks a bunch for a very clear answer! I was beginning to think I'd need a rewrite to solve it, but wasn't sure how it'd interact with VirtualDocumentRoot. This works perfectly. – Rick Moynihan Sep 3 '12 at 10:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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