With the use of virtual hosts we can make an httpd
server manage multiple websites. We can use both IP and name-based virtual hosts; what are the differences between them?
How Apache decides what of the virtual hosts should be
used to respond to a client request? We will answer these questions in this
article, keep reading!
In this tutorial you will learn:
- What are the differences between IP and name based virtual hosts
- What is the Listen directive and how it is used
- How Apache decides what virtual host should be used to respond to a request
Software Requirements and Conventions Used
Category | Requirements, Conventions or Software Version Used |
---|---|
System | Distribution Independent |
Software | No specific software needed |
Other | Familiarity with the Apache web server and http basic concepts |
Conventions | # – requires given linux commands to be executed with root privileges either directly as a root user or by use of sudo command$ – requires given linux commands to be executed as a regular non-privileged user |
The “Listen” directive
The first thing to take in consideration, is the Listen
directive. This directive is mandatory, and is needed to tell the httpd
server to what IP-PORT
combination it should listen for requests. By default the server is usually configured to listen to every IP
on port 80
.
In /etc/httpd/conf/httpd.conf
which is the main httpd
configuration file on Fedora/RHEL/CentOS systems, at line 45
, for example, we can read:
Listen 80
As you can see, only the port is specified with the Listen
directive. As a result, the server will listen on that port on all the machine IP addresses. If an address is specified, instead, the server will listen only on the provided IP:PORT
combination.
The Listen
directive can be repeated multiple times, therefore is very easy to specify multiple combinations.
VirtualHost matching
Once the server is configured to listen to a specific address or port, Apache must decide what VirtualHost should be used to fulfill the client request. Before seeing the steps involved in this decision, let’s briefly see how a virtual host is defined.
The directive used to create and configure virtual host, is VirtualHost
; it uses the following syntax:
<VirtualHost addr[:port] [addr[:port]] ...> ... </VirtualHost>
As we can observe, each VirtualHost
directive needs an addr
; it can be specified as:
- An IP address, either IPv4 or IPv6 (IPv6 addresses must be enclosed in square brackets);
- A Fully Qualified Domain Name;
- A
*
wildcard (this will match all addresses)
All the parameters and configurations made inside the <VirtualHost></VirtualHost>
tags, are “local” to that specific virtual host. Here is an example of a virtual host configuration:
<VirtualHost 93.184.216.34:80> ServerName: www.exampleone.com DocumentRoot "/var/www/exampleone" </VirtualHost>
Or, using a wildcard:
<VirtualHost *:80> ServerName: www.exampleone.com DocumentRoot "/var/www/exampleone" </VirtualHost>
The first thing the server does is to analyze, in order, every virtual host, and check if their addr
matches the request. It’s important to notice that defined IP addresses have priority over wildcards, that are considered only if no exact matches are found. At this point we can have three cases:
- Only one virtual host matches the request;
- No virtual hosts match the request;
- Multiple virtual host matches the request;
The first case resolution is easy: if the client request matches only one specific virtual host, the httpd
server does respond by serving the content related to that virtual host. In this case we talk about IP-based
virtual hosts.
The second case is also easily explained: if no virtual host configuration satisfies the client request, the default server configuration is used to respond to the request. For default configuration, we intend everything set outside of <VirtualHost></VirtualHost>
.
In the third case multiple virtual hosts match the client request. When this happens, the server must discriminate depending on some other factor other than the IP:PORT
combination: the scheme and hostname the virtual host uses to identify itself.
Name-based virtual hosts
The server does examine every matching virtual host in order of definition and selects which one should be used depending on the requested host name
. This are called “name-based” virtual hosts. The first virtual host that matches the request is used. If there are no matches, the server does use the first defined VirtualHost
as fallback.
The main advantage of using name-based virtual hosts, is that we can run multiple websites on the same IP address. Let’s see an example of a name-based VirtualHost:
<VirtualHost *:80> ServerName www.serverone.com DocumentRoot /var/www/serverone </VirtualHost>
Since *:80
is used as address, the virtual host will match every request made on port 80
. What makes the difference in this case is the ServerName
directive. If this directive is omitted, the server will try to obtain a Fully Qualified Domain Name (FQDN) based on the operating system hostname.
The server checks if the host name specified in the request matches the one configured via the ServerName
directive, in this case www.serverone.com
. If it does, the content specified with the DocumentRoot
directive it’s served to the client.
Inside a virtual host configuration it’s also possible to define one or more aliases, to match multiple host names. This is accomplished by using the ServerAlias
directive:
<VirtualHost *:80> ServerName www.serverone.com ServerAlias *.serverone.com DocumentRoot /var/www/serverone </VirtualHost>
In the above configuration we added a ServerAlias
instruction using a wildcard. The configuration will now match also every subdomain of serverone.com
.
IP-based virtual hosts
IP-based virtual hosts, as we already saw, are basically what the httpd
server uses by default. When using them, the ability to serve multiple websites is based on the client request IP:PORT
combination.
It goes by itself that, to use this type of virtual hosts, a machine must have multiple network addresses. This doesn’t mean that multiple physical network interfaces are required, since multiple addresses can be assigned to the same interface ( this is called IP aliasing
), and virtual interfaces can also be created (want to know how to create a virtual network interface on Linux?
Take a look at our article about creating virtual network interfaces on Linux. Here are two examples of IP-based virtual hosts:
Listen 8080 <VirtualHost 93.184.216.34:80> ServerName: www.exampleone.com DocumentRoot "/var/www/exampleone" </VirtualHost> <VirtualHost 93.187.216.34:8080> ServerName www.exampletwo.com DocumentRoot "/var/www/exampletwo" </VirtualHost>
Above we can see that even if the two virtual hosts have the same IP address, a different port is specified in the second example: 8080
. In order for the server to be able to listen to that port we use the Listen 8080
directive.
Conclusion
In this tutorial we saw how Apache virtual hosts work. We learned the difference between IP and name-based virtual hosts, and how the server determines what configuration should be used to respond to a client request. Please, take a look at installing Apache article if you want to know more about how to configure an Apache virtual host.