If you're like me, you've figured out how to install and configure your very own web development environment on Mac OS X. You've got Apache. You've got PHP. You've got MySQL (and phpMyAdmin, too). And, like a proud father, you've already cranked out a bunch of whiz-bang, dynamic web sites -- all on a Mac.
But, as your kids grow older, they're bound to go through some growing pains. And one of the first things you'll need to figure out is where to store your web site's files. Should they be in the Sites folder? The Documents folder? What are your options?
Here are three common approaches -- which address the needs of basic, intermediate, and advanced web developers.
If you're just beginning to experiment with web development on Mac OS X, storing files in your Sites folder (AKA ~/Sites/) is definitely your best option. (Note: if you're already a Mac web-dev whiz, you can definitely skip this part.)
If you haven't already, make sure you enable Web Sharing (via System Preferences->Sharing), so that your copy of the Apache web server is fired up and ready to serve.
Once you've started web serving, to access any file or directory in your ~/Sites/ folder, just type
127.0.0.1 (also referred to as "localhost") into your browser, followed by your user name, and then the file or directory name you wish to access, like so:
~/Sites/ --------> http://127.0.0.1/~your_user_name/ ~/Sites/site/ -----> http://127.0.0.1/~your_user_name/site ~/Sites/page.html ---> http://127.0.0.1/~your_user_name/page.html
Each time you start working on a new web site, all you need to do is create a directory for the new site, drag it into your Sites folder, and, voila, that site is now being served!
So let's step things up a notch. Let's say you already have an existing file structure for your projects, and you're none too pleased about having to move everything over to the Sites folder. What do you do?
Easy! Just add a couple of aliases to your Apache config file (/etc/httpd/httpd.conf) and you'll be able to serve your web sites from wherever they happen to be located -- not just from the Sites folder.
There's one catch, though. Like many of OS X's UNIX underpinnings, your Apache config file is hidden from view. So the first thing you need to do is get a tool that will let you open the config file. To do this, you should use a text editor capable of opening and editing hidden files (like BBEdit) or, alternately, use a utility like TinkerTool that can enable the Finder to show all hidden files. (Note: it's always a good idea to back the config file up before making any changes.)
OK, so once you've got that sucker open, scroll down to the Aliases section and take a look. Here's how it should look:
Alias /icons/ "/usr/share/httpd/icons/" <Directory "/usr/share/httpd/icons"> Options Indexes MultiViews AllowOverride None Order allow,deny Allow from all </Directory>
As you can see, each alias contains two parts: an
Alias directive, which is the actual name used to access your site from the browser (as in
http://127.0.0.1/alias), and then a
<Directory> tag, which points to the actual location of the files you wish to serve.
Let's say you want to serve up some files from a project that's stored deep down in your Document directory, such as /Users/your_name/Documents/Clients/Client 4/site/. Just add a new set of
Directive commands to your config file, like so:
Alias /icons/ "/usr/share/httpd/icons/" Alias /client4/ "/Users/your_name/Documents/Clients/Client 4/site/" <Directory "/usr/share/httpd/icons"> Options Indexes MultiViews AllowOverride None Order allow,deny Allow from all </Directory> <Directory "/Users/yourname/Documents/Clients/Client 4/site/"> Options Indexes MultiViews AllowOverride None Order allow,deny Allow from all </Directory>
Once you've made these changes, save your httpd.conf file and restart Apache (by turning Web Sharing off and then back on again in the Sharing pane in System Preferences).
Now, you should be able to access your new project by just entering
http://127.0.0.1/client4/ straight into your browser! (And, of course, for each additional site you wish to serve from outside your Sites folder, just add a new Alias/Directory combo, restart your server again, and you're good to go.)
But wait, there's a catch -- and, if you're using PHP, it's an important one.
By default, PHP is configured to work properly with any files in your Sites directory. But should you serve files from a different location, you'll need to tweak your PHP configuration file, as well.
Now -- don't get scared on me -- the truth is Mac OS X, by default, doesn't have a php.ini file. So you'll actually need to make your own! But don't worry. It's easy.
Now that you're all set, open up your new php.ini file and scroll down to the Paths and Directories section, which should look like this:
;;;;;;;;;;;;;;;;;;;;;;;;; ; Paths and Directories ; ;;;;;;;;;;;;;;;;;;;;;;;;; ; UNIX: "/path1:/path2" ;include_path = ".:/php/includes"
First, remove the semi-colon in front of
include_path, so that we can enable includes.
include_path = ".:/php/includes"
I know what you're thinking -- "Why do we need to tweak our include path, Patrick?" Well, dear Mac web developer, it turns out that PHP apps often rely on something called the
include() command, which, you guessed it, allows PHP to include (or load) external files. Being a talented Mac OS X web developer, you'll probably wish to enable this feature at some point, either for use in other people's code or your own.
So, next, as you can probably guess, you need to add the directory from our earlier example to the
include_path variable, so that PHP will work in this directory the same way it works in the Sites folder. (Use this trick each time you add a new alias to Apache's config file that might use PHP, separating each new include path with a colon, as in the example below.)
include_path = ".:/php/includes:/Users/your_name/Documents/Clients/ Client 4/site/"
Ok, that's it! You're now fully set up to serve both HTML and PHP files using aliases!
But wait! There's more! This next option is the trickiest of the three, but it offers the greatest ability to make your local development server truly function like a production server.
And this gets to why I wrote this article in the first place. I had to figure out how to enable virtual hosts over the weekend -- and a thousand Google searches later, I realized that while there may be a cornucopia of documentation on Apache, MySQL, PHP, and the like, virtually none of it deals with Mac OS X! (Come on, people! Start documenting your experiences with this stuff, will ya?)
OK, with my rant out of the way, let's get busy with this virtual host stuff. Basically, with virtual hosts, a single Apache web server can serve multiple web sites from the same IP address. And not only that, you can actually use different, customized domain names for each web site.
In other words, instead of accessing files through
127.0.0.1, you can use a real (or simulated) domain name. So, to the untrained eye, your local web site will look like it's being served straight off the web — without any
Not only are there a lot of technical benefits to doing things this way (support for absolute file paths, no need to mess with PHP includes, etc.), but this stuff is perfect for client demos! You can run presentations straight off of your PowerBook and no one ever needs to know you're not on the Web.
Since this is exactly the sort of thing that many web developers on OS X really need, let's set up some virtual hosts!
To get started, scroll down to the very bottom of your Apache config file (/etc/httpd/httpd.conf) and find the
# Use name-based virtual hosting. # #NameVirtualHost
First, let's enable name-based virtual hosts, which we'll do by removing the
# comment prefix from the last line.
# Use name-based virtual hosting. # NameVirtualHost
Next, let's specify the IP address to which our name-based virtual host names will resolve: which, of course, is our old friend
# Use name-based virtual hosting. # NameVirtualHost 127.0.0.1
Now, we need to set up our
VirtualHost directives. Using the example provided in the Apache config itself, we'll first add a virtual host for our existing Sites folder. We do this to ensure that we'll still be able to access web sites stored in the Sites folder using our existing
127.0.0.1-based addresses once we've enabled virtual hosts.
As you can see, we place
127.0.0.1 in the
ServerName field, and then, with
DocumentRoot, we specify where the files for our virtual host are stored -- the Sites folder.
<VirtualHost 127.0.0.1> ServerName 127.0.0.1 DocumentRoot /Users/your_name/Sites </VirtualHost>
With that behind us, we'll now add a
VirtualHost directive using the same logic, but this time, we'll do it using my web site iCalShare as an example.
Since we still need to access the real iCalShare web site, we can't use the
icalshare.com domain for our virtual host. If we did use that domain, whenever we entered
icalshare.com into our browser, it wouldn't know whether to load the local site, or the external one.
Since this is a test server, we'll append a "test" subdomain to our primary domain name, making our complete server name
test.icalshare.com. That name won't conflict with the existing iCalShare domain name, and it also tells us a little about the purpose of this server.
So let's place our new name in both the
ServerName tags. And, then, once again, we'll use
DocumentRoot to point to the location of the files for this site, which are stored a few levels down in our Documents folder.
<VirtualHost test.icalshare.com> DocumentRoot /Users/patrick/Documents/Projects/iCalShare/wwwroot ServerName test.icalshare.com </VirtualHost>
Now I bet you're asking, "How does my browser know that
test.icalshare.com is a local request, and that
icalshare.com is a remote one?" Good question! And the answer is ... because we're going to tell it!
The Web as we know it is actually strung together using IP addresses, not domain names. Each time you enter a web site domain name into your browser, it's actually translating that name into an IP address, which it does by checking with a DNS server. Once the DNS server finds an IP address match for the domain name you entered, you're magically transported to the web site you're seeking.
As it turns out, with Mac OS X, when you enter a domain name, your browser first checks with /etc/hosts to see if there's a matching IP address. If no match is found, the browser will forward the domain name on to a DNS server. So, by editing /etc/hosts, you can actually change where your browser goes when you enter various domain names. And this is exactly how we'll get your machine to recognize the virtual hosts we set up earlier.
So, open up your /etc/hosts file, and you should be looking at something like this:
127.0.0.1 localhost 255.255.255.255 broadcasthost ::1 localhost
To enable the virtual host we set up earlier, just add a new entry to the file, as we've done below for our iCalShare example.
127.0.0.1 localhost 127.0.0.1 test.icalshare.com 255.255.255.255 broadcasthost ::1 localhost
For each virtual host you need, just create a new line that begins with
127.0.0.1, followed by a space or tab, and then the actual domain name.
So that's it! Save your /etc/httpd/httpd.conf and /etc/host files, restart Apache, and your vanity domain should now work like magic!
(Note: I've only touched the surface of all of the nifty things you can do with virtual hosts. Further reading on this topic is recommended.)
And, now patient readers, in the tradition of the great Jerry Springer, I leave with you a final thought ... get out there and go crazy with this stuff! And if you discover something cool in your web-development-on-OS-X travels, don't forget to share it!
Patrick Crowley is the creator of iCalShare, the iCal calendar directory, which was recently featured in Steve Jobs' keynote speech at Macworld San Francisco 2003.
Return to MacDevCenter.com
Copyright © 2009 O'Reilly Media, Inc.