Setting up virtual hosts on XAMPP* local webserver
Tags: virtualhosts, tutorial, localhostdomains, php
Published: 2021-03-22 07:31:25

This tutorial will walk you through setting up a virtual host for your PHP project. I split this tutorial in two parts - beginning with quick walkthrough, from start to finish in few steps. In the second part, I dive deep on each step of the tutorial to make sure you understand everything that you have done. I have no illusion that most of you will read the second part.

_I explain the concepts from a Windows-user perspective (paths, file names). If you happen to be a unix/linux user, I am sure you know where you have your stuff and can follow along._

## Why create virtual hosts?

Your PHP application will likely run on real url address, such as `danieldusek.com`, you want to emulate this locally and `localhost` just doesn't do it for you. You want `danieldusek.localhost` instead. Or... your application maybe doesn't handle relative paths well. 

## Quick step by step virtual host setup in xampp

Make sure you know:

1. Path to your PHP project, e.g.: `c:\users\username\source\mysite`
2. Path to your xampp/lampp installation, e.g.: `c:\xampp`

Then go and do:

1. Open your `xampp` install directory and locate `httpd-vhosts.conf` file under `apache/conf/extra` folder.
2. Open `httpd-vhosts.conf` file in text editor of your choice.
3. At the very end of the file paste the following code, but replace:
   1. `c:\users\username\source\mysite` with actual path to your PHP project,
   2. `danieldusek.localhost` with your own name (do yourself a favor and use actually `.localhost` TLD)

```xml
<VirtualHost *:80>
    DocumentRoot "c:\users\username\source\mysite"
    ServerName danieldusek.localhost
    <Directory "c:\users\username\source\mysite">
        Require all granted
    </Directory>
</VirtualHost>
```

You have just configured local server to look for scripts to execute in whichever directory you chose, whenever it receives request looking for `yourdomain.localhost` (or whatever you have decided to go with).

Be sure to **RESTART THE APACHE SERVER** after saving the file.  

The last step is to tell your computer to route all `yourdomain.localhost` requests to localhost (your computer):

1. Open `c:\windows\system32\drivers\etc` folder and find `hosts` file
2. Open `hosts` file in text editor of your choice, that can save files as administrator (Visual Studio Code can elevate to Administrator in a user friendly way when saving)
3. Add `127.0.0.1 yourdomain.localhost` line at the very end of it.
4. Save.

When you now access `yourdomain.localhost` in the browser, you will see your project. If not, your setup is broken and/or you don't know what you are doing. Please proceed to the second part of this tutorial where I explain the concepts in more detail.

## Step by step breakdown of what is actually going on

I decided to run an experiment where I will be explaining every concept of this tutorial and everything related to it, instead of providing troubleshooting FAQ. If my hypothesis is correct and my explanation up to par, you should be able to fix your problem on your own.

### How it all works?

My basic assumption here is that you have installed an XAMPP or similar package on your device. You did that because you want to develop an application in PHP or other supported language.

XAMPP package comes with an apache server which knows how to process web requests, interpret PHP (if installed) scripts and provide content back to user sending the web requests. **One of the things that apache server does while processing user's request is checking for what domain the request was sent**. Remember this. Doesn't matter whether the domain name is valid or whether it exists.

When apache web server runs on a computer, it can be reached by accessing `127.0.0.1` - or its `localhost` alias - in the browser. Alternatively, if you happen to be connected to the internet and you have a public IP assigned to your computer, other people can send requests to your apache web server as well - they will use your public IP, instead of the `localhost`/`127.0.0.1`.

During the XAMPP / web server installation, you are allowed to choose on which ports the server will operate. By convention, http traffic will be served on port `80` and https traffic on `443`. This convention is again important - these ports are well known and when your browser makes an http request, it lands on port 80 of the target server. Same it goes for https and 443. If you have chosen to use different ports for http and https traffic respectively, you will need to specify them in address. 

**Example scenario**: You installed server to process http traffic on port `81`. When you want to reach the server from your computer, you will have to access `http://127.0.0.1:81`.

These ports can be changed, but the process to do so would be out of scope for this tutorial. This [stack overflow post](https://stackoverflow.com/a/21914920) does a great job at explaining how to do that.

To summarize - if you followed this tutorial, you achieved two things:

- Told your apache server where to look for scripts when processing requests that are aimed at a specific domain that you specify in `httpd-vhosts.conf`.
- Told your computer to re-route requests to `yourdomain.localhost` to `127.0.0.1`, also known as localhost.

### How does editing `httpd-vhosts.conf` works?

Let's have a look at the snippet of code that gets appended to the file: 

```xml
<VirtualHost *:80>
    DocumentRoot "c:\users\username\source\mysite"
    ServerName danieldusek.localhost
    <Directory "c:\users\username\source\mysite">
        Require all granted
    </Directory>
</VirtualHost>
```

First thing that needs an explanation is the port number at line 1: `<VirtualHost *:80>`. It is 80, once again, as a side effect of the http=80 convention mentioned above. If you have installed on different port, you need to update it.

The asterisk infront of it tells the webserver to match all addresses. This can be used when you have multiple named addresses on your web server and want to fallback to the first one in case request does not match any other in the config file. Source: [apache.org documentation](https://httpd.apache.org/docs/2.4/vhosts/examples.html).

The `<Directory ...>` are markings in a configuration language used by apache that indicate that everything inside them should be used on a given directory and all of it children directories and files. The things that are enclosed in them are called directives. Source: [apache.org documentation](https://httpd.apache.org/docs/2.4/mod/core.html#directory)

As for the actual directive used - `Require all granted` - this tells the apache server that it should not refuse to serve these pages to any IP requesting them. 

In most scenarios, you will be on a local network without a public IP. So using this broad directive causes that effectively anyone on the same local network can request pages from your webserver. Should you have a public IP address, then anyone on the internet might be able to do that. If this is a concern for you, [read the apache documentation](http://httpd.apache.org/docs/2.4/mod/mod_authz_core.html#require) and look for `Require ip [IP]` directive.

The `ServerName yourdomain.localhost` is pretty self-explanatory. Requests for given domain will be routed to the folder provided under `DocumentRoot`.

### Why should you use `.localhost` TLD?

Short answer: Because you should not use an existing TLD.

Long answer: You have no control over which TLDs will be created in the future, but you can refer to [RFC2606, page 2](https://tools.ietf.org/html/rfc2606) which lists domains that you can use for private testing. These are `.test`, `.example`, `.invalid`, and `.localhost`.

### How does `hosts` file update works?

In the second part of the local domain setup we edit the `hosts` file and add a `127.0.0.1 yourdomain.localhost` line at the end of it. This line maps - as perceived by your computer - the `yourdomain.localhost` domain to `127.0.0.1` ip (your computer's ip; a localhost). You can put any domain and any IP address there instead and it will work the same way.

This is very similar to how Domain Name System (DNS) works. DNS is a protocol that maps domain names to IP addresses of computers that host websites the user is trying to reach. It is very convenient for users to type `danieldusek.com` instead of remembering that it is hosted on `89.221.213.23`. It also gives me flexibility in changing the hosting provider without the need to tell people to now go to different address. 

The `hosts` file is a local hint for the operating system that is used with higher priority. If a domain name is found in the `hosts` file, the system will not try to get the information about target IP address from the DNS server, but will use the one specified. 

And that's about it.