Home > Virtual Hosting | Japanese
Some methods are examined that are used to avoid writing VirtualHost directives as many as the number of domains in Apache web server.
In a Corona-quarantine time, we are looking a job that can be done remotely. We accept order of network infrastructure or site construction job. Planning to make things work via mail or chat, or phone or video as possible. Please contact.
Recently I moved KobuCom's web and mail servers to a cheaper VPS (virtual private server) and added free SSL certificates from Let's Encrypt. In doing so, I used methods called dynamically configured mass virtual hosting to simplify virtual host configuration in Apache web server. I like to share the experience here.
The number of domains I set up was just three. Even though I don't feel good when I repeat the same settings in more than one place. The dynamic methods are good for my mental health.
On searching for a way to avoid repetition of VirtualHost's, I found the following discussion:
Sharing configuration between several VHosts
https://stackoverflow.com/questions/18714293/sharing-configuration-between-several-vhosts
One answer says Apache proposes three methods to do it:
Module | Description | Difficulty | Flexibility |
---|---|---|---|
mod_vhost_alias | Variable path | Simple | Limited |
mod_macro | Macro expansion | Relatively simple | Not so limited |
mod_rewrite | URL rewriting | Difficult | Unlimited |
Of these, I tested the first two. Eventually I used mod_vhost_alias for HTTP port 80 virtual hosting and mod_macro for HTTPS port 443 in my site.
I will show you in turn simple configuration examples used in my experiment. I tested with Apache2 v2.4.38 on Raspberry Pi's Raspbian (Debian 10) on a local lan. I assume the reader has knowledge of basic Apache configuration and virtual host settings (name-based vs IP-based, etc.). Related links in Apache are shown at the end of this page.
I will use the following two domains in examples below. Name-based virtual hosting is used instead of IP-based.
A traditional static configuration is
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com/html
ScriptAlias "/cgi-bin/" "/var/www/example.com/cgi-bin/"
# other settings
</VirtualHost>
<VirtualHost *:80>
ServerName example.org
ServerAlias www.example.org
DocumentRoot /var/www/example.org/html
ScriptAlias "/cgi-bin/" "/var/www/example.org/cgi-bin/"
# other settings
</VirtualHost>
You must repeat VirtualHost settings the number of times of the domains served by Apache.
I first tried vhost_alias module. This module was already included in Debian 10 and CentOS 8. You have to enable it with "a2enmod" in Debian.
Here is an example of VirtualHost using the vhost_alias module.
<VirtualHost *:80>
UseCanonicalName Off
VirtualDocumentRoot "/var/www/%-2.0.%-1.0/html"
VirtualScriptAlias "/var/www/%-2.0.%-1.0/cgi-bin/"
# other common settings can be added here
</VirtualHost>
"UseCanonicalName" indicates how to determine a requested domain name. "Off" takes from "Host" header while "DNS" means a reverse DNS lookup. "Off" is for name-based virtual hosting. "DNS" is for IP-based hosting. "VirtualDocumentRoot" and "VirtualScriptAlias" specify locations where static or dynamic contents reside, respectively. In IP-based hosting, "VirtualDocumentRootIP" and "VirtualScriptAliasIP" are used instead. A portion dynamically determined on reception of a request is "%-2.0.%-1.0". This represents the last two parts of a domain name delimited by dots (.). The variable part will be "example.com" if a requested domain name is either "example.com" or "www.example.com". I planned to hit the same directory whether "www" is present or not.
The mod_vhost_alias's path component pattern syntax needs a little explanation. The apache document presents concise tables and some examples. I quote the tables.
A variable pattern can contain:
%% | insert a % |
%p | insert the port number of the virtual host |
%N.M | insert (part of) the name |
and both 'N' and 'M' takes the following values:
0 | the whole name |
1 | the first part |
2 | the second part |
-1 | the last part |
-2 | the penultimate part |
2+ | the second and all subsequent parts |
-2+ | the penultimate and all preceding parts |
1+ and -1+ | the same as 0 |
Now let me show you some patterns using 'www.example.com' as an example:
Pattern | Value | Remark |
---|---|---|
%0 | www.example.com | whole domain name |
%1 | www | fisrt dot-delimited component |
%-1 | com | last component |
%1.0 | www | whole string of the first component |
%-1.0 | com | whole string of the last component |
%-2.0 | example | whole string of the second last component |
%1.1 | w | first character of the first component |
%-1.-1 | m | last character of the last component |
I suppose you now understand what '%-2.0.%-1.0' means. It consists of '%-2.0', literal dot and '%-1.0'. In this example, it represents 'example.com'.
This is a directory I used for the test:
$pwd
Let me show you content of the files.
$cat example.com/html/index.html example.com
$cat example.com/cgi-bin/test.cgi #!/bin/bash echo 'Content-Type: text/plain' echo '' echo test.cgi of example.com running
You see the same contents in the "example.org" directory except "com" is changed to "org".
Let me test with HTML files.
$ curl http://example.com/ example.com $ curl http://example.org/ example.org
Next, try CGI scripts.
$ curl http://example.com/cgi-bin/test.cgi test.cgi of example.com running $ curl http://example.org/cgi-bin/test.cgi test.cgi of example.org running
Also try a case with "www" attached to the domain.
$ curl http://www.example.com/ example.com $ curl http://www.example.com/cgi-bin/test.cgi test.cgi of example.com running
It is easy to use vhost_alias module to configure dynamic virtual hosts.
However, only changeable values are DocumentRoot and ScriptAlias.
If you need other settings different per domain, mod_vhost_alias is not usable.
The mod_macro module is more flexible.
## mod_macro
The second method I tried is macro module.
This module was already included in Debian 10 and CentOS 8.
You have to enable it with "a2enmod" in Debian.
Here is an example of VirtualHost using mod_macro.
<Macro VHost $domain> <VirtualHost *:80> ServerName $domain ServerAlias www.$domain DocumentRoot "/var/www/$domain/html" ScriptAlias "/cgi-bin/" "/var/www/$domain/cgi-bin/" # other per-domain settings can be added here
Use VHost example.com Use VHost example.org
UndefMacro VHost
A macro definition starts from "Macro VHost" and ends with "/Macro".
The macro argument $domain indicates a variable domain name.
"Use VHost" expands the macro into a settings having the value of $domain.
In this case, two sets of VirtualHost blocks for "example.com" and "example.org" are created.
"UndefMacro" indicates no more "Use" appears in the rest of the file.
Let me test.
$ curl www.example.com example.com $ curl www.example.org example.org $ curl example.com example.com $ curl example.org example.org $ curl example.com/cgi-bin/test.cgi test.cgi of example.com running $ curl example.org/cgi-bin/test.cgi test.cgi of example.org running
The first introduced mod_vhost_alias is *dynamic* in real meaning.
Without prior designation, any domain name published through your DNS can be a target of virtual hosting.
In a mod_macro case, static settings for domains designated with "Use" are created during Apache startup.
Other domains are not a target of virtual hosting.
## mod_rewrite
The last method is to rewrite URL arbitrarily using the rewrite module.
An [apache document](https://httpd.apache.org/docs/trunk/rewrite/vhosts.html) shows some examples of virtual hosting using mod_rewrite.
I quote one example where _site_.example.com refers to /home/_site_/www.
RewriteEngine on RewriteMap lowercase int:tolower RewriteCond %{HTTP_HOST} !^www. RewriteCond ${lowercase:%{HTTP_HOST}} ^([^.]+).example.com$ RewriteRule ^(.*) /home/%1/www$1
This page also states:
>mod_rewrite is usually not the best way to configure virtual hosts. You should first consider the alternatives before resorting to mod_rewrite.
I agree with this.
Using mod_rewrite is difficult and requires lots of time and effort especially in debugging a script.
It's hard to understand a script written by others or me six months ago.
I am trying not to use it as possible.
About virtual hosting, I recommend first think if mod_vhost_alias can do and use mod_macro if not.
## References
Dynamically Configured Mass Virtual Hosting
https://httpd.apache.org/docs/trunk/vhosts/mass.html
Apache Module mod_vhost_alias
http://httpd.apache.org/docs/2.4/mod/mod_vhost_alias.html
Apache Module mod_macro
http://httpd.apache.org/docs/2.4/mod/mod_macro.html
Dynamic mass virtual hosts with mod_rewrite
https://httpd.apache.org/docs/trunk/rewrite/vhosts.html
An In-Depth Discussion of Virtual Host Matching
https://httpd.apache.org/docs/2.4/vhosts/details.html
## Notice
We are willing to do network infrastructure or site construction jobs in a remote style.
Please contact.
## ![Kobu.Com Logo](../images/kobulogo.png)
Written 2020-May-03