Introduction

Caudium Webserver has a powerfull Virtual Hosting System that can find its data from LDAP or (My)SQL server. It is working lika a charm and very usefull.
Apache 2.X has also a virtual hosting system but it still need to change the httpd.conf file every time you add a new virtual server and I don't like it.

Apache 2.x mod_*

There is several thrid party virtual hosting modules :

As you see there is not mutch choices, so I decided to code my own one based on mod_vdbh with some simplifications.

Design Considerations

I don't want to re-invent the wheel, so I have used libhome as authentification library. This library is a wrapper to getpwname() and can take its data from MySQL, LDAP or system password backend (even PAM). This library can also cache its data in a berkeley db for speed purposes.
With such authentification library you'll get all the flexibility you want to, and also easy configurations to update. mod_vhs will work automagically without any modifications inside you httpd.conf if you have a correct home.conf(5) file.

The module

What's new ?

Since mod_vhs 1.0.32
--------------------
o Fixed some compilation errors with Apache 2.2 (and automagicaly set debian
  compatibility)
o Added initial support for mod_suphp from Thomas Rasch
 
Since mod_vhs 1.0.30
--------------------
o Fixed some errors if #ifdef when using THREADS

Since mod_vhs 1.0.28
--------------------
o Added Makefile instead of using scripts
o Now mod_vhs should compile correctly under Debian/SARGE

Since mod_vhs 1.0.26
--------------------
o Added note about regexp problems with libhome
o Fixed a segfault when php entries are not corrects.

Since mod_vhs 1.0.24
--------------------
o Fix wrong paths and informations sent to apache / environment variables
  when vhs_Path_Prefix is used.
o PHP can be configured now using "passwd" libhome field.
o Fix some missing path values when used vhs_Path_Prefix
o Compile only what is needed. eg don't include php code or config
  variables when PHP support is not compiled into.

Since mod_vhs 1.0.22
--------------------
o Fixed openbasedir append function that didn't worked as it should.
o Fixed debug for openbasedir stuff.
o Added warning about Apache2 NameVirtualHost oddyty ...

Since mod_vhs 1.0.20
--------------------
o Removed unused variables, and make some code cleanup
o SuEXEC support has been removed because of conflict of structures
  between libhome and pwd.h (included by the needs of SuExec).
o vhs_Default_Host, always use redirect now. The vhs_Default_Host_Redirect
  configuration option is now removed
o Try to fix struct passwd conficts. To be tested.
o Added vhs_LogNotFound flag to enable / disable (disabled per default) logs
  into apache error log when a host or a path is not found. Patch by 
  Raphaël Jeudy.

Since mod_vhs 1.0.18
--------------------
o Removed VH_HOST variable since it is more or less unusuable and somewhat
  dangerous. You can enable it again by compiling mod_vhs with -DWANT_VH_HOST.
o Fixed compilation of mod_vhs when using Apache 2.0 branch (problems
  with ap_regex_t that exists only on Apache 2.1)
o Added open_basedir functions to append homedir to a default open_basedir
  path.
o Added experimental SUEXEC support. Not tested and not documented !
o According to Frédéric VANNIERE, mod_rewrite don't work when it
  is specified in module list... Another neat exception of Apache...
  Now mod_vhs should work with mod_rewrite...
o Use Apache internal regexp than "system" ones. This fix portability
  of this code on Debian


Since mod_vhs 1.0.16
--------------------

o Fixed a crash reported by Renato when parent lamer mode is on and the
  hostname was not found.
o New flag to enable / disble VHS (EnableVHS) default to Off to allow
  some VirtualServer to no have mod_vhs enabled.

Since mod_vhs 1.0.14
--------------------

o Lamer friendly mode is now fixed.
o Fixed a non thread safe call when lamer friendly mode is engaged.
o Added mod_alias "compatible" configuration values, eg : vhs_Alias, 
  vhs_ScriptAlias, vhs_Redirect, vhs_AliasMatch, vhs_ScriptAliasMatch,
  vhs_RedirectMatch, vhs_RedirectTemp and vhs_RedirectPermanent configuration
  directives. See mod_alias manual for more informations.


Since mod_vhs 1.0.12
--------------------

o Added option vhs_PHPdisplay_errors used on PHP support to show 
  php errors when needed on <VirtualHost></> basis.
o Added options on load that mod_vhs wait for input from mod_alias and
  mod_userdir before mod_vhs make things works.
o Added options on load that mod_vhs is making his work before mod_rewrite
  and mod_php is making their works.
o Added option vhs_Default_Host_Redirect (on/off) to force HTTP redirect
  if default host is triggered.
o The module should be now threads safe. Note that we don't garantee
  that your Apache will still be thread safe if you use non thread
  safe module (like mod_php for example).
o Add support for PHP 4.3.x. The following entries are modified according
  to <VirtualHost></> httpd.conf.
  Example :

   <VirtualHost 1.2.3.4>
   vhs_Default_Host www.mydomain.com
   vhs_PHPsafe_mode On
   vhs_PHPopen_basedir On
   </VirtualHost>


   <VirtualHost 1.2.3.5>
   vhs_Default_Host www.mydomain.com
   vhs_PHPsafe_mode Off
   vhs_PHPopen_basedir Off
   </VirtualHost>
  
  Option from Koen de Boeve


Since mod_vhs 1.0.10
--------------------

o Thanks to apache-dev now DOCUMENT_ROOT now gets the right value form
  mod_vhs.
o Server admin email, pathinfo and hostname now gets values from VHS.


Since mod_vhs 1.0.8
-------------------

o Removed unused code.
o Empty VH_ENVIRONMENT variable is removed and replaced by VH_GECOS
  with values from gecos returned from libhome or system.
o Removed DOCUMENT_ROOT "hack" since it doesn't seems to work
o Added "lamer mode" option (VHS option vhs_Lamer On/Off) to
  allow people that always add "www." to an address to be 
  magicaly handled by this module.

Since mod_vhs 1.0.6
-------------------

o DOCUMENT_ROOT & SERVER_ROOT environment variables 
  are now completly setup for PHP and some other
  scriptable environments. 

Since mod_vhs 1.0.2
-------------------

o Fix bad english in Changelog

Since mod_vhs 1.0
-----------------

o Create a ChangeLog file
o Fix compile.sh script
o DNS names are case insensitives, so HTTP/1.1 Host header should
  be case insensitive too

About Apache 2 and MPM=worker

This is a simple notice...
All development is done with FreeBSD and Apache2 NPM=prefork. I have added on 1.0.12 experimental thread safety. Please notice I cannot test it on heavy loaded system, so submits bugs reports, patches or success to the mailing list.

Mailing Lists

There is a mailing list server for mod_vhs: mod_vhs@lists.oav.net.

README.TXT

mod_vhs 1.0 - Virtual Hosting module

mod_vhs is an Apache 2.0 Web Server module allowing mass virtual hosting without
the need for file based configuration. The virtual host paths are translated
from a any database supported by libhome at request time.

Building and Installing Apache with mod_vh

mod_vhs is configured using the Apache 2.0 apxs system. Normaly all Apache 2.0
system should have this tool installed, so if you don't have it, you'll have
a problem :)

You will need a installed libhome into your system. Please fetch it at
http://pll.sourceforge.net/ before.

mod_vhs can be installed and configured using provided Makefile. Please
edit the Makefile and update it as your convience.

This will, as root, install mod_vhs into Apache 2.0 module directory and 
enable it in the configuration file. This is the prefered way to do it.
mod_vhs is enabled by default once the Apache configuration has been rebuilt.

Note: you can use a "slow" way to install it (eg: add the files into 
      apache 2 source tree and remake the configuration file, but I have
      never try that... so use a your own risk !).

Configuring mod_vhs in Apache Configure Files

In order to use mod_vhs with Apache Web Server server configuration blocks
will need to be configured with mod_vh configuration directives described
in the table below. mod_vhs configuration directives must be located in a
server configuration block (ie <VirtualHost></VirtualHost>).

EnableVHS:		Enable or Disable mod_vhs. Per default VHS is NOT
			enabled.
vhs_LogNotFound:	Enable or Disable logging into error log when
			mod_vhs cannot find the hostname in database.
			Per default this option is disabled.
vhs_libhome_tag :	Set Libhome tag. See home.conf(5) man page for usage.
			This option is not required, if not set the libhome
			tage will be set to "mod_vhs".
vhs_Path_Prefix :	Sets an optional location to prefix translations by.
			This option is not required.
vhs_Default_Host :	Sets the default host to use if a non-HTTP/1.1 request
			was received. This option is not required and usually
			won't do anything because the Apache Web Server by
			default catches these errors.
			Since we use internaly HTTP Rediect you MUST use 
			an URI.
vhs_Lamer :		boolean (On / Off), default to Off.
			If set, this will enable "lamer mode" option to
			allow people that always add an "www." to web
			addresses to be magicaly handled by this module.
vhs_PHPsafe_mode :	boolean (On / Off), default Off.
			If set, and if you have compiled mod_vhs with PHP
			support it will set safe_mode to on for the 
			virtual host otherwise php.ini defaults will be
			used.
vhs_PHPopen_basedir :	boolean (On / Off), default Off.
			If set, and if you have compiled mod_vhs with PHP
			support, it will set open_basedir to the home 
			directory given by libhome/mod_vhs otherwise php.ini
			defaults will be used.
vhs_open_basedir_path :	string. The open_basedir path that will be used to
			be set when vhs_PHPopen_basedir is set AND 
			vhs_append_open_basedir.
vhs_append_open_basedir:boolean (On / Off), default Off.
			Is set, mod_vhs will append the homedir path into
			vhs_open_basedir_path.
			NOTE :	mod_vhs open_basedir option will OVERIDE
				php.ini settings.
vhs_PHPdisplay_errors :	boolean (On / Off), default Off.
			If set, and if you have compiled mod_vhs with PHP
			support, it will enable display_errors to be shown,
			otherwise php.ini defaults will be used.
vhs_PHPopt_fromdb :	boolean (On / Off), default Off,
			If set, and if you have compiled mod_vhs with PHP
			support, it will alter PHP configuration using
			libhome passwd unused field. See README.phpopt
			for more detailed example.
vhs_Alias, vhs_ScriptAlias, vhs_ScriptAliasMatch, vhs_RedirectTemp and
vhs_RedirectPermanent :	mod_alias 100% compatible options inside mod_vhs.
			Please see http://httpd.apache.org/docs-2.0/mod_alias.html
			for more informations.

Notes about vhs_PHP* values :

	All this options *will* override the default PHP values you have
	set into php.ini. For example if you have in php.ini safe_mode = On,
	and in a <VirtualHost></> you get a vhs_PHPsafe_mode Off then the
	value of php.ini will be safe_mode = Off. 

Example :

You have set home.conf with such data :

mode ldap
ld_hosts 127.0.0.1
ld_base . ou=whosting,dc=kazar,dc=net
ld_version 3
ld_timeout 5

[mod_vhs]
log.stderr y
where wwwDomain
user wwwDomain
home homeDirectory
uid uidNumber
gid gidNumber
gecos description
passwd "*"
shell /dev/null
quota FTPQuotaMBytes
class admin@foo.com

You get such ldap entry :

#
# LDAPv3
# base <ou=whosting,dc=kazar,dc=net> with scope sub
# filter: wwwDomain=jb.kazar.net
# requesting: ALL
#

# 'jb.kazar.net', whosting, kazar.net
dn: wwwDomain='jb.kazar.net',ou=whosting,dc=kazar,dc=net
objectClass: top
objectClass: kazarPerson
objectClass: PureFTPdUser
uid: jb
description: JB Home page
uidNumber: 65534
gidNumber: 65534
FTPuid: 65534
FTPgid: 65534
FTPStatus: enabled
userPassword:: xxxxxxxxxxxxx
homeDirectory: /hosting/http/j/b/k/jb.kazar.net/
FTPQuotaMBytes: 50

A simple test to see if your libhome map will work :

$ home_finger -t mod_vhs jb.kazar.net
login: jb.kazar.net
passwd: *
uid: 65534
gid: 65534
gecos: JB Home page
home: /hosting/http/j/b/k/jb.kazar.net/
shell: 
expire: 0
quota: 50
class: admin@foo.com

Note that class will be used for server admin mail inside Apache (usualy 
diplayed for webmasters, and/or errors).

Then if you set the DNS entry for jb.kazar.net to 10.1.2.3, the following 
apache2 configuration file will look for jb.kazar.net files in 
/hosting/http/j/b/k/jb.kazar.net/ :-)

NameVirtualHost 10.1.2.3

<VirtualHost 10.1.2.3>
    vhs_Default_Host http://devnull.oav.net
</VirtualHost>

Other handlers should still work accordingly.  mod_vhs declares its
translate_name phase as AP_HOOK_FIRST so it can run before other translations.
An example configuration allowing mod_tcl in specific directories follows.

<VirtualHost 10.2.3.4>
    vhs_Default_Host http://devnull.oav.net

    <Directory /hosting/http/j/b/k/jb.kazar.net>
        AddHandler tcl-handler tm

        Tcl_ContentHandler content_handler
    </Directory>
</VirtualHost>

With PHP support you can do also :

<VirtualHost 1.2.3.4>
   vhs_Default_Host http://www.mydomain.com
   vhs_PHPsafe_mode On
   vhs_PHPopen_basedir On
</VirtualHost>


<VirtualHost 1.2.3.5>
   vhs_Default_Host http://www.mydomain.com
   vhs_PHPsafe_mode Off
   vhs_PHPopen_basedir Off
</VirtualHost>


Additional Information

mod_vhs will check on every connection if data exist or not. If you don't want
to hammer your LDAP/MySQL server please use cache_file and cache_ttl values in
home.conf(5).

References

mod_vhs is an Apache 2.0 module using libhome library, more about 
Apache Web Server can be found at http://www.apache.org/.
Documentation regarding libhome can be found at http://pll.sourceforge.net/
This module was highly inspired from mod_vdbh, I wishe to send many thanks
to Michael K Link <mlink@apache.org> that helped me a lot to give me a 
good start to make my module work, mod_vdbh homepage : http://www.synthemesc.com/mod_vdbh/.


Author

Send bugs, ideas, fixes, patches, and food to :
Xavier Beaudouin <kiwi@oav.net>

Home page of this module 

http://www.oav.net/projects/mod_vhs/

README.phpopt

This README file will explain the limits and how mod_vhs will configure
PHP "on the fly".

Introduction
------------

mod_vhs when compiled with -DHAVE_MOD_PHP_SUPPORT, uses zend_alter_ini_entry()
to change on the fly parameters like you can do with php.ini entry.


mod_vhs apache configuration directives
---------------------------------------

There is several directives (see README file from more) :

	vhs_PHPsafe_mode
	vhs_PHPopen_basedir
	with :	vhs_open_basedir_path
		vhs_append_open_basedir

	vhs_PHPdisplay_errors

	and
	
	vhs_PHPopt_fromdb

How are evaluated php configuration directives ?
------------------------------------------------ 

They are evaluated in this order (if they are enabled) :

1- vhs_PHPsafe_mode
2- vhs_PHPopen_basedir (and also vhs_open_basedir_path / vhs_append_open_basedir)
3- vhs_PHPdisplay_errors
4- vhs_PHPopt_fromdb

You have to know this order of evaluation if you don't have brain damage when 
you use vhs_PHPopt_fromdb and security problems that you can have because
of this order of evaluation.


Why there can be a security problem ?
-------------------------------------

vhs_PHPopt_fromdb is evaluated at the end of PHP autoconfiguration. If you
set : 
 vhs_PHPsafe_mode On

And in the field used by vhs_PHPopt_fromdb : safe_mode=Off;

Then the configuration of PHP will be safe_mode=Off. 

vhs_PHPopt_fromdb will ALLWAYS HAVE THE LAST WORD in terms of PHP configuration.

This is NOT a bug, but a feature. So you _need_ to be 100% sure the 
php autoconfiguration from DB will be set to people you trust in terms
of security.

vhs_PHPopt_fromdb format
------------------------

mod_vhs will take his parameters from libhome using 'passwd' field.

The format is :

<parameter>=<value>;<parameter>=<value>;

With <parameter> = php.ini parameter (like safe_mode for example)
     <value>     = php.ini value of this parameter (On for example)

WARNING 1 : you MUST NOT add space or forgot a ";" at the end of ligne
            CR / LF are passed as is to PHP. So double check the entries
            in database.
WARNING 2 : If you don't have anything in you "passwd" entry libhome
            will not return anything from DB because this can be
            a null password. So add an default string when php options are
            not used (like for example "*").
WARNING 3 : If parameter is boolean (eg On / Off) you have to write in DB
            using 1 / 0 instead eg :
		On  = 1
		Off = 0

vhs_PHPopt_fromdb full example
------------------------------

This example uses MySQL but you can adapt it to your system :

MySQL Database :
 
CREATE TABLE `vhost` (
  `ServerName` varchar(100) NOT NULL default 'name.foo.tld',
  `ServerAdmin` varchar(100) NOT NULL default 'root@foo.tld',
  `DocumentRoot` varchar(100) NOT NULL default '/tmp/null',
  `CustomLog` varchar(100) NOT NULL default '/var/log/undefined_apache_host.log',
  `SuexecUserGroup` varchar(100) NOT NULL default 'nobody nogroup',
  `SetEnv` varchar(100) NOT NULL default '/tmp',
  `domain_id` mediumint(9) NOT NULL default '0',
  `owner` varchar(50) NOT NULL default 'me',
  `stats` enum('off','on') NOT NULL default 'on',
  `statsdone` enum('no','yes') NOT NULL default 'no',
  `isalias` enum('0','1') NOT NULL default '0',
  `PointTo` varchar(255) NOT NULL default 'null.foo.tld',
  UNIQUE KEY `ServerName` (`ServerName`)
) TYPE=MyISAM;

INSERT INTO `vhost` VALUES 
	('mrjack.oav.net', 'me@foo.tld', '/usr/local/www/mrjack',
	 '/usr/local/www/mrjack', '/tmp/access.log', 'mrjack ftp',
	 'memory_limit=32M;upload_max_filesize=8M;expose_php=0;', 1, 'mrjack', 'on',
	 'yes', '1', 'mrjack.oav.net');

We have a virtual host 'mrjack.oav.net' with php values :
memory_limit=32M
upload_max_files=8M

libhome configuration :

# more /usr/local/etc/home.conf
mode mysql
myhosts localhost
myuser vhostuser
mypasswd vhostpasswd
mydatabase hosting

[mod_vhs]
log.stderr y
where ServerName
user ServerName
home DocumentRoot
uid "80"
gid "80"
gecos PointTo
passwd SetEnv
shell owner
quota "1000"
table vhost
class ServerAdmin

Apache2 configuration :

Listen 8000
<VirtualHost 1.2.3.4:8000>
  EnableVHS On
  vhs_LogNotFound On
  vhs_Default_Host http://oav.net/
  vhs_Lamer On
  vhs_PHPsafe_mode On
  vhs_PHPopen_basedir On
  vhs_open_basedir_path /tmp:/var/tmp
  vhs_append_open_basedir On
  vhs_PHPdisplay_errors On
  vhs_PHPopt_fromdb On
</VirtualHost>

IMPORTANT NOTE
--------------

Since mod_vhs use Zend functions to change the php ini values, you NEED
to load mod_php *before* mod_vhs otherwise errors like :

Syntax error on line 269 of /etc/apache/httpd.conf:
Cannot load /usr/libexec/apache/mod_vhs.so into server: /usr/libexec/apache/mod_vhs.so: undefined symbol: zend_alter_ini_entry  


Conclusion
----------

vhs_PHPopt_fromdb can only configure php.ini values like foo=value, but it 
cannot configure specific section of php.ini (eg [mysql] for example). So
you'll have to keep that in mind when designing your system.

$Id: README.phpopt,v 1.3 2005/12/14 16:43:04 kiwi Exp $

README.logs

Here is some hint to get logs per db-vhost given from 
Micha Dalecki and updated by me :)

1. home.conf (libhome)

Add a line to add gecos field with database stuff:
(Here is LDAP configuration, adapt it to your setup)

[mod_vhs]
where wwwDomain
user wwwDomain
home homeDirectory
uid uidNumber
gid gidNumber
gecos wwwDomain
passwd "*"
shell /dev/null

2. In httpd.conf:
LogFormat "%{VH_GECOS}e %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" vdbh_combined
Which is exatly the same as:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
except %{VH_GECOS}e at the beginning.
Don't use %V because it is the content of Host: HTTP header so it cannot be trusted.
Also you must be aware that ${VH_HOST}e is directly extracted from Host: header with some more modifications than %V, but it should NOT be trusted.

So for 'common':
LogFormat "%h %l %u %t \"%r\" %>s %b" common
LogFormat "%{VH_GECOS}e %h %l %u %t \"%r\" %>s %b" vdbh_common

and so other...

3. Make an executable script, in my case:
root@mip ~# cat /usr/sbin/mod_vdbh_log
#!/bin/bash
LOG_PATH=$1
while read name line; do
    echo $line >> $LOG_PATH/${name}_access_log;
done
root@mip ~#

3. Inside <VirtualHost></> define CustomLog like this:
CustomLog "|/usr/sbin/mod_vdbh_log /var/log/httpd/vdbh" vdbh_combined

Restart apache. At this moment you can enjoy separate logs for every database vhost.
Remember to make /var/log/httpd/vdbh directory, and give apache write permission to it.

This can't be done for ErrorLog, because ErrorLog isn't customizable.



README.mod_suphp

This is README for supporting mod_suphp within mod_vhs.

Please see http://www.suphp.org/ homepage before asking about what is
mod_suphp.

To enable suPHP, you have to enable the compilation variable 
HAVE_MOD_SUPHP_SUPPORT in the Makefile or in the apxs command line.

Check that mod_suphp is compiled with SUPHP_USE_USERGROUP to get full 
support (if there is a good way to get sure of that while loading 
mod_vhs as module, contact me).

A new configuration variable is added to the apache virtual host configuration:
vhs_suphp_config_path /users/%s/config

The %s will be replaced by the username which libhome gives back for the hostname.
SuPHP will look for a php.ini in this path for the given user, it basically needs
to contain only one line (or whatever options you want to change for the user):
open_basedir = /users/MYUSER/data

mod_vhs will set the SuPHP-Variables "suPHP_Engine", "suPHP_ConfigPath" and
"suPHP_UserGroup" for each request in the "vhs_suphp_handler"-method.
The first problem here is that suphp expects a per-directory configuration,
which can only be set in the handler, but not in "vhs_translate_name" method.


This is for now basic support, if you get some more patches and updates
don't hesitate to contact me.


Versioning

I have been requested to write a little note about versioning. I use same method as Linux and lots of OpenSource projects :)

Download

Feedback

Bugs, flames, money, junk food or postcard can be sent to Xavier Beaudouin <kiwi@oav.net>

If you wishes to send money (that I will use to pay hosting....) please feel free to use my paypal account : kiwi@kazar.org or click on the following button :

Thanks

I wishe to thanks Michael K Link for his mod_vdbh module I took to start my project.

Related

I have learnt that we can do similar work with mod_perl. Here is an article about how to make such setup.
I use some undocumented code from mod_perl to set document root from a module.
Some apache developpers don't like it... but the fact is that Apache internal API are really undocumented and somewhat prehistorics... So bad that Apache 2.x didn't fix such problems...
Some French article on mod_vhs, thanks to Frédéric Vannière.

(c)Copyright 1997-2005 - Xavier Beaudouin - Site hosted by Kazar