Where to Place Local Web Site Content When Using XAMPP on a Mac

W

A web site located on a local computer is accessed in a browser through the URL localhost and normally served by a local Apache server. There are two parts to this process. The first is the resolution of the name localhost to the IPv4 loopback address 127.0.0.1 which is configured in the local computer’s hosts file.

On macOS this is /private/etc/hosts:

##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1       localhost
255.255.255.255 broadcasthost
::1             localhost
The /private/etc/hosts file on macOS

 

 

Throughout the remainder of this article the URL localhost is synonymous with http://localhost, 127.0.0.1 and http://127.0.0.1.

The second part is the configuration of the local Apache server to tell it where to locate and serve the web site’s files. This location is known as the DocumentRoot and is normally configured in a file named httpd.conf. The location of this file will differ depending on how your computer provides a local Apache environment. For XAMPP this is /Applications/XAMPP/xamppfiles/etc/httpd.conf and below is part of that file showing the default DocumentRoot configuration:

# 
# DocumentRoot: The directory out of which you will serve your
# documents. By default, all requests are taken from this directory, but
# symbolic links and aliases may be used to point to other locations.
#
DocumentRoot "/Applications/XAMPP/xamppfiles/htdocs"
<Directory "/Applications/XAMPP/xamppfiles/htdocs">
    #
    # Possible values for the Options directive are "None", "All",
    # or any combination of:
    #   Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
    #
    # Note that "MultiViews" must be named *explicitly* --- "Options All"
    # doesn't give it to you.
    #
    # The Options directive is both complicated and important.  Please see
    # http://httpd.apache.org/docs/trunk/mod/core.html#options
    # for more information.
    #
    #Options Indexes FollowSymLinks
    # XAMPP
    Options Indexes FollowSymLinks ExecCGI Includes

    #
    # AllowOverride controls what directives may be placed in .htaccess files.
    # It can be "All", "None", or any combination of the keywords:
    #   Options FileInfo AuthConfig Limit
    #
    #AllowOverride None
    # since XAMPP 1.4:
    AllowOverride All

    #
    # Controls who can get stuff from this server.
    #
    Require all granted
</Directory>
The default DocumentRoot configuration in /Applications/XAMPP/xamppfiles/etc/httpd.conf

 

 

For requests to localhost, the Apache server in XAMPP serves the file index.php located in the DocumentRoot folder /Applications/XAMPP/xamppfiles/htdocs/:

<?php
	if (!empty($_SERVER['HTTPS']) && ('on' == $_SERVER['HTTPS'])) {
		$uri = 'https://';
	} else {
		$uri = 'http://';
	}
	$uri .= $_SERVER['HTTP_HOST'];
	header('Location: '.$uri.'/dashboard/');
	exit;
?>
Something is wrong with the XAMPP installation :-(
Redirecting to localhost/dashboard in /Applications/XAMPP/xamppfiles/htdocs/index.php

 

 

Line 8 of index.php performs a redirect from localhost to localhost/dashboard/ where Apache serves the XAMPP Welcome Page generated by the file index.html located in /Applications/XAMPP/xamppfiles/htdocs/dashboard/:

The XAMPP welcome page
The XAMPP welcome page

 

 

To have Apache serve your own web site content there are two main options. The first is to place it within the default DocumentRoot. The second is to place it outside of the default DocumentRoot and use the Alias directive to map a URL to this location.

In the following examples, the generic index.php file below is placed within the DocumentRoot or aliased location and simply displays its name and location within the server’s folder structure:

<!doctype html>

<html lang="en">
<head>
	<meta charset="utf-8">
	<title>XAMPP Test</title>
</head>

<body>
  	<p style="font-size:1.5em;">This page was generated by <?php echo $_SERVER['SCRIPT_FILENAME'];?></p>
</body>
</html>
Generic index.php used in examples

 

 

1. Place Web Site Content Within the DocumentRoot

Perhaps the easiest option – and the one requiring least change – is to place your web site content within the default DocumentRoot folder /Applications/XAMPP/xamppfiles/htdocs/ remembering to replace, rename or delete the existing index.php there.

A request to localhost then serves the following page:

Test page for localhost with DocumentRoot set to /Applications/XAMPP/xamppfiles/htdocs
Test page for localhost with DocumentRoot set to /Applications/XAMPP/xamppfiles/htdocs

 

 

An alternative is to re-define the DocumentRoot configuration in /Applications/XAMPP/xamppfiles/etc/httpd.conf to point to another folder and place your web site content in this new location. This folder does not have to be within the /Applications/XAMPP/ folder structure. Below the DocumentRoot is changed to /User/steve/Sites/mysite:

# 
# DocumentRoot: The directory out of which you will serve your
# documents. By default, all requests are taken from this directory, but
# symbolic links and aliases may be used to point to other locations.
#
DocumentRoot "/User/steve/Sites/mysite"
<Directory "/User/steve/Sites/mysite">
    #
    # Possible values for the Options directive are "None", "All",
    # or any combination of:
    #   Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
    #
    # Note that "MultiViews" must be named *explicitly* --- "Options All"
    # doesn't give it to you.
    #
    # The Options directive is both complicated and important.  Please see
    # http://httpd.apache.org/docs/trunk/mod/core.html#options
    # for more information.
    #
    #Options Indexes FollowSymLinks
    # XAMPP
    Options Indexes FollowSymLinks ExecCGI Includes

    #
    # AllowOverride controls what directives may be placed in .htaccess files.
    # It can be "All", "None", or any combination of the keywords:
    #   Options FileInfo AuthConfig Limit
    #
    #AllowOverride None
    # since XAMPP 1.4:
    AllowOverride All

    #
    # Controls who can get stuff from this server.
    #
    Require all granted
</Directory>
Re-defining the DocumentRoot configuration in /Applications/XAMPP/xamppfiles/etc/httpd.conf

 

 

A request to localhost now serves the following page:

Test page for localhost with DocumentRoot set to /Users/steve/Sites/mysite
Test page for localhost with DocumentRoot set to /Users/steve/Sites/mysite

 

 

2. Place Web Site Content Outside the DocumentRoot

There’s another pre-defined location within XAMPP where you can place your site files. This is /Applications/XAMPP/xamppfiles/apache2/htdocs/. Navigating to the end of the Apache configuration file /Applications/XAMPP/xamppfiles/etc/htppd.conf we see:

# XAMPP
Include etc/extra/httpd-xampp.conf
Include "/Applications/XAMPP/xamppfiles/apache2/conf/httpd.conf"
Referencing additional configuration files in /Applications/XAMPP/xamppfiles/etc/htppd.conf

 

 

Below is the /Applications/XAMPP/xamppfiles/apache2/conf/httpd.conf file passed as an argument to the Include statement on line 523:

Alias /bitnami/ "/Applications/XAMPP/xamppfiles/apache2/htdocs/"
Alias /bitnami "/Applications/XAMPP/xamppfiles/apache2/htdocs"

<Directory "/Applications/XAMPP/xamppfiles/apache2/htdocs">
    Options Indexes FollowSymLinks
    AllowOverride All
    Order allow,deny
    Allow from all
</Directory>
Mapping a URL to a directory in /Applications/XAMPP/xamppfiles/apache2/conf/httpd.conf file

 

 

On lines 1 and 2 the Alias directive is used to map a URL containing /bitnami/ or /bitnami to /Applications/XAMPP/xamppfiles/apache2/htdocs/ or /Applications/XAMPP/xamppfiles/apache2/htdocs respectively, allowing Apache to serve files outside of the DocumentRoot. As such, a request to localhost/bitnami should cause Apache to serve /Applications/XAMPP/xamppfiles/apache2/htdocs/index.html.

However out-of-the box, a request to localhost/bitnami results in a 403 Forbidden error:

Error 403 when requesting localhost/bitnami
403 Forbidden error when requesting localhost/bitnami

 

 

To understand why this is happening let’s take a look at another section of the Apache configuration file /Applications/XAMPP/xamppfiles/etc/htppd.conf:

#
# Deny access to the entirety of your server's filesystem. You must
# explicitly permit access to web content directories in other
# <Directory> blocks below.
#
<Directory />
    AllowOverride none
    Require all denied
</Directory>
Denying access to the server’s entire filesystem in /Applications/XAMPP/xamppfiles/etc/htppd.conf

 

 

Using Require all denied, access to the server’s entire filesystem is forbidden and only granted to named directories if explicitly given. As an example, Require all granted explicitly grants access to /Applications/XAMPP/xamppfiles/htdocs as part of the Directory block on line 259 of /Applications/XAMPP/xamppfiles/etc/htppd.conf.

<Directory "/Applications/XAMPP/xamppfiles/htdocs">
    #
    # Possible values for the Options directive are "None", "All",
    # or any combination of:
    #   Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
    #
    # Note that "MultiViews" must be named *explicitly* --- "Options All"
    # doesn't give it to you.
    #
    # The Options directive is both complicated and important.  Please see
    # http://httpd.apache.org/docs/trunk/mod/core.html#options
    # for more information.
    #
    #Options Indexes FollowSymLinks
    # XAMPP
    Options Indexes FollowSymLinks ExecCGI Includes

    #
    # AllowOverride controls what directives may be placed in .htaccess files.
    # It can be "All", "None", or any combination of the keywords:
    #   Options FileInfo AuthConfig Limit
    #
    #AllowOverride None
    # since XAMPP 1.4:
    AllowOverride All

    #
    # Controls who can get stuff from this server.
    #
    Require all granted
</Directory>
Explicitly granting access to an individual directory in /Applications/XAMPP/xamppfiles/etc/htppd.conf

 

 

However, if we look again at /Applications/XAMPP/xamppfiles/apache2/conf/httpd.conf there is no Require all granted. Instead we see Order allow,deny and Allow from all:

Alias /bitnami/ "/Applications/XAMPP/xamppfiles/apache2/htdocs/"
Alias /bitnami "/Applications/XAMPP/xamppfiles/apache2/htdocs"

<Directory "/Applications/XAMPP/xamppfiles/apache2/htdocs">
    Options Indexes FollowSymLinks
    AllowOverride All
    Order allow,deny
    Allow from all
</Directory>
The deprecated Order and Allow directives in /Applications/XAMPP/xamppfiles/apache2/conf/httpd.conf

 

 

The Order and Allow directives are provided by Apache’s mod_access_compat module and as of Apache v2.4 have been deprecated in favour of the Require directive provided by the mod_authz_host module. Both of these modules are loaded by XAMPP so either Order allow,deny together with Allow from all or Require all granted by itself should work, but the Apache documentation states:

Mixing old directives like Order, Allow or Deny with new ones like Require is technically possible but discouraged. mod_access_compat was created to support configurations containing only old directives to facilitate the 2.4 upgrade. Please check the examples below to get a better idea about issues that might arise.

Let’s replace the Order and Allow directives with a single Require directive:

Alias /bitnami/ "/Applications/XAMPP/xamppfiles/apache2/htdocs/"
Alias /bitnami "/Applications/XAMPP/xamppfiles/apache2/htdocs"

<Directory "/Applications/XAMPP/xamppfiles/apache2/htdocs">
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>
Replacing the deprecated Order and Allow directives with the Require directive in /Applications/XAMPP/xamppfiles/apache2/conf/httpd.conf

 

 

A request to localhost/bitnami/ now serves the following page:

Test page for localhost/bitnami aliased to /Applications/XAMPP/xamppfiles/apache2/htdocs
Test page for localhost/bitnami aliased to /Applications/XAMPP/xamppfiles/apache2/htdocs

 

 

As an alternative, we can map a new URL to a new location by adding the configuration to the existing /Applications/XAMPP/xamppfiles/apache2/conf/httpd.conf file:

Alias /bitnami/ "/Applications/XAMPP/xamppfiles/apache2/htdocs/"
Alias /bitnami "/Applications/XAMPP/xamppfiles/apache2/htdocs"
 
<Directory "/Applications/XAMPP/xamppfiles/apache2/htdocs">
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>


Alias /steve/ "/Users/steve/Sites/myblog/"
Alias /steve "/Users/steve/Sites/myblog"

<Directory "/Users/steve/Sites/myblog">
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>
Mapping another URL to a new location in /Applications/XAMPP/xamppfiles/apache2/conf/httpd.conf

 

 

A request to localhost/steve/ serves the following page:

Test page for localhost/steve alaised to /Users/steve/Sites/mysite
Test page for localhost/steve aliased to /Users/steve/Sites/myblog

 

 

Whenever changes are made to Apache’s configuration files the Apache server has to be re-started1 for the changes to take effect. You can start, stop and restart the Apache server using the Manage Servers tab of XAMPP‘s Application Manager:

The XAMPP Application Manager
The XAMPP Application Manager

 

 

If you prefer, the Apache server can be managed from the command line in Terminal.

To stop the Apache server type:

sudo /Applications/XAMPP/xamppfiles/bin/apachectl stop

 

 

To start the Apache server type:

sudo /Applications/XAMPP/xamppfiles/bin/apachectl start

 

 

To re-start1 the Apache server type:

sudo /Applications/XAMPP/xamppfiles/bin/apachectl graceful

 

 

1 If the Apache server is running, apachectl graceful doesn’t first stop and then start the server, it simply reloads the configuration files. If the Apache server is not running, apachectl graceful attempts to start it.

About the author

A native Brit exiled in Japan, Steve spends too much of his time struggling with the Japanese language, dreaming of fish & chips and writing the occasional blog post he hopes others will find helpful.

8 responses

Leave a Reply to Leo Cancel reply

8 Comments

Steve

Recent Comments

Recent Posts