Setting up a Local Development Environment (XAMPP Edition)

Anyone in the Web Design and Development business [with more than a few days experience] will tell you “Never develop on a Production Site”… This is solid advice, and while most hosting providers have a way to create add-on or sub-domains, some do not or maybe you want to develop in-house due to bandwidth or other factors. That’s why I developed this tutorial.

In this edition, we are going to cover how to setup a local development environment using XAMPP (discussed in more detail below) which will allow us to host multiple websites/domains one physical server (or virtual server).

We’re going to break this down into a handful of steps, to make it easier to follow along:

  • Determine Development Environment
  • Select the best software package for our environment
  • Install the software
  • Configure virtual hosts
  • Bonus: Configure SSL
Video walk-through and tutorial (approx 1 hour)

Step 1: Determine your environment (OS)

Yes, this may seem redundant but determining your environment is an essential first step as certain software packages may not be available or the process of installing them will be different.

In this example, our environment will be a Windows 10 PC running on a local network without a DNS server available. Since we will not have a DNS server, we will need to tell each machine in our network what the domain name and IP Address of the webserver are using the ‘HOSTS’ file

Step 2: Select Software Package

For our local development environment, we have a few options available to us… we could use Local (formerly known as “Local By Flywheel”), XAMPP or a completely custom installation of Apache, Perl, PHP, MySql and phpMyAdmin.

Both XAMPP and Local have simplistic one-click installers making them extremely easy to install. As stated previously, I am going to walk through the XAMPP installation for now (check back later for a tutorial on Local).

XAMPP includes the following in a standard install

  • Apache 2.4 with OpenSSL
  • MariaDB (MySQL)
  • PHP
  • phpMyAdmin
  • Perl
  • FileZilla Server
  • Mercury Mail Server
  • Tomcat

Step 3: Install required software

For this tutorial, I am going to install XAMPP as it includes all the required pieces of the puzzle for us, and we can configure each application as required.

After downloading the installer package, navigate to the location of the downloaded file and double click (or the preferred method would be to right click and choose ‘Run as Administrator’)… this will launch the installer.

Now, the XAMPP Control Panel should be loaded and running.

xampp control panel

Close this control panel by clicking ‘Quit’ and lets re-open the app as the administrator…

xampp control panel as administrator

To ensure Apache and MySQL run as services, click within the associated grey boxes (Currently showing a big red X) under the ‘Service’ column and confirm the service installation then click the ‘Start’ button.

install service confirmation

If you want to enable the FileZilla FTP Server, check that box as well. (Note: this tutorial does not cover FileZilla setup/configuration)

If you open a web browser and navigate to http://localhost/ or https://localhost/ you should see the XAMPP welcome page(s).

xampp default localhost

Step 4: Configure Apache

By default, our installation of XAMPP has a single host defined (localhost) with both SSL and Non-SSL access enabled (which for a single development site would be perfectly fine)… but for demo purposes we are going to walk through how to create additional virtual hosts in order to allow for future expansion.

First, we need to determine what our “development’ domains are going to be… I typically use the same as a production domain but swap the ‘.com’ for ‘.local’ [I will explain why a little later on]. Lets say our production sites are ‘’ and ‘’. So, by slightly adjusting the naming, we will end up with ‘widgetfactory.local’ and ‘widgetdeveloper.local’.

I use the ‘.local’ domain as it does not require any form of registration and if you have any WordPress plugins that use the Freemius framework, you can install them without counting against your license count.

Second, lets edit our HOSTS file so that APACHE and our Web Browser will know the address of our two development domains      localhost    xampp.local    widgetdeveloper.local www.widgetdeveloper.local    widgetfactory.local www.widgetfactory.local

Third, lets build out our folder structure for our development sites (in this example, I am going to use a second HDD (D:) and create a top level folder called ‘sites’). open Windows Explorer, and navigate to the where you want to create your SITES folder structure. Create a subdirectory for each domain/site and within those folders, create three folders so you end up with a structure resembling below:

site directory structure

Within the ‘htdocs’ folder create a simple index.html (and info.php)

<h1>Welcome to Widget Developer</h1>

Finally, lets define the virtual host(s) for our development domains, syntax check the Apache config file and restart Apache. Lets take a look at the virtual host configuration file (c:\xampp\apache\conf\extra\httpd-vhosts.conf) as it ships.

apache vhosts default

To be honest, the only line we need to keep (as of the current release) is the “NameVirtualHost”, so lets get started…

Apache will use the FIRST virtual host as a default/fallback, so we will allow it do it’s job. Some online forums discuss defining the last virtual host using ‘ServerAlias *’, and while this works, Apache will still report the first virtual host as the default.

NameVirtualHost *:80
# Default/Fallback Virtual Host
<VirtualHost *:80>
	ServerName localhost
	DocumentRoot "c:/xampp/htdocs"
<Directory "D:\sites\*\htdocs">
	AllowOverride all
	Options Indexes FollowSymLinks Includes
	Require all granted
<VirtualHost *:80>
    ServerName widgetdeveloper.local
    ServerAlias www.widgetdeveloper.local
    DocumentRoot "D:\sites\widgetdeveloper\htdocs"
    DirectoryIndex index.php index.html
    ErrorLog "D:\sites\widgetdeveloper\logs\error.log"
    CustomLog "D:\sites\widgetdeveloper\logs\access.log" combined
<VirtualHost *:80>
    ServerName widgetfactory.local
    ServerAlias www.widgetfactory.local
    DocumentRoot "D:\sites\widgetfactory\htdocs"
    DirectoryIndex index.php index.html
    ErrorLog "D:\sites\widgetfactory\logs\error.log"
    CustomLog "D:\sites\widgetfactory\logs\access.log" combined

Open a command prompt, and execute ‘\xampp\apache\bin\httpd -t’

If all went well this should return ‘Syntax OK’, and you can now restart the Apache Service and then open a browser and access each of our new websites via standard HTTP (our ‘Hello from INDEX’ message should appear). Now try accessing the ‘info.php’ and you should see details on the PHP version installed.

From here can build your development site from the ground up, install WordPress or any other CMS or Framework you would like.

Bonus Step: Setup (self-signed) SSL and HTTP2

First, lets create a Certificate Signing Request (CSR) config file with information specific to our development domain (repeat this step for your second domain, swapping out domain names and alt names).

Note: Self-Signed certificates will cause a security warning when accessing the site, but you can ‘install’ the certificate in the browser which will avoid this notice in the future.

Locate the ‘ssl’ folder we created earlier, and create new file named ‘server.cnf’

default_bits = 4096
default_md = sha512
distinguished_name = dn
encrypt_key = no
prompt = no
x509_extensions = req_ext
C  = "US"
ST = "CA"
L  = "AnyTown"
O  = "Widget Developer"
OU = "WidgetDeveloper"
emailAddress = ""
CN = "widgetdeveloper.local"
subjectAltName = @alt_names
DNS.1 = *.widgetdeveloper.local

Note: the ‘encrypt_key = no’ is extremely important here, as XAMPP and Apache can not load encrypted key files (lesson learned the hard way, personally)…

Second, we will run the ‘openssl’ command (default full path: c:\xampp\apache\bin\openssl.exe)

openssl req -config d:\sites\widgetdeveloper\ssl\server.cnf -newkey rsa -x509 -days 365 -keyout d:\sites\widgetdeveloper\ssl\server.key -out d:\sites\widgetdeveloper\ssl\server.crt

Third, let’s enable HTTP2 and create our SSL Enabled Virtual hosts, syntax check the Apache configuration files and restart Apache. This step is very similar the defining our non-ssl virtual hosts, just in a separate file and with some additional directives.

Locate the file ‘c:\xampp\apache\conf\httpd.conf’ and uncomment the line below (remove the pound sign) and save the file

#LoadModule http2_module modules/

Locate the file ‘c:\xampp\apache\conf\extra\httpd-ssl.conf’, find the line ‘Listen 443’ and add the ‘Protocols’ directive immediately after that… Scroll down until you find the ‘VirtualHost _default_’ definition and insert your new ‘VirtualHost’ directives above that section. After making your edits, save the file.

Listen 443
Protocols h2 h2c http/1.1
<VirtualHost *:443>
	DocumentRoot "d:\sites\widgetdeveloper\htdocs"
	ServerName widgetdeveloper.local
    ServerAlias www.widgetdeveloper.local
    ErrorLog ....
    TransferLog ....
	SSLEngine On
	SSLCertificateFile "d:/sites/widgetdeveloper/ssl/server.crt"
	SSLCertificateKeyFile "d:/sites/widgetdeveloper/ssl/server.key"
<VirtualHost _default_:443>

Now, do another syntax check on your Apache config and finally restart the Apache Service.

Viola, you should now be able to access each of your development sites via HTTPS.

If you found this article helpful, we hope you will share it and provide feedback using the comments form below…

Leave a Reply

Your email address will not be published. Required fields are marked *