oreilly.comSafari Books Online.Conferences.


AddThis Social Bookmark Button

Virtual Hosts, mod_rendezvous_apple, and Apache on Mac OS X

by Joe Maller

Editor's note -- In this article, Joe Maller shows you a three-step workaround for serving locally-named virtual hosts to Rendezvous clients.

Apple's recent 10.2.4 update for OS X introduced a Rendezvous Apache module for serving locally hosted sites to nearby Rendezvous-enabled computers. This is a fantastic addition because whenever I visit the office, everyone has instant access to the sites I'm working on.

Well, it's almost perfect. So far there doesn't appear to be a way to successfully serve Virtual Hosts with all their features enabled. This is a very unfortunate omission which led me to discover the workaround described in this article.

Since switching to OS X, I've been using Virtual Hosts and Apache to serve local copies of the web sites I'm working on. This isn't all that complicated because Personal Web Sharing in OS X is really just a GUI for Apache. Since most of the Internet runs on Apache servers, it's a great way to test sites before uploading. I also found it helped me quickly learn lots of other server-related technologies since I was free to tinker and take things apart with full access and without having to worry about breaking someone else's computer.

Related Reading

Mac OS X in a Nutshell
A Desktop Quick Reference
By Jason McIntosh, Chuck Toporek, Chris Stone

The workaround is something of a hack since it involves IP Virtual Hosts, Name Base virtual hosts, creating a dynamic index file, and a lot of monkeying around in httpd.conf. Essentially this process uses Rendezvous for initial server discovery, then uses IP virtual hosts for the actual serving. These instructions assume you've already got virtual hosts working--I talked about getting mine set up in a weblog I wrote back in June 2002.

1. In httpd.conf, modify the mod_rendezvous_apple directives

The default settings for this module will register sites for each user on a machine as well as the machine itself. Since these overlap and show my default site twice, I disabled them and added a specific named resource pointing to my Sites directory.

Confusingly, mod_rendezvous apparently uses whatever is set by mod_userdir earlier in httpd.conf. This comes preset to 'Sites', so any url with a '~user' will automatically point to ~/Sites in that user's home folder. Since all my virtual hosts point directly to specific directories and I'm the only one using this machine, I commented out the userdir lines. After deleting out the rest of the mod_rendezvous commands, I was left with this:

<IfModule mod_rendezvous_apple.c>
RegisterResource "Joe's Staging Sites" "/"

With this in place, other machines on the local network now see this machine as a Rendezvous web server with the name "Joe's Staging Sites".

2. Duplicate named virtual hosts as IP virtual hosts

My httpd.conf file has a half-dozen named virtual hosts serving locally which I also want to share over Rendezvous. Because there doesn't seem to be a way to show virtual hosts individually in mod_rendezvous, I decided to hack around the problem by making them all IP-named hosts as well.

After stumbling around for awhile and reading the Apache Virtual Host 'in depth' docs several times, I finally realized that a single directive would not work as both a named virtual host and an IP virtual host. IP hosting overrode the name. The solution was to create two separate virtual host directives for each site.

The duplicate virtual host blocks will use specific ports to serve different sites, so the default site needs to be modified first so that it responds specifically to requests on port 80 (the default http port). This is the beginning of the revised virtual hosts section:

NameVirtualHost *

Listen 80
<VirtualHost *:80>
    DocumentRoot "/Users/joe/Sites/"
    ServerName localhost

The listen directive tells Apache to respond to any requests on the specified port.

Next, all the existing and working named virtual host blocks should have port 80 added to their name declarations:

<VirtualHost *:80>

Finally, the whole virtual host block is duplicated. Add a listen directive before the copy, change the listening port, and delete the ServerName directive. The standard virtual host blocks for sites on my laptop now looks like this:

<VirtualHost *:80>    
    ServerName  joesfilters.joe    
    DocumentRoot "/Users/joe/Sites/"
    <Directory "/Users/joe/Sites/">
        AllowOverride All
        Options All

Listen 9000
<VirtualHost *:9000>
    DocumentRoot "/Users/joe/Sites/"
    <Directory "/Users/joe/Sites/">
        AllowOverride All
        Options All

According to a comment at the original virtual hosting article, ports over 8080 are rarely used by Unix systems and can safely be assigned to new hosts. My sites start at 9000 and count up, but the number choice is arbitrary.

Repeat the duplication steps for each additional virtual host incrementing the second port number, and restart Apache. One way is to toggle the Web Sharing checkbox in System Preferences > Sharing. A faster way is to use the apachectl command in the terminal. I use this one to check the configuration file's syntax and restart the server in one command:

sudo apachectl configtest ; sudo apachectl restart

Using the up arrow in the terminal accesses the previous command history, so that doesn't even need to be retyped.

3. Build a dynamic page pointing to IP virtual hosts

With the above settings, the main Sites directory will show up in Rendezvous, and each site will be accessible by attaching the corresponding port onto the machine's IP address. A dynamic index file in the Sites directory bridges these two together so machines can discover my computer via Rendezvous and link directly to each local site.

Because this computer often has different IP addresses assigned by whichever wireless network it's on, hard-coding the IP locations of each site won't work. Instead I used a little PHP to embed the current IP address into a link. PHP's global $_SERVER array contains a ton of useful information. This simple command uses the current IP address to build a dynamic link:

<?php echo "<a href='http://$_SERVER[SERVER_ADDR]:9000'> joesfilters</a>" ?>

Repeat that for each site, making sure the port numbers match the names.

Looking forward

This process is definitely a workaround for features that will hopefully appear in future revisions of mod_rendezvous_apple. It would be wonderful if the module would just notice and serve each named virtual host using its assigned name. Until then, this will allow everything to work.

Joe Maller is an author, developer and digital artist based in New York City.

Return to Mac DevCenter.