How to Configure and Troubleshoot Virtual Hosts in Apache HTTPD
In this post, we will learn how to configure Apache httpd to provide IPbased and name-based virtual hosts.
Virtual Hosts
Virtual hosts allow a single httpd server to serve content for multiple domains. Based on either the IP address of the server that was connected to, the hostname requested by the client in the http request, or a combination of both, httpd can use different configuration settings, including a different DocumentRoot.
Virtual hosts are typically used when it is not cost-effective to spin up multiple (virtual) machines to serve out many low-traffic sites; for example, in a shared hosting environment.
Configuting Virtual Hosts
Virtual hosts are configured using <VirtualHost> blocks inside the main configuration. To ease administration, these virtual host blocks are typically not defined inside /etc/httpd/conf/ httpd.conf, but rather in separate .conf files in /etc/httpd/conf.d/.
The following is an example file, /etc/httpd/conf.d/site1.conf.
- This block provides access to the DocumentRoot defined further down.
- This is the main tag of the block. The 192.168.0.1:80 part indicates to httpd that this block should be considered for all connections coming in on that IP/port combination.
- Here the DocumentRoot is being set, but only for within this virtual host.
- This setting is used to configure name-based virtual hosting. If multiple <VirtualHost> blocks are declared for the same IP/port combination, the block that matches ServerName with the hostname: header sent in the client http request will be used. There can be exactly zero or one ServerName directives inside a single <VirtualHost> block. If a single virtual host needs to be used for more than one domain name, one or more ServerAlias statements can be used.
- To help with sorting mail messages regarding the different websites, it is helpful to set unique ServerAdmin addresses for all virtual hosts.
- The location for all error messages related to this virtual host.
- The location for all access messages regarding this virtual host.
If a setting is not made explicitly for a virtual host, the same setting from the main configuration will be used.
Name-based vs. IP-based virtual hosting
By default, every virtual host is an IP-based virtual host, sorting traffic to the virtual hosts based on what IP address the client had connected to. If there are multiple virtual hosts declared for a single IP/port combination, the ServerName and ServerAlias directives will be consulted, effectively enabling name-based virtual hosting.
Wildcards and priority
The IP address part of a <VirtualHost> directive can be replaced with one of two wildcards: _default_ and *. Both have exactly the same meaning: “Match Anything”.
When a request comes in, httpd will first try to match against virtual hosts that have an explicit IP address set. If those matches fail, virtual hosts with a wildcard IP address are inspected. If there is still no match, the “main” server configuration is used.
If no exact match has been found for a ServerName or ServerAlias directive, and there are multiple virtual hosts defined for the IP/port combination the request came in on, the first virtual host that matches an IP/port is used, with first being seen as the order in which virtual hosts are defined in the configuration file.
When using multiple *.conf files, they will be included in the alphanumeric sorting order. To create a catch-all (default) virtual host, the configuration file should be named something like 00default.conf to make sure that it is included before any others.
Troubleshooting Virtual Hosts
When troubleshooting virtual hosts, there are a number of approaches that can help.
- Configure a separate DocumentRoot for each virtual host, with identifying content.
- Configure separate logfiles, both for error logging and access logging, for each virtual host.
- Evaluate the order in which the virtual host definitions are parsed by httpd. Included files are read in alphanumeric sort order based on their filenames.
- Disable virtual hosts one by one to isolate the problem. Virtual host definitions can be commented out of the configuration file(s), and include files can be temporarily renamed to something that does not end in .conf.
- journalctl UNIT=httpd.service can isolate log messages from just the httpd.service service.