Virtual Hosts

Virtual Hosts and How Apache Picks One

Each site is a <VirtualHost> block in its own sites-available/ file, enabled with sudo a2ensite site-b and a reload. Apache 129 first matches the address and port the connection arrived on, keeping only the most specific match (an exact IP beats *). Among the blocks left, it compares the Host header with each ServerName and ServerAlias in configuration order: the first match wins, and if none matches, the first block serves the request. Exactly one virtual host is ever chosen.

/etc/apache2/sites-available/site-b.confApache config
LogFormat "%h %{Host}i \"%r\" %>s %O %Dus \"%{User-Agent}i\"" timed
<VirtualHost *:8101>
  ServerName site-b.example
  ServerAlias www.site-b.example
  DocumentRoot /var/www/site-b
  ErrorLog ${APACHE_LOG_DIR}/site-b-error.log
  CustomLog ${APACHE_LOG_DIR}/site-b-access.log timed
</VirtualHost>

apache2ctl -S prints the table Apache built, with the file and line of each block, and curl 3,008 -H tests it without DNS:

Dumping the virtual host table, then testing it with Host headersShell
sudo apache2ctl -S 2>&1 | head -7
for h in site-a.example site-b.example www.site-b.example unknown.example; do
  printf '%-19s ' "$h"
  curl -s -H "Host: $h" localhost:8101/ | grep -o -m1 -E '<title>.*</title>|^site-. home'
done
Output
VirtualHost configuration:
*:8101                 is a NameVirtualHost
         default server PHANG.localdomain (/etc/apache2/sites-enabled/000-default.conf:1)
         port 8101 namevhost PHANG.localdomain (/etc/apache2/sites-enabled/000-default.conf:1)
         port 8101 namevhost site-a.example (/etc/apache2/sites-enabled/site-a.conf:1)
         port 8101 namevhost site-b.example (/etc/apache2/sites-enabled/site-b.conf:3)
                 alias www.site-b.example
site-a.example      site-a home
site-b.example      site-b home
www.site-b.example  site-b home
unknown.example     <title>Apache2 Ubuntu Default Page: It works</title>

The unknown name fell through to 000-default.conf, the default server, because it sorts first (it shows the machine's hostname since it sets no ServerName). It answers every scanner that hits your IP address, so make it a deliberate catch-all that returns 404. A site that does not answer at all usually has a closed port (Port Closed?) or EC2 24 security group (Security Groups).