Some Virtual hosts troubleshooting information/tips based on the common questions about them in #httpd
The page will concentrate on Name Based virtual hosts mainly because it is what most people use and it is the one many people seem to have problems with. Version specifc information is marked as such.
Virtual Hosts are much simpler than most people seem to think but in some cases are made more complicated by some unusual 'default' virtual host setups installed by some of the major distributions.
First things first, read the documentation!
Secondly, and this cannot be stressed enough, use apachectl -S
or httpd -S
whenever any changes are made to the configuration. It outputs various lines of information that are vital to the troubleshooting of virtual host configurations. See below for further information.
Thirdly, although there are a couple of exceptions, if an access log is defined then httpd will always log something to it when it serves a request and an entry will always be logged in the error log on a 4xx return code. An error log entry will also normally be written on a 5xx return code, however when using 3rd party modules, CGIs or launguages such as php it is possible for these to be hijacked and nothing will be in the log. If you cannot find the access/error log entry then you are either looking in the wrong log or the request didn't actually reach the web server.
NameVirtualhost *:80 |
<VirtualHost *:80> |
ServerName foo.com |
DocumentRoot /var/www/foo |
With named base virtual hosts, the first one apache finds in the configuration files is special. This is the one that requests will be passed to if apache has no way to determine which specific virtual host to use. It is the default virtual host.
In general, if the user types http://my.domain.com/my/url/path
into their browser, then it is the string my.domain.com
that is matched against the host component of the ServerName, or any ServerAlias directive (Remember Server{{`Name can contain an optional schema and port). Anything that does not match a Server}}Name or Server
`Alias in the configuration will be served by the default virtual host.
Note: It is the contents of the Host
header that is actually used by httpd here rather than the host component of the URL, though these would normally be the same.
Here is a very simple two virtual host example that we will use to highlight the output of apachectl -S
.
# NameVirtualhost is needed in httpd prior to v2.3.11 NameVirtualHost 192.168.0.1:80 # Any request to foo.com, or indeed anything other than bar.com that resolves # to 192.168.0.1 will be served by this first virtual host <VirtualHost 192.168.0.1:80> ServerName foo.com ServerAlias www.foo.com DocumentRoot /var/www/foo </Virtualhost> # Only URLs that start http:///bar.com/ or http://www.bar.com will be served # by this virtual host <VirtualHost 192.168.0.1:80> ServerName bar.com ServerAlias www.bar.com DocumentRoot /var/www/bar </Virtualhost> |
The ErrorLog is always the first place to look when any problems arise, but there are things that can be done to make troubleshooting virtual hosts easier.
%v
to the relevant LogFormat.
GET
). It is worth learning these tools and their options, but here are some examples by way of an introduction.
# Get the headers from foo.com. Output in the file headers.txt curl -s -D headers.txt -o /dev/null http://foo.com/ GET -uUsSed http://foo.com/ > headers.txt # Using just the host header instead of the fqdn. Output in the file headers.txt curl -H "Host: foo.com" -s -D headers.txt -o /dev/null http://192.168.0.1/ wget --header="Host: foo.com" -nv --save-headers=on -O headers.txt http://192.168.0.1/ GET -H "Host: foo.com" -uUsSed http://192.168.0.1/ > headers.txt # Get the headers and content of the page to the terminal curl -s -i http://foo.com/ wget -nv --save-headers=on -O - http://foo.com/ GET -uUsSe http://foo.com/ |
apachectl -S
to test it before the web server is restarted. Below are two examples of the output from this command for httpd v2.2.x and 2.4.x with line numbers added for clarity. A line by line explanation of each follows. The output was generated using a basic httpd install with the example virtual host configuration above.
# Example output from httpd 2.2 1: VirtualHost configuration: 2: 192.168.0.1:8080 is a NameVirtualHost 3: default server foo.com (/etc/httpd/conf.d/vhosts.conf:11) 4: port 80 namevhost foo.com (/etc/httpd/conf.d/vhosts.conf:11) 5: port 80 namevhost bar.com (/etc/httpd/conf.d/vhosts.conf:18) |
# Example output from httpd 2.4 1: VirtualHost configuration: 2: 192.168.0.1:80 is a NameVirtualHost 3: default server foo.com (/etc/httpd/conf.d/vhosts.conf:2) 4: port 80 namevhost foo.com (/etc/httpd/conf.d/vhosts.conf:2) 5: alias www.foo.com 6: port 80 namevhost bar.com (/etc/httpd/conf.d/vhosts.conf:9) 7: alias www.bar.com 8: <After this are several lines of output relating to the global configuration> |
In the ouput, if there are any duplicate server names or aliases (other than the default one and the namevhost immediately after it) then there are virtual hosts with the same name (or Alias) and only the first one in the list will work.
With httpd prior to v2.3.11, if you do not have a Name{{`Virtual}}{{Host directive you will not see the line ending in }}is a NameVirtualHost` and depending on the exact configuration you may see something similar to one of the following warnings:
# If the virtual hosts are defined with IP:port [Fri Jan 11 22:27:30 2013] [warn] VirtualHost 192.168.0.1:80 overlaps with VirtualHost 192.168.0.1:80, the first has precedence, perhaps you need a NameVirtualHost directive # If the virtual hosts are defined with *:port [Fri Jan 11 22:28:04 2013] [warn] _default_ VirtualHost overlap on port 80, the first has precedence |