Setting Up a Web Server with Web Sharing

You don’t need to install Lion Server to set up a web server on Mac OS X. Lion (as does any version of Mac OS greater than 10.3) is equipped with Apache, the web server that is estimated to serve 63% of all websites1. Apache is included with Lion for Web Sharing, and can be started using the checkbox in Sharing Preferences. If you want a more advanced web server, it is also easy to start caching your web pages, and storing data with MySQL.

Apache

At first, your web root (http://localhost/) is set to /Library/WebServer/Documents, and your user folder accessible at http://localhost/{{YOUR USERNAME}}. However, this is easy to amend by changing Apache’s configuration file, which is located at /etc/apache2/httpd.conf. Replace line 238 with the below (substituting in your username):

DocumentRoot "/Users/{{YOUR USERNAME}}/Sites"

And, to allow access to this directory, replace line 265 with the following:

<Directory "/Users/{{YOUR USERNAME}}/Sites">

I chose to turn all the Options off by replacing line 278 with:

    Options None

I also allowed .htaccess files to change some aspects of the configuration for select folders using:

    AllowOverride All

This allows a lot of web applications to function properly — for example Wordpress permalinks. For Wordpress to work, PHP must also be enabled, so I uncommented line 111:

LoadModule php5_module libexec/apache2/libphp5.so

I also commented out line 403, and lines 418 to 423 to disable the default server scripting directory:

    #ScriptAliasMatch ^/cgi-bin/((?!(?i:webobjects)).*$) "/Library/WebServer/CGI-Executables/$1"

and

#<Directory "/Library/WebServer/CGI-Executables">
#    AllowOverride None
#    Options None
#    Order allow,deny
#    Allow from all
#</Directory>

Finally, I commented out line 617. This line allows access to users’ Sites directories. We have already allowed access to what we need, so we can and should comment out this line to stop any other users’ Sites directories being exposed:

#Include /private/etc/apache2/extra/httpd-userdir.conf

Your file should now end up looking like this one. Once you have made your changes, restart Apache. You can do this using the checkbox in Sharing Preferences, or typing the following into Terminal:

sudo /usr/sbin/apachectl restart

Varnish

Although Varnish, a caching engine, can be installed manually, it can be far easier installed using Homebrew. It’s as simple as:

brew install varnish

Once you have installed Varnish, it can be configured using the Varnish Configuration Language (VCL). But we must tell Apache to use a port other than port 80 if we wish to do our caching on the default HTTP port. To do this, open up your httpd.conf file again and modify line 52 to read:

Listen 8000

Now, restart Apache (sudo /usr/sbin/apachectl restart) and you should find it is running on port 8000 (serving your web directory at http://localhost:8000/). Now, open up your Varnish configuration file, which will be located at /usr/local/etc/varnish/default.vcl if you installed Varnish using Homebrew, and set up the default backend — what Varnish will cache:

backend default {
    .host = "127.0.0.1";
    .port = "8000";
    .probe = {
         .url = "/";
         .interval = 2s;
         .timeout = 2 s;
         .window = 5;
         .threshold = 3;
    }
}

The probing function loads the URL specified at the interval specified, and if the URL loads slower than the timeout value (or gives an error message), it marks the backend sick. This health value can be used in the configuration (.healthy), for example, to cache content longer if the server is misbehaving like so:

sub vcl_recv {
    if (req.backend.healthy) {
        set req.grace = 30s;
    } else {
        set req.grace = 1h;
    }
}

sub vcl_fetch {
    set beresp.grace = 1h;
}

You can also set HTTP headers in the configuration file. I send two custom headers, X-Varnish-Cached and X-Apache-Health. These headers describe whether the request was cached and whether Apache is healthy respectively.

sub vcl_deliver {
    if (obj.hits > 0) {
        set resp.http.X-Varnish-Cached = "HIT";
    } else {
        set resp.http.X-Varnish-Cached = "MISS";
    }

    if (req.grace == 30s) {
        set resp.http.X-Apache-Health = "Healthy";
    } else {
        set resp.http.X-Apache-Health = "Sick";
    }
}

To start Varnish automatically at boot, create a file named com.varnish.varnishd.plist and save it in the /Library/LaunchDaemons folder. Open it in a plain text editor, and give it the following contents:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Disabled</key>
	<false/>
	<key>GroupName</key>
	<string>wheel</string>
	<key>UserName</key>
	<string>root</string>
    <key>Label</key>
    <string>com.varnish.varnishd</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/sbin/varnishd</string>
        <string>-f</string>
        <string>/usr/local/etc/varnish/default.vcl</string>
        <string>-s</string>
        <string>malloc,1G</string>
        <string>-T</string>
        <string>127.0.0.1:2000</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>

The malloc,1G states that 1GB of RAM will be used for Varnish. Now open Terminal, and enter the following commands:

sudo chown root /Library/LaunchDaemons/com.varnish.varnishd.plist
sudo launchctl load /Library/LaunchDaemons/com.varnish.varnishd.plist

Varnish should now launch at boot.

MySQL

Currently, the MySQL formula for Homebrew is broken, so you will need to use the package installer. The preference pane and startup item are broken, so skip those. Once you have installed MySQL, you can start it using:

sudo /usr/local/mysql/bin/mysqld_safe

To change the root password, which is by default blank, enter the following command into Terminal, substituting your desired password:

mysqladmin -u root password {{NEWPASSWORD}}

To make MySQL start at boot, create a file named com.mysql.mysqld.plist and add it to the /Library/LaunchDaemons directory. Use a plain text editor to give it the following contents:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>KeepAlive</key>
    <true/>
    <key>Label</key>
    <string>com.mysql.mysqld</string>
    <key>Program</key>
    <string>/usr/local/mysql/bin/mysqld_safe</string>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>

Load it into launchd by typing the following commands into Terminal:

sudo chown root /Library/LaunchDaemons/com.mysql.mysqld.plist
sudo launchctl load /Library/LaunchDaemons/com.mysql.mysqld.plist

I recommend you use a program like Sequel Pro to administer MySQL. Sequel Pro is a fully-featured and open-source program that provides a graphical user interface for easy management of MySQL.

With Apache, Varnish, and MySQL setup, you have a powerful web server running on your Mac. Mac OS X includes Ruby, Python, and Perl, which you can also use for web development.

  1. As of May 2011: May 2011 Web Server Survey