VirtualHost Defaulting to Wrong Deployment on Restart
We have a server running seven domains/subdomains. To try to go as minimal as possible here I'll include four of them.
- example.com
- www.example.com
- dwf.example.com
- chris.example.com
The server works great 90% of the time, but occasionally we get a larger number of requests and the database server goes down. This then max's out the apache connections, because all the db connections are waiting to timeout. All well and good, we force a restart on the DB, and connections come back up. However, the requests are then coming to the dfw.example.com configuration. That deployment doesn't have our codebase, which is a big issue and I don't understand why that is happening. It also consistently goes to that deployment when this happens and never any of the other 5 we have.
From the documentation I read, I thought Apache read through the httpd.conf file and looked for the first NamedVirtualHost match:
Now when a request arrives, the server will first check if it is using an IP address that matches the NameVirtualHost. If it is, then it will look at each
<VirtualHost>
section with a matching IP address and try to find one where the ServerName or ServerAlias matches the requested hostname. If it finds one, then it uses the configuration for that server. If no matching virtual host is found, then the first listed virtual host that matches the IP address will be used.
We are running Apache 2.2.15.
Parts I think are relevant from the httpd.conf file:
Listen 80
Listen 255.255.255.255:443
...
ServerName www.example.com
... (this is the exact order, www (https/http), dfw, then all other versions)
NameVirtualHost www.example.com:80
<VirtualHost www.example.com:80>
ServerAdmin [email protected]
DocumentRoot /var/www/html/www.example.com
ServerName www.example.com
DirectoryIndex index.html
DirectoryIndex index.php
LogLevel notice
ErrorLog /var/log/httpd/www.example.com/error.log
CustomLog /var/log/httpd/www.example.com/access.log w3c_extended
</VirtualHost>
NameVirtualHost www.example.com:443
<VirtualHost www.example.com:443>
ServerAdmin [email protected]
DocumentRoot /var/www/html/www.example.com
ServerName www.example.com
#certificate stuff
DirectoryIndex index.html
DirectoryIndex index.php
LogLevel notice
ErrorLog /var/log/httpd/www.example.com/error.log
CustomLog /var/log/httpd/www.example.com/access.log w3c_extended
</VirtualHost>
NameVirtualHost dfw.example.com:80
<VirtualHost dfw.example.com:80>
ServerAdmin [email protected]
DocumentRoot /var/www/html/dfw.example.com
ServerName dfw.example.com
DirectoryIndex index.html
DirectoryIndex index.php
LogLevel notice
ErrorLog /var/log/httpd/dfw.example.com/error.log
CustomLog /var/log/httpd/dfw.example.com/access.log w3c_extended
</VirtualHost>
NameVirtualHost chris.example.com:443
<VirtualHost chris.example.com:443>
ServerAdmin [email protected]
DocumentRoot /var/www/html/chris.example.com
#cert stuff
ServerName chris.example.com
DirectoryIndex index.html
DirectoryIndex index.php
LogLevel notice
ErrorLog /var/log/httpd/chris.example.com/error.log
CustomLog /var/log/httpd/chris.example.com/access.log w3c_extended
</VirtualHost>
NameVirtualHost chris.example.com:80
<VirtualHost chris.example.com:80>
ServerAdmin [email protected]
DocumentRoot /var/www/html/chris.example.com
ServerName chris.example.com
DirectoryIndex index.html
DirectoryIndex index.php
LogLevel notice
RewriteLog /home/chris/writinglog.log
RewriteLogLevel 8
ErrorLog /var/log/httpd/chris.example.com/error.log
CustomLog /var/log/httpd/chris.example.com/access.log w3c_extended
CheckSpelling on
</VirtualHost>
Doing a sudo service httpd restart
gets the correct deployment serving again.
Output from apachectl -S
:
VirtualHost configuration:
[IPV6ADDRESS]:443 is a NameVirtualHost
default server chris.example.com (/etc/httpd/conf/httpd.conf:1077)
port 443 namevhost chris.example.com (/etc/httpd/conf/httpd.conf:1077)
[IPV6ADDRESS]:80 is a NameVirtualHost
default server chris.example.com (/etc/httpd/conf/httpd.conf:1095)
port 80 namevhost chris.example.com (/etc/httpd/conf/httpd.conf:1095)
port 80 namevhost cory.example.com (/etc/httpd/conf/httpd.conf:1128)
IPV4Address:80 is a NameVirtualHost
default server www.example.com (/etc/httpd/conf/httpd.conf:1035)
port 80 namevhost dfw.example.com (/etc/httpd/conf/httpd.conf:1065)
port 80 namevhost www.example.com (/etc/httpd/conf/httpd.conf:1035)
port 80 namevhost chris.example.com (/etc/httpd/conf/httpd.conf:1095)
IPV4Address:443 is a NameVirtualHost
default server www.example.com (/etc/httpd/conf/httpd.conf:1047)
port 443 namevhost www.example.com (/etc/httpd/conf/httpd.conf:1047)
port 443 namevhost chris.example.com (/etc/httpd/conf/httpd.conf:1077)
wildcard NameVirtualHosts and _default_ servers:
_default_:443 www.example.com (/etc/httpd/conf.d/ssl.conf:74)
Syntax OK
Solution 1:
I am not sure if its good that you have multiple NameVirtualHost *
directives.
As I understand your question, you yust want a pure NAME Virtual Host and you want that all interfaces on all ports are handled by NameVirtual Host.
I would recoment you to create you hosts like this:
# Use Virtual hosts for all interfaces on all ports
NameVirtualHost *
<VirtualHost *>
ServerName example.com
# all other settings for this hostname
</VirtualHost>
<VirtualHost *>
ServerName www.example.com
# all other settings for this hostname
</VirtualHost>
<VirtualHost *>
ServerName dfw.example.com
# all other settings for this hostname
</VirtualHost>
<VirtualHost *>
chris.example.com
# all other settings for this hostname
</VirtualHost>
## ssl.conf
<VirtualHost _default_:443>
ServerName www.example.com
# all other settings for this hostname
SSLEngine on
#certificate stuff
</VirtualHost>
And if you want to use the same settings for multiple hostnames (e.g. example.com and www.example.com) you could simple add ServerAlias directive where all Hostnames are listed (wildcards like "*.example.com" are possible too).
e.g. a virtual host what matches "example.com" and "www.example.com" could be done like this:
<VirtualHost *>
ServerName example.com
ServerAlias example.com www.example.com
# all other settings for this hostname
</VirtualHost>
p.s. Settings like DirectoryIndex
or LogLevel
you can define once in your global config. Your virtual host will take the global config and you dont need to add the same value to each host.
Only if one host needs a config different to global values, you must add the special settings in this host.