ApacheVirtualHost
This page contains information on how to configure Virtual Hosts (or vhosts) for the Apache HTTP server. There is some general information about how vhosts work as well as concrete configuration documentation.
The main page about Apache configuration is this: Apache.
How Virtual Hosts work
The VirtualHost directive
Virtual hosts must be configured with VirtualHost directives. For instance
<VirtualHost 1.2.3.4> [...] </VirtualHost>
encloses a block of directives that are used when requests on the interface 1.2.3.4 need to be served. There may be several such blocks for 1.2.3.4, but each block must contain a different ServerName directive - this directive decides which block is used to service a specific request. Example:
<VirtualHost 192.168.178.20:80> ServerName www.herzbube.ch ServerAlias herzbube.ch 212.101.18.224 [...] </VirtualHost>
This block is used when a request for www.herzbube.ch, herzbube.ch or the explicit IP address 212.101.18.224 comes in from the interface 192.168.178.20, on port 80.
For every HTTP request, the HTTP header Host: is matched against the server name and server aliases of all virtual hosts in order to determine which virtual host block should be used. The order in which virtual hosts are checked is the order in which they appear in the configuration. As a fallback, if no virtual host matches, the virtual host that appears first in the configuration is selected.
Configuration problems related to virtual hosts can be hard to resolve. The following command is very helpful to "debug" a virtual host configuration - the command will simply print out which virtual hosts exist and in which order they appear:
apache2ctl -S
Besides ServerName and ServerAlias, a virtual host block usually contains at least the following information:
- DocumentRoot directive: the system directory that corresponds to the root URL ("/") of the virtual host; for instance http://www.herzbube.ch/
- ServerAdmin directive: defines the administrator person (often called the webmaster) to contact for that virtual host
- CustomLog and ErrorLog directives: define the location of the corresponding log files
Wildcard Virtual Hosts
Imagine this setup:
<VirtualHost 1.2.3.4:80> ServerName foo.ch [...] </VirtualHost> <VirtualHost *:80> ServerName bar.ch [...] </VirtualHost>
If a request comes in on 1.2.3.4 for server name bar.ch
, Apache will match the first virtual host that uses an explicit IP address. For me this came as a surprise: I would have expected the wildcard virtual host to match because the first virtual host's server name does not match. It appears that the Apache developers have given the IP address a higher priority.
Note: In this example, the fallback mechanism seems to apply: If no virtual host matches, the virtual host that appears first in the configuration is selected.
How Virtual Hosts configurations are stored
On Debian, virtual host configuration files are stored in this folder:
/etc/apache2/sites-available
Configurations in that folder need to be enabled to take effect. Enabling a configuration happens by creating a symlink to the configuration file in the folder
/etc/apache2/sites-enabled
You can manually create such a symlink, but the recommended way to do this is by running the a2ensite
utility. Example:
a2ensite www.herzbube.ch.conf
Important: As was stated further up, the "catch-all" default virtual host must appear as the first virtual host in the entire Apache configuration. Because vhost configuration files are loaded in ascending alphabetical order of their file name, the default vhost configuration file should be named with a prefix such as "000" - this ensures that it is loaded before any other vhost configuration files. Example:
root@pelargir:~# ls -l /etc/apache2/sites-enabled total 0 lrwxrwxrwx 1 root root 35 Jun 8 18:30 000-default.conf -> ../sites-available/000-default.conf lrwxrwxrwx 1 root root 47 Jul 5 21:38 aceexpander.herzbube.ch.conf -> ../sites-available/aceexpander.herzbube.ch.conf lrwxrwxrwx 1 root root 40 Jul 3 16:13 bugs.herzbube.ch.conf -> ../sites-available/bugs.herzbube.ch.conf lrwxrwxrwx 1 root root 39 Jun 15 15:05 cal.herzbube.ch.conf -> ../sites-available/cal.herzbube.ch.conf [...]
Log rotation
Rotation of default log files such as /var/log/apache2/access.log
is triggered by
/etc/logrotate.d/apache2
Rotation of non-default log files such as the ones created by the vhost configuratins below must be managed by a custom logrotate
config snippet. Details are available on this page.
Concrete configuration: All my vhosts
The default Virtual Host
This is the content of sites-available/000-default.conf
:
<VirtualHost *:80> ServerName unknown ServerAdmin webmaster@herzbube.ch ErrorLog ${APACHE_LOG_DIR}/unknown/error.log CustomLog ${APACHE_LOG_DIR}/unknown/access.log combined DocumentRoot /var/www/unknown </VirtualHost> # -------------------------------------------------------------------------------- # SSL Host # -------------------------------------------------------------------------------- <VirtualHost *:443> ServerName unknown ServerAdmin webmaster@herzbube.ch ErrorLog ${APACHE_LOG_DIR}/unknown/error.log CustomLog ${APACHE_LOG_DIR}/unknown/access.log combined DocumentRoot /var/www/unknown Include conf-available/pelargir-herzbube.ch-vhosts-ssl.conf </VirtualHost>
www.herzbube.ch
Pages that deal with stuff that is not covered in the vhost:
This is the content of sites-available/www.herzbube.ch.conf
:
# -------------------------------------------------------------------------------- # www.herzbube.ch # -------------------------------------------------------------------------------- <VirtualHost *:80> ServerName www.herzbube.ch ServerAlias 82.195.228.21 herzbube.ch ServerAdmin webmaster@herzbube.ch ErrorLog ${APACHE_LOG_DIR}/www.herzbube.ch/error.log CustomLog ${APACHE_LOG_DIR}/www.herzbube.ch/access.log combined Redirect permanent "/" "https://www.herzbube.ch/" </VirtualHost> # -------------------------------------------------------------------------------- # SSL Host # -------------------------------------------------------------------------------- <VirtualHost *:443> ServerName www.herzbube.ch # Explicitly name the public IP as an alias, otherwise access # to http://82.195.228.21 will be served by the "catch-all" # Virtual Host ServerAlias 82.195.228.21 herzbube.ch ServerAdmin webmaster@herzbube.ch ErrorLog ${APACHE_LOG_DIR}/www.herzbube.ch/error.log CustomLog ${APACHE_LOG_DIR}/www.herzbube.ch/access.log combined DocumentRoot /var/www/hugo/herzbube.ch # ---------------------------------------- # Simple aliases for files and folders that are not in the document root # ---------------------------------------- Alias /isfdb/ /var/www/www.herzbube.ch/isfdb/ Alias /PGPHerzbubeAtHerzbubeDotCH.txt /var/www/www.herzbube.ch/PGPHerzbubeAtHerzbubeDotCH.txt Alias /pgp-key-signing-policy.html /var/www/www.herzbube.ch/pgp-key-signing-policy.html Alias /robots.txt /var/www/www.herzbube.ch/robots.txt Alias /sitemap.txt /var/www/www.herzbube.ch/sitemap.txt # Slash at the end is important because the main software page # must remain accessible under "/software", i.e. no slash Alias /software/ /var/www/software/ Alias /fuego/ /var/www/fuego/ # ---------------------------------------- # Regex-based aliases # ---------------------------------------- # Requests for documents of the old Eredain site will display the content of the # index page (which tells users that they have arrived at at a dead end). We try # to be clever and guess whether the user wants to see a German or an English page. AliasMatch ^/(web){0,1}svn /var/www/www.herzbube.ch/svn-replaced-by-git.html AliasMatch ^/Eredain/.*_d.* /var/www/www.herzbube.ch/Eredain/EredainIndex_d.shtml # Requests for /svn or /websvn (or any path below those) AliasMatch ^/Eredain /var/www/www.herzbube.ch/Eredain//EredainIndex.shtml RewriteEngine on # ---------------------------------------- # Host-based rules must appear before path-based rules, otherwise a # path-based rule might kick-in before the appropriate host-based rule # ---------------------------------------- RewriteCond %{HTTP_HOST} ^herzbube.ch$ RewriteRule ^(.*)$ https://www.herzbube.ch$1 [R,L] # ---------------------------------------- # Path-based rules must appear after host-based rules. # ---------------------------------------- # Currently there are no path-based rules. The regex-based aliases above # used to be path-based rules. Because the mapped files are no longer in the # document root the mapping can no longer be done with rewriting. See # version control history for details. Include conf-available/pelargir-herzbube.ch-vhosts-ssl.conf </VirtualHost> # -------------------------------------------------------------------------------- # new-site.herzbube.ch (for testing new content) # -------------------------------------------------------------------------------- <VirtualHost *:443> ServerName new-site.herzbube.ch ServerAdmin webmaster@herzbube.ch ErrorLog ${APACHE_LOG_DIR}/www.herzbube.ch/error.log CustomLog ${APACHE_LOG_DIR}/www.herzbube.ch/access.log combined DocumentRoot /var/www/hugo/new-site.herzbube.ch Include conf-available/pelargir-herzbube.ch-vhosts-ssl.conf </VirtualHost> # -------------------------------------------------------------------------------- # old-site.herzbube.ch (for testing new content) # -------------------------------------------------------------------------------- <VirtualHost *:443> ServerName old-site.herzbube.ch ServerAdmin webmaster@herzbube.ch ErrorLog ${APACHE_LOG_DIR}/www.herzbube.ch/error.log CustomLog ${APACHE_LOG_DIR}/www.herzbube.ch/access.log combined DocumentRoot /var/www/hugo/old-site.herzbube.ch Include conf-available/pelargir-herzbube.ch-vhosts-ssl.conf </VirtualHost>
kino.herzbube.ch
This is the content of sites-available/kino.herzbube.ch.conf
:
# -------------------------------------------------------------------------------- # kino.herzbube.ch # -------------------------------------------------------------------------------- <VirtualHost *:80> ServerName kino.herzbube.ch ServerAdmin webmaster@herzbube.ch ErrorLog ${APACHE_LOG_DIR}/kino.herzbube.ch/error.log CustomLog ${APACHE_LOG_DIR}/kino.herzbube.ch/access.log combined Redirect permanent "/" "https://kino.herzbube.ch/" </VirtualHost> # -------------------------------------------------------------------------------- # SSL Host # -------------------------------------------------------------------------------- <VirtualHost *:443> ServerName kino.herzbube.ch ServerAdmin webmaster@herzbube.ch ErrorLog ${APACHE_LOG_DIR}/kino.herzbube.ch/error.log CustomLog ${APACHE_LOG_DIR}/kino.herzbube.ch/access.log combined DocumentRoot /var/www/hugo/kino.herzbube.ch Alias /robots.txt /var/www/kino.herzbube.ch/robots.txt Include conf-available/pelargir-herzbube.ch-vhosts-ssl.conf </VirtualHost>
acexpander.herzbube.ch
This is the content of sites-available/acexpander.herzbube.ch.conf
:
# -------------------------------------------------------------------------------- # aceexpander.herzbube.ch # -------------------------------------------------------------------------------- <VirtualHost *:80> ServerName acexpander.herzbube.ch ServerAdmin webmaster@herzbube.ch ErrorLog ${APACHE_LOG_DIR}/acexpander.herzbube.ch/error.log CustomLog ${APACHE_LOG_DIR}/acexpander.herzbube.ch/access.log combined RewriteEngine on RewriteRule ^.*$ https://www.herzbube.ch/acexpander [R,L] </VirtualHost> # -------------------------------------------------------------------------------- # SSL Host # -------------------------------------------------------------------------------- <VirtualHost *:443> ServerName acexpander.herzbube.ch ServerAdmin webmaster@herzbube.ch ErrorLog ${APACHE_LOG_DIR}/acexpander.herzbube.ch/error.log CustomLog ${APACHE_LOG_DIR}/acexpander.herzbube.ch/access.log combined RewriteEngine on RewriteRule ^.*$ https://www.herzbube.ch/acexpander [R,L] </VirtualHost>
bugs.herzbube.ch
See Bugzilla page.
cal.herzbube.ch
See DAViCal page.
gallery.herzbube.ch
See Gallery page.
git.herzbube.ch
See GitServer page.
ldap.herzbube.ch
See OpenLDAP page.
lists.herzbube.ch
See Mailman page.
mail.herzbube.ch
See Roundcube page (used to be SquirrelMail).
mysql.herzbube.ch
See MySQL page.
postgres.herzbube.ch
See PostgreSQL page.
wiki.herzbube.ch
See Mediawiki page.
pelargir.herzbube.ch
This is the content of sites-available/pelargir.herzbube.ch.conf
:
# -------------------------------------------------------------------------------- # pelargir.herzbube.ch # -------------------------------------------------------------------------------- <VirtualHost *:80> ServerName pelargir.herzbube.ch ServerAlias localhost Redirect permanent "/" "https://pelargir.herzbube.ch/" </VirtualHost> # -------------------------------------------------------------------------------- # SSL Hosts # -------------------------------------------------------------------------------- <VirtualHost *:443> ServerName pelargir.herzbube.ch ServerAlias localhost ServerAdmin webmaster@herzbube.ch ErrorLog ${APACHE_LOG_DIR}/pelargir.herzbube.ch/error.log CustomLog ${APACHE_LOG_DIR}/pelargir.herzbube.ch/access.log combined DocumentRoot /var/www/pelargir.herzbube.ch <Directory /var/www/pelargir.herzbube.ch/> Require all granted Options FollowSymLinks Includes php_admin_flag engine on </Directory> Include conf-available/pelargir-herzbube.ch-vhosts-ssl.conf </VirtualHost>
www.grunzwanzling.ch
This is the content of sites-available/www.grunzwanzling.ch.conf
:
# -------------------------------------------------------------------------------- # www.grunzwanzling.ch # -------------------------------------------------------------------------------- <VirtualHost *:80> ServerName www.grunzwanzling.ch ServerAlias grunzwanzling.ch ServerAdmin webmaster@grunzwanzling.ch ErrorLog ${APACHE_LOG_DIR}/www.grunzwanzling.ch/error.log CustomLog ${APACHE_LOG_DIR}/www.grunzwanzling.ch/access.log combined Redirect permanent "/" "https://www.grunzwanzling.ch/" </VirtualHost> # -------------------------------------------------------------------------------- # SSL Host # -------------------------------------------------------------------------------- <VirtualHost *:443> ServerName www.grunzwanzling.ch ServerAlias grunzwanzling.ch ServerAdmin webmaster@grunzwanzling.ch ErrorLog ${APACHE_LOG_DIR}/www.grunzwanzling.ch/error.log CustomLog ${APACHE_LOG_DIR}/www.grunzwanzling.ch/access.log combined DocumentRoot /var/www/hugo/grunzwanzling.ch Alias /robots.txt /var/www/grunzwanzling.ch/robots.txt RewriteEngine on # ---------------------------------------- # Host-based rules must appear before path-based rules, otherwise a # path-based rule might kick-in before the appropriate host-based rule # ---------------------------------------- RewriteCond %{HTTP_HOST} ^grunzwanzling.ch$ RewriteRule ^(.*)$ https://www.grunzwanzling.ch$1 [R,L] Include conf-available/pelargir-grunzwanzling.ch-vhosts-ssl.conf </VirtualHost>
www.moser-naef.ch
This is the content of sites-available/www.moser-naef.ch.conf
:
# -------------------------------------------------------------------------------- # www.moser-naef.ch # -------------------------------------------------------------------------------- <VirtualHost *:80> ServerName www.moser-naef.ch ServerAlias moser-naef.ch ServerAdmin webmaster@herzbube.ch ErrorLog ${APACHE_LOG_DIR}/www.moser-naef.ch/error.log CustomLog ${APACHE_LOG_DIR}/www.moser-naef.ch/access.log combined Redirect permanent "/" "https://www.moser-naef.ch/" </VirtualHost> # -------------------------------------------------------------------------------- # SSL Host # -------------------------------------------------------------------------------- <VirtualHost *:443> ServerName www.moser-naef.ch ServerAlias moser-naef.ch ServerAdmin webmaster@herzbube.ch ErrorLog ${APACHE_LOG_DIR}/www.moser-naef.ch/error.log CustomLog ${APACHE_LOG_DIR}/www.moser-naef.ch/access.log combined DocumentRoot /var/www/www.moser-naef.ch RewriteEngine on # ---------------------------------------- # Host-based rules must appear before path-based rules, otherwise a # path-based rule might kick-in before the appropriate host-based rule # ---------------------------------------- RewriteCond %{HTTP_HOST} ^moser-naef.ch$ RewriteRule ^(.*)$ https://www.moser-naef.ch$1 [R,L] # ---------------------------------------- # Path-based rules must appear after host-based rules. # ---------------------------------------- # All requests now display /index.html (which tells users that the site has # been shut down for privacy reasons). Note that we do not redirect ([R] flag). RewriteRule ^ /index.html [L] # Redirect requests to /gallery/hochzeit/ to the correct Gallery2 album RewriteRule ^/gallery/hochzeit/?$ https://gallery.herzbube.ch/v/2005-wedding/2005-bestofwedding/ [R,L] Include conf-available/pelargir-moser-naef.ch-vhosts-ssl.conf </VirtualHost>
www.francescamoser.ch
This is the content of sites-available/www.moser-naef.ch.conf
:
# -------------------------------------------------------------------------------- # www.francescamoser.ch # -------------------------------------------------------------------------------- <VirtualHost *:80> ServerName www.francescamoser.ch ServerAlias francescamoser.ch ServerAdmin webmaster@herzbube.ch ErrorLog ${APACHE_LOG_DIR}/www.francescamoser.ch/error.log CustomLog ${APACHE_LOG_DIR}/www.francescamoser.ch/access.log combined Redirect permanent "/" "https://www.francescamoser.ch/" </VirtualHost> # -------------------------------------------------------------------------------- # SSL Host # -------------------------------------------------------------------------------- <VirtualHost *:443> ServerName www.francescamoser.ch ServerAlias francescamoser.ch ServerAdmin webmaster@herzbube.ch ErrorLog ${APACHE_LOG_DIR}/www.francescamoser.ch/error.log CustomLog ${APACHE_LOG_DIR}/www.francescamoser.ch/access.log combined DocumentRoot /var/www/www.francescamoser.ch RewriteEngine on # ---------------------------------------- # Host-based rules must appear before path-based rules, otherwise a # path-based rule might kick-in before the appropriate host-based rule # ---------------------------------------- RewriteCond %{HTTP_HOST} ^francemoser.ch$ RewriteRule ^(.*)$ https://www.francescamoser.ch$1 [R,L] # ---------------------------------------- # Path-based rules must appear after host-based rules. # ---------------------------------------- # Redirect (almost) all requests to moser-naef.ch RewriteRule !^/robots.txt$ https://www.moser-naef.ch [R,L] Include conf-available/pelargir-francescamoser.ch-vhosts-ssl.conf </VirtualHost>
Test suite
What's this?
The links in the following sections should work. This can be used as a kind of test suite after changes to the Apache config have been made.
Note: The page DrupalMaintenance contains more tests that are related to Drupal.
Active resources
- http://herzbube.ch/pgp-key-signing-policy.html
- Must display my PGP key signing policy.
- git clone https://git.herzbube.ch/git/tools.git
- Must clone the Git repository "tools". If this works, it can be assumed that cloning will work as well for the remaining repositories.
- https://git.herzbube.ch/gitweb.cgi
- Must allow to browse my Git repositories (not for cloning, web access only)
- https://www.herzbube.ch/acexpander
- Must display (possibly after a redirect) the AceXpander project website. If this works, it can be assumed that the remaining project websites will work as well.
- https://www.herzbube.ch/robots.txt
- The robots.txt file for the main site.
- https://www.herzbube.ch/sitemap.txt
- The sitemap.txt file.
- https://wiki.herzbube.ch/robots.txt
- The robots.txt file for the wiki site.
- https://bugs.herzbube.ch/robots.txt
- The robots.txt file for the Bugzilla site.
- https://www.francescamoser.ch/
- Must redirect to moser-naef.ch
- https://pelargir.herzbube.ch/
- Must display a service overview.
Obsolete resources
- https://www.herzbube.ch/PGPHerzbubeAtHerzbubeDotCH.txt
- Must display a notice that this file is no longer in use.
- https://www.herzbube.ch/svn
- Must display a notice that I no longer use Subversion.
- https://www.herzbube.ch/Eredain
- Must display a notice about the demise of Eredain.