Table of Contents

  1. Overview

  2. Installation and Quick Start
      2.1 License
      2.2 System Requirements
      2.3 Install and Upgrade
      2.4 Quick Start

  3. vHost Commands
      3.1 Introduction
      3.2 Command and Profile
      3.3 Command and Login Level
      3.4 Environment Variables
      3.5 Parameters and Switches
      3.6 User Input
      3.7 Exit Code
      3.8 Command Usage Details
             # vhost --addvroot
             # vhost --delvroot
             # vhost --adddns
             # vhost --deldns
             # vhost --addhost
             # vhost --delhost
             # vhost --addhali
             # vhost --delhali
             # vhost --adduser
             # vhost --deluser
             # vhost --adduali
             # vhost --deluali
             # vhost --passwd
             # vhost --access
             # vhost --qhost
             # vhost --quser
             # vhost --lshost
             # vhost --lsuser
             # vhost --cphost
             # vhost --uphost
             # vhost --addmydb
             # vhost --delmydb
             # vhost --hostlog
             # vhost --cmdlog
             # vhost --reload
      3.9 Undocumented Commands
             # vhost --rotatelog
             # vhost --getvalue
             # vhost --getdns
             # vhost --modpass
             # vhost --vdeliver
             # vhost --poprelay
             # vhost --netpulse
             # vhost --uninstall
             # vhost --install
             # vhost --version
             # vhost --support
             # vhost --require
             # vhost --history
             # vhost -q

  4. Data and Directory Structure
      4.1 Files and Directories
      4.2 Special Users and Groups

  5. Profiles, Modules, and Virtual Services
      5.1 Introduction
      5.2 Profile Essentials
      5.3 Module Essentials
      5.4 Modules and Virtual Services
             # V00hostconf
             # V01network
             # V10apache
             # V15proftpd
             # V15wu-ftpd
             # V20postfix
             # V20sendmail
             # V25pop3d
             # V30openwebmail
             # V30squirrelmail
             # V35awstats
             # V35webalizer
             # V40mysql
             # Vxxsample

  6. Security and Login Levels

  7. Quota Control

  8. Distributed Setup (Clustering)
      8.1 Introduction
      8.2 Configuration

  9. WebGUI

10. Misc. Tips, Hacks, and FAQs
      10.* Perl RegEx and UTF8 Bug
      10.* vHost and SELinux
      10.* $dotChar, $unameLen
      10.* About the Main Host
      10.* DNS on an All-in-One Box
      10.* A Non-root Superuser
      10.* vhost --lshost Speedup
      10.* Virtual FTP
      10.* Virtual POP3
      10.* Virtual POP3/Webmail Login
      10.* Virtual SMTP and SpamAssassin, ClamAV
      10.* Mail Forwarder, Autoresponder

11. vHost API

12. Credits

1. Overview

vHost is a one-step solution for all virtual hosting needs.  It enables a Linux/BSD server with single or multiple IP addresses to function as unlimited virtual hosts with HTTP, FTP, SMTP, POP3, IMAP, and other virtual services extendible via modules.  It comes with both a command-line interface and a web-based GUI ("control panel"), offering maximum control to a domain's owner while relieving the system administrator of most routine administration tasks.  Other major features include four levels of login, comprehensive quota control, and built-in clustering capability.  

As a system utility attempting to create a robust and standard-compliant virtual hosting platform, the general philosophy of vHost is to follow the proper spirit of Unix, and to be powerful yet simple at the same time.  

vHost is not a general-purpose virtualization system.  It is specifically designed for hosting purposes, and it aims to be practial.  Virtualizations are done at the userland/application level (as opposed to the OS/kernel level).  This gives major advantages such as minimum system overhead and footprint, ease of installation and upgrade, and cross-platform compatibility.  

vHost is not a web-centric "control panel".  Even though it does come with a web-based GUI, under the hood vHost is command-centric, with major features and virtualizations implemented in commands and modules.  For that matter the default web-based GUI can be easily replaced with a customized version or even an X-based GUI.  (The default GUI in its current form, is deceptively simplistic, and minimalist to many people.  There will be major cosmetic enhancements in the upcoming 4.0 release.)  

There is no plan to port vHost to Windows in the foreseeable future.  

2. Installation and Quick Start

2.1 License

vHost is licensed under the GPL, the GNU General Public License.  

2.2 System Requirements

Currently vHost has been tested on NetBSD, FreeBSD, and several major Linux distributions including RedHat/Fedora, Debian, and CentOS.  There is no reason why it wouldn't work on other distributions.  

Minimum system requirements are Perl and GCC in order to get vHost installed.  Depending on virtual services running on the system, various third party packages are needed.  PHP 4.10 or higher is required in order to use the web-based GUI.  

2.3 Install and Upgrade

To install or upgrade vHost, follow these simple steps:  

0. Download, cd into the download directory
1. tar -zxvf vhost-3.31r1.tar.gz
2. cd vhost-3.31r1
3. less README
4. su
5. make install

When installing, vHost will detect any previous version existing on the system and automatically carry out necessary upgrade procedures.  While upgrading, previous system configurations are retained in order to ensure zero system downtime.  

The installation is successful when it shows the message "installation completed".  After "press ENTER to continue", you may encounter a few error messages, which means that you will need to make adjustments to certain configuration variables.  The error messages, which can be repeated by running command "/usr/sbin/vhost", will indicate exactly which module files and configuration variables need to be changed.  Open each module in a text editor and make changes to relavant variables according to their comments.  The system is properly configured when the command usage info appears while running "/usr/sbin/vhost".  Note that third-party packages required for virtual services such as Apache, SquirrelMail etc. are not included in this distribution.  Make sure those packages are installed and working properly on the system.  

If you get the "invalid main host name" error while installing, it means that your system's main host name is not a Fully Qualified Domain Name (FQDN) in the form of "host.domain.com".  An FQDN is necessary for a host to be uniquely identifiable on the internet.  For testing purpose, you can change the main host name to an FQDN like "myhost.com" and put an entry in "/etc/hosts", and vHost will stop complaining.  The main host name can be changed with command "hostname myhost.com", or edit "/etc/sysconfig/network" on RedHat or derived systems (other systems vary) to make the change permanent.  The entry in "/etc/hosts" should look like "[ip_address] myhost.com", where "[ip_address]" is the main host's IP address.  

If vHost is being installed on a system for the first time, it will take a few moments to complete certain configuration and initialization steps, including quotacheck which can be particularly lengthy.  There will not be any feedback on screen.  However it is important not to interrupt the process.  Otherwise quotacheck will need to be run manually in order to enforce disk quota.  This is also true when $VHOME (in "/etc/vhost.d/V00hostconf") is changed to a new file system.  The first command run after the change will likely take longer to complete due to quotacheck on the new file system.  

2.4 Quick Start

There are quite a few vHost commands.  Some of the most frequently used commands are: --addhost, --adduser, --lshost, --lsuser.  

Assuming vHost is installed with virtual web enabled, login as root and run the following command-line sequence:  

mv /etc/hosts /etc/hosts.0
ln /etc/vhosts /etc/hosts
vhost addhost test.com owner -f
vhost adduser test.com user
vhost lshost
vhost lsuser
vhost lsuser test.com
mozilla http://test.com
mozilla http://test.com/~user
mv /etc/hosts.0 /etc/hosts

3. vHost Commands

3.1 Introduction

vHost carries out all its functions via shell commands in the form of "/usr/sbin/vhost --command [parameter ...] [switch ...]".  Each command completes a well defined task.  Commands are interpreted by the main vHost script /usr/sbin/vhost.pl, which does some basic but essential core operations and then calls various "modules" to get configuration values and complete specific service related operations.  Modules are Perl scripts put together in a directory called a "profile".  vHost comes with a set of default modules related to common services such as Apache and Sendmail.  Users are encouraged to create their own modules or modify the default ones in order to add new commands or new features to existing commands.  The web-based GUI is simply a wrapper which does everything by running these commands.  

The syntax of vHost commands are fairly straight forward.  The usage info page, which is displayed every time a command is invoked with wrong syntax or without parameters, covers most aspects of command usage.  However, due to brevity restriction, there are subtleties in some of the commands that are left out of the usage info page.  These are explained here in details on a command by command basis.  There are also a few "undocumented" commands for vHost's own internal use, which may be of interest for advanced users.  

3.2 Command and Profile

Each vHost command has an associated profile at run time.  A profile is a directory containing a set of modules.  The default profile is /etc/vhost.d.  By allowing commands, virtual hosts, virtual host owners, and virtual root users ("vroot") to associate with customizable profiles, vHost offers great configurability and flexibility.  

A virtual host and its owner are automatically associated with a profile when the host is being created with command "vhost --addhost".  While a virtual host can only be associated with one profile, a host owner can be associated with multiple profiles through creations of multiple hosts.  A virtual root user is associated with a profile via command "vhost --addvroot".  Access and security relations among vHost commands, virtual hosts, virtual host owners, and virtual root users naturally emerge from associations of profiles.  

A profile can be explicitly specified at the command-line with option "-p profile_path".  The actual profile associated with a command is determined by the following process:  

If a host is specified at the command line, and the host exists and is not a deleted host, the profile associated with that host will be used.  The profile specified at the command line, if any, will be ignored.  

Otherwise, if a valid profile is specified at the command line or defined by environment variable VHOST_PROFILE, that profile will be used.  

Otherwise, if a host owner is specified at the command line, and the host owner has valid associated profile(s), the first associated profile will be used.  

Otherwise, if the current user who is running the command has valid associated profile(s), the first associated profile will be used.  

Otherwise, the default profile, /etc/vhost.d, will be used.  

For more details regarding profile, see Chapter 5. Profiles, Modules, and Virtual Services.  

3.3 Command and Login Level

Most vHost commands behave differently depending on the login level of the user who runs the command.  For example, different users will see different output from command "vhost --lshost" or "vhost --cmdlog".  The differences are transparent to users.  vHost will automatically adjust its behavior according to users and their login levels.  

There are four login levels: root, virtual root user ("vroot"), virtual host owner, and virtual user.  For more details regarding login levels, see Chapter 6. Security and Login Levels.  

3.4 Environment Variables

Most vHost commands behave differently with the presence of certain environment variables.  Following is a complete list of these variables:  

VHOST_HOSTNAME
VHOST_USERNAME
VHOST_PASSWORD
VHOST_PROFILE
VHOST_DEBUG
VHOST_LOCAL
VHOST_CHILD
VHOST_NEWIP
VHOST_NEWVU
VHOST_USRID
VHOST_VDATE
VHOST_QHOST
VHOST_QUSER
PAGER

Most of these environment variables are used internally by vHost.  Only a few of them can be set manually at the command line (by non-root users):  

VHOST_HOSTNAME

Define a virtual host.  If this environment variable is present, the user who's running the command will be treated as a virtual user on the defined virtual host.  

VHOST_USERNAME
VHOST_PASSWORD

These two environment variables must be present at the same time.  They effectively change the identity of the user who's running the command.  This is useful for programically calling vHost commands from other applications, such as the web GUI.  

VHOST_PROFILE

Define the profile associated with the current command.  The command-line switch "-p" takes precedence over this environment variable.   For more details, see 3.2 Command and Profile.  

PAGER

Define a pager program for command "vhost --hostlog" and "vhost --cmdlog".  The pager program must be a secure executable, or it will be ignored.  This environment variable overwrites $PAGER (module V00hostconf).  

3.5 Parameters and Switches

vHost commands generally have the form of "/usr/sbin/vhost --command [parameter ...] [switch ...]".  The leading "--" part of a command is optional.  Commands are immediately followed by parameters, whose position and order are important.  One common parameter pattern is "host_name user_name".  Switches must come after parameters, whose order does not matter.  They can be stacked together as in standard Unix commands.  One exception is the "-p profile_path" pair, which can be placed anywhere in a command.  Common switches include "-f" which forces a command to run in certain conditions and also bypasses user input, "-d" which forces deleting data but is only meaningful when "-f" is present, and "-q" which quits a command before it reloads virtual services.  Two "undocumented" switches, "-h" and "-u", can be used to eliminate potential ambiguity in certain commands that take either "host_name" or "user_name" as a parameter, such as --lshost, --lsuser, --cphost, --uphost.  

3.6 User Input

Some vHost commands require user inputs such as password or confirmation.  These commands only start operations after all user inputs are gathered, therefore it is safe to interrupt such a command with Ctrl-C at the user input stage, and no change will be made to the system.  

3.7 Exit Code

All vHost commands generate an exit code upon completion.  The default exit codes are:  

0 - Successful Completion
1 - System Configuration Error
2 - Command Syntax Error
3 - Permission Denied
4 - Quota Exceeded
5 - Inappropriate Operation
6 - Aborted at Prompt (not by Ctrl-C)
7 - File Locking Failure
127 - Login Incorrect

Note that exit code can be set to any arbitrary value by customized modules.  

3.8 Command Usage Details

# vhost --addvroot profile_dir [vroot_name] [-c] [-f]

Associate a virtual root user ("vroot") with a profile.  If <vroot_name> does not exist, it will be created as a user.  If <profile_dir> does not exist, it will be created as a symlink (default) or copy ("-c" switch) of the profile associated with the current command (see 3.2 Command and Profile).  If <vroot_name> is not specified, simply create <profile_dir>.  

A vroot has root-like privileges under associated profiles.  One vroot can have multiple associated profiles, and one profile can have multiple associated vroots.  

# vhost --delvroot profile_dir [vroot_name] [-f]

Dissociate a virtual root user ("vroot") from a profile.  If <vroot_name> is not specified, dissociate all virtual root users from <profile_dir>, and delete <profile_dir> if it doesn't have associated virtual hosts.  

# vhost --adddns host_name [ip_address] [-z] [-i] [-q] [-f]

Add DNS record for <host_name> and <ip_address>.  If <ip_address> is not specified, vHost will look for <host_name> as a virtual host on the system and use its assigned IP address, or in case <host_name> does not exist as a virtual host, it will pick an IP address according to $IPADD (module V00hostconf).  Obviously, <ip_address> should always be specified unless this command is invoked after the "vhost --addhost" command.  

vHost will automatically figure out whether the DNS record needs to be created as a new DNS zone, or a new entry in an existing zone.  The "-z" switch can be used to force creating a new zone.  If <host_name> is a sub-level host whose parent domain is listed in $TLDs (module V00hostconf), it will be created as a new zone instead of an entry in parent domain's zone.  

When creating a new DNS zone, configuration variable $masterC or $slaveC (module V00hostconf) will be applied to generate the zone entry in named.conf, and $zoneC will be applied to populate the zone file.  

The "-i" switch can be used to add the reverse DNS entry for <ip_address>.  This is not needed for "name-based" virtual hosts.  

This command should only be used on systems running a local DNS server, or distributed systems where $DNSs (module V00hostconf) points to a list of remote DNS servers.  If $DNSAWARE (module V00hostconf) is enabled, it is invoked internally by command "vhost --addhost".  Although not meant to be a general purpose DNS command, it is often handy for routine DNS admin tasks.  

Note that it is usually not necessary to explicitly add "www" as a DNS entry.  For example, when adding the DNS record for "virtual.com", the default $zoneC configuration will automatically add entries "www.virtual.com", "ftp.virtual.com", and "mail.virtual.com" under DNS zone "virtual.com".  

# vhost --deldns host_name [ip_address] [-q] [-f]

Delete DNS record for <host_name> and <ip_address>.  If <ip_address> is not specified, all records related to <host_name> will be deleted.  

vHost will automatically figure out whether the DNS zone of <host_name> is empty and needs to be deleted.  

If <ip_address> is specified, its reverse DNS entry, if exists, will also be deleted.  

# vhost --addhost host_name owner_name [ip_address] [-q] [-f]

Add <host_name> as a virtual host under owner <owner_name>.  If <owner_name> exists, vHost will prompt for confirmation;  otherwise it will prompt for a password and <owner_name> will be created as a user.  This is probably the most important vHost command.  

If <ip_address> is not specified, vHost will pick an IP address according to $IPADD (module V00hostconf).  If $IPs (module V00hostconf) has one or more IP addresses listed and <ip_address> is specified out of range, vHost will generate error message "not allowed to access ip address" and abort.  This is to prevent wrong IP addresses (typo etc.) from being activated and potentially disrupting the system's network services.  It is rarely necessary to manually specify <ip_address> on a properly configured system.  

If <host_name> is an existing virtual host and <owner_name> is the host owner, and the "-f" switch is specified, vHost will re-add the host.  This feature can be useful for repairing a virtual host with missing or damaged components and configurations.  It is used by command "vhost --uphost" to update existing hosts.  Caution needs to be taken though, since vHost will restore things to defaults.  

If $DNSAWARE (module V00hostconf) is enabled, vHost will automatically configure DNS by invoking command "vhost --adddns" internally, in which case two DNS switches, "-z" and "-i", can also be specified.  Otherwise they will simply be ignored.  ($DNSAWARE is disabled by default because it requires correct DNS-related settings in module V00hostconf.)  

$HOSTADD (module V00hostconf) determines who can add.  

Note that it is not necessary to add "www" as a separate virtual host.  For example, when adding "virtual.com" as a virtual host, the DNS module (V00hostconf) and Apache module (V10apache) are configured so that "www.virtual.com" will be automatically functional.  (This is also true for "ftp.virtual.com" and "mail.virtual.com".  "ftp.virtual.com" can be used as the hostname for FTP, while "mail.virtual.com" can be used as the hostname for both POP3/incoming and SMTP/outgoing servers.)  

# vhost --delhost host_name [-q] [-f [-d]]

Delete virtual host <host_name>.  If the "-d" switch is not specified (or "n" is entered at the prompt), vHost simply deactivates the virtual host and keeps all data.  This is useful for temporarily disabling a virtual host, or changing the host owner, IP address, or associated profile.  If the "-d" switch is present, all host data, including virtual users and associated host aliases, will be permanently removed from the system.  

# vhost --addhali host_name host_alias [-q]

Add <host_alias> as an alias to <host_name>.  Among other things, all HTTP requests to <host_alias> will be redirected to <host_name>, and all emails addressed to users at <host_alias> will be redirected to the same users at <host_name>.  

# vhost --delhali host_alias [-q]

Delete host alias <host_alias>.  

# vhost --adduser host_name user_name [full_name] [-f]

Add virtual user <user_name> on host <host_name>.  Standard shell command quotation can be used if <full_name> contains space.  Assuming relevant modules are enabled, virtual users have all essential Unix-like features such as home directory, mail spool, .forward/.procmailrc support, FTP access, POP3 and web-based mail, public web space, etc.  

If <user_name> is an existing virtual user on <host_name>, and the "-f" switch is specified, vHost will re-add the user.  This feature can be useful for repairing a broken virtual user account.  

A real system user called "alternative login" is created for every virtual user in order for some of the virtual services to function properly.  An alternative login is essentially a link between the virtual user and the system.  

A primary example is virtual FTP.  Unlike the HTTP protocol which supports name-based virtual hosts, the FTP protocol only identify hosts by their IP addresses.  For FTP access, virtual users on name-based virtual hosts must use their alternative logins.  However, vHost's web-based FTP (phpWebFTP) eliminates this restriction.  Even though it still uses alternative logins under the hood, web-based FTP only requires virtual users to log in at their respective virtual host's website with virtual user names.  

Another example is virtual POP3.  vHost comes with vpop3d, a POP3 daemon which accepts logins in the form of "user@virtual.com".  However, if a system is configured to use a POP3 daemon other than vpop3d (i.e., module V25pop3d is not enabled), virtual users must use their alternative logins for POP3 access.  Again, vHost's web-based mail (OpenWebmail or SquirrelMail) does not have this restriction and only requires virtual users to log in at their respective virtual host's website with virtual user names.  

It is important to note that all alternative logins (therefore virtual users) on a virtual host share the same numeric user ID with the host owner.  The main reason is so that the host owner has full control over all virtual users' data, and all data are accounted for under the host owner in terms of disc space and quota control.  

# vhost --deluser host_name user_name [-f [-d]]

Delete virtual user <user_name> on host <host_name>.  If the "-d" switch is not specified (or "n" is entered at the prompt), vHost will keep the user's data.  

# vhost --adduali host_name user_alias|catch-all@ destinations

Add <user_alias> as an alias (redirect) on <host_name>.  This is an email-only feature.  All emails addressed to <user_alias> at <host_name> will be redirected to <destinations>.  If "catch-all@" is specified instead of <user_alias>, all emails addressed to non-existing users at <host_name> that would otherwise bounce will be redirected to <destinations>.  When specifying multiple destinations, separate them with white space.  

vHost does not check the validity of a destination.  In general a destination should be one of the following: 1. a standard email address in the form of "user@domain.com";  2. a local address ("local" relative to <host_name>) in the form of "user";  3. an executable pipe in the form of "| /bin/filter --options";  4. an include file containing any of these four (including another include file) in the form of ":include:/etc/mailing".  

If a local user ("local" relative to <host_name>) is specified as a destination, there are differences between the full email address ("user@virtual.com")  and the local address ("user" only, without the "virtual.com" part).  If the full address is specified, emails (already redirected from <user_alias>) will be routed externally and go through all checks and filters of the mail system before reaching the user's mail spool.  If the local address is specified, emails will be internally and directly written to the user's mail spool.  

User aliases take precedence over existing users.  If an alias is added while the user with the same name already exists on the virtual host, vHost will issue a warning, and the existing user will no longer receive emails.  However, an alias can specify itself as a destination, in which case the user with the same name will get a copy of all redirected emails.  

The <destinations> part is accumulative, meaning that one destination can be specified many times in one or more commands, and vHost will only pick up new additions from a command and ignore duplicates.  

This command can be used to create a simple mailing list either directly within the command or with the ":include:" format.  

Command example:

vhost --adduali virtual.com info info joe@domain.com '| /bin/filer' ':include:/etc/mailing'

# vhost --deluali host_name user_alias|catch-all@ [destinations]

Delete specified <destinations> for <user_alias> on <host_name>.  If no destination is specified, delete the entire <user_alias>.  

# vhost --passwd [host_name] user_name

Set password for <user_name> on <host_name>.  If <host_name> is not specified, it defaults to the main host.  Note that a host owner is a user on the main host as well as a virtual user on the virtual host.  

# vhost --access [host_name] [user_name] 2|1|0

Set access level for <user_name> on <host_name>.  If <host_name> is not specified, it defaults to the main host.  If <user_name> is not specified, it sets access level for all users on <host_name>, except the host owner.  Note that a host owner is a user on the main host as well as a virtual user on the virtual host.  

Level 2 (shell) access can only be set for host owners and other users on the main host.  Level 0 access effectively disables a user.  

Initial/default access level is defined by $ACCESS (module V00hostconf).  

# vhost --qhost host_name mailbox_size(K/M/G)|. #user|. #uali|.

Set host quota values for <host_name>, including mailbox size for each virtual user, number of virtual users, and number of user aliases.  A value "0" means unlimited.  If "." is specified in place of a value, the original value will remain unchanged.  

Initial/default host quota values are defined by $QHOST (module V00hostconf).  

Command example:

vhost --qhost virtual.com 100M 100 100

# vhost --quser owner_name disk_space(K/M/G)|. #host|. #hali|.

Set owner quota values for <owner_name>, including total disk space size, number of virtual hosts, and number of host aliases.  A value "0" means unlimited.  If "." is specified in place of a value, the original value will remain unchanged.  

Initial/default owner quota values are defined by $QUSER (module V00hostconf).  

Command example:

vhost --quser owner 10.0G 10 10

# vhost --lshost [host_name|owner_name] [-s|-r[n]] [-l] [-a] [-f]

List virtual hosts.  If no <host_name> or <owner_name> is specified, it will list virtual hosts accessible by the user who runs the command.  If <host_name> is specified, it will list that host as a single entry.  If <owner_name> is specified, it will list virtual hosts accessible by <owner_name> as a virtual host owner or virtual root user.  

The "-l" switch lists each host's IP address and associated profile as additional information.  The "-a" switch lists all hosts, including deleted hosts whose data are not removed from the system (see command "vhost --delhost").  A deleted host will have "-" appended to its host name on the list.  

The disk usage information of each host is collected using system command "du", which is resource intensive.  For speed improvement, especially on systems with a large number of virtual hosts, enable $DUCACHE (module V00hostconf).  The "-f" switch displays real-time disk usage info regardless of $DUCACHE, and updates the cache at the same time.  

# vhost --lsuser [host_name|owner_name] [-s|-r[n]]

List users, including virtual users, virtual host owners, and virtual root users.  If no <host_name> or <owner_name> is specified, it will list virtual host owners and virtual root users accessible by the user who runs the command.  If <host_name> is specified, it will list virtual users on that host.  If <owner_name> is specified, it will list virtual host owners and virtual root users accessible by <owner_name>.  

Virtual host owners and virtual root users establish their access and security relations via associations of profiles (see Chapter 5. Profiles, Modules, and Virtual Services).  

# vhost --cphost [host_name|owner_name] destination_ip [-f [-d]]

Copy virtual hosts to a remote system specified by <destination_ip>.  If no <host_name> or <owner_name> is specified, it will copy virtual hosts accessible by the user who runs the command.  If <host_name> is specified, it will copy that host only.  If <owner_name> is specified, it will copy virtual hosts accessible by <owner_name> as a virtual host owner or virtual root user.  

In order for the "-f" switch to work, password-less login needs to be set up for root at destination.  An "undocumented" switch "-q" can be specified to show the entire copying process without actually doing the copying.  

Internally, vHost uses rsync for data transferring.  The "-d" switch deletes extra files at destination that don't exist at source, with rsync's "--delete" option.  

For testing purpose, a system's own IP address can be specified as <destination_ip>.  

This command will have problems when copying virtual hosts between systems with different $dotChar or $unameLen settings (module V00hostconf).  For example, if the original system has $dotChar and $unameLen set to "." and "32", but the destination system does not support "." in usernames or has shorter username length limit, alternative logins will not be duplicated at the destination.  To fix this, first make sure $dotChar and $unameLen in all profiles (which should have already been copied over from the original system) are modified to reflect the correct settings at the destination, and then run the following script (as root) to automatically re-create alternative logins on the destination system (which will not be the same as the ones on the original system).  

for h in `vhost --lshost | sed -n '1d;/^#/q;p' | awk '{print $8}'`; do
   if [ -c /etc/vdata/vusers.$h ]; then continue; fi
   echo "`sed '1q' /etc/vdata/vusers.$h`" > /etc/vdata/vusers.$h
   for u in `vhost --lsuser $h | sed -n '1,2d;/^#/q;p' | awk '{print $1}'`; do
      echo vhost --adduser $h $u -f
      vhost --adduser $h $u -f
      vhost --modpass `vhost --getvalue $h $u '$VUSR{$U};'` . "`vhost --getvalue $h $u '$VSPW{$U};'`"
   done
done

# vhost --uphost [host_name|owner_name] [-q] [-f]

Update virtual hosts.  If no <host_name> or <owner_name> is specified, it will update virtual hosts accessible by the user who runs the command.  If <host_name> is specified, it will update that host only.  If <owner_name> is specified, it will update virtual hosts accessible by <owner_name> as a virtual host owner or virtual root user.  

This command is essentially a wrapper for the "vhost --addhost" command with the "-f" switch, which re-adds hosts to the system.  It can be useful for repairing virtual hosts with missing or damaged components and configurations, or batch update third party packages (e.g. SquirrelMail) or modified configuration variables such as $apacheC (module V10apache).  Caution needs to be taken though, since the update will overwrite host customizations.  

To skip updating a particular host's configuration in conf files such as httpd.conf, locate the host's configuration section, and comment out the "# keep this line - by vhost" part (put another "#" in front of the line).  To skip updating a particular host entirely, put a file named ".no-update" under the host's root directory, and vHost will not touch that host.  

This command may automatically change a virtual host's IP address to reflect the latest system settings.  If this is undesired (especially in the case of manually specified IP address with command "vhost --addhost"), either put the IP address in $IPs (module V00hostconf) so that vHost recognizes it, or disable $UPDATEIP (module V00hostconf).  

# vhost --addmydb host_name mydb_name [-f]

Add MySQL database <mydb_name> on <host_name>.  The actual name of the database will have <host_name> added as a prefix (with "." replaced by "_"), if the <host_name> string does not appear in <mydb_name>.  This command is added by module V40mysql.  

The MySQL database username/password will be the same as the host owner's username/password. If the host owner already exists before module V40mysql is installed/activated, password will be blank.  It can be synchronized with command "vhost --passwd".  

MySQL database files are stored in /var/mysql under a virtual host's root directory.  

# vhost --delmydb host_name mydb_name [-f [-d]]

Delete MySQL database <mydb_name> on <host_name>.  The actual name of the database will have <host_name> added as a prefix (with "." replaced by "_"), if the <host_name> string does not appear in <mydb_name>.  This command is added by module V40mysql.  

If the "-d" switch is not specified (or "n" is entered at the prompt), vHost will delete the database but keep the data stored in /var/mysql under a virtual host's root directory.  

# vhost --hostlog host_name [log_name|-q]

View log files on <host_name>.  The "-q" switch simply lists available log files.  

Log files are located in /var/log under a virtual host's root directory.  

# vhost --cmdlog [log_file]

View command log.  The default command log is defined by $CMDLOG (module V00hostconf).  An alternative log file can be specified with <log_file>.  

# vhost --reload [-delay_time(Sec)] [-f]

Reload virtual services.  The "-f" switch forces reloading all services, and only works for the root user.  For others, reload will only happen if there are pending reloads due to the use of the "-q" switch in previous commands.  Otherwise it does nothing.  

A <delay_time> number can be specified for reload to happen in the future, in which case the command will generate a fork and return immediately.  

3.9 Undocumented Commands

# vhost --rotatelog [host_name] [-z] [-#backlog]

Rotate log files on <host_name>.  If <host_name> is not specified, rotate log files on all hosts.  A <backlog> number can be specified as the number of old log files to keep.  The "-z" switch compresses old log files with gzip.  vHost automatically converts old log files to plain or compressed format depending on the absence/presence of the "-z" switch.  

This command is used by vHost to setup the default root cron job which rotates log files on a weekly basis, among other things.  It can only be run by root.  Manually running the command is discouraged and rarely necessary, as each run will rotate out the oldest log files which can not be recovered.  

Log files are located in /var/log under a virtual host's root directory.  To skip rotating a particular log file on a virtual host, put the log name in a file named ".no-rotate" under /var/log, and vHost will not touch it.  

# vhost --getvalue [host_name [user_name]] eval_script

This command is invoked by vHost internally to get certain values.  Optional <host_name> and <user_name> can be specified if <eval_script> requires it, or to make sure the command is run under the profile associated with <host_name>.  Other than display the result of a pre-defined <eval_script>, this command does not actually do anything.  

# vhost --getdns host_name dns_variable

This is essentially a specialized "vhost --getvalue" command.  It is called internally by commands "vhost --adddns" and "vhost --deldns" on distributed systems in order to get configuration values from the DNS master server, which is defined as the first entry in $DNSs (module V00hostconf).  <dns_variable> can be one of the following: @dnsCf, @revZf, $dnsRt, @zoneCf.  

# vhost --modpass user_name shell_bin|. pass_hash|.

This command is invoked by vHost internally to modify an alternative login's shell and password hash.  If "." is specified, the original shell or password hash will remain unchanged.  

# vhost --vdeliver user_name host_name

Deliver an email message to <user_name> at <host_name>.  This command is added by module V20postfix/V20sendmail and invoked by vHost internally for virtual mail delivery.  

# vhost --poprelay [ip_address [time_stamp]]

Allow "pop relay" ("POP before SMTP") by adding a new or modifying an existing <ip_address> and <time_stamp> entry in /etc/poprelay.  This command is added by module V25pop3d and invoked by vpop3d (without the time_stamp part) to register POP3 authenticated IP addresses for mail relaying.  The specified entry is first added or modified, and then the list is refreshed to flush out old entries.  

If <ip_address> is not specified, simply refresh /etc/poprelay.  If <time_stamp> is not specified, the current Unix epoch time will be used.  If <time_stamp> is in the past and outside the time window defined by $popTimer (module V25pop3d), the entry will be modified and then immediately flushed out, if it's on the list.  

This command can be run manually by root to add or delete an <ip_address> and <time_stamp> entry in /etc/poprelay.  To delete an entry, use a <time_stamp> value in the distant past, for example 1.  To permanently add an entry, use a <time_stamp> value in the distant future, for example 9999999999 (10^10 - 1).  

To disallow pop relay (but still allow POP3 login) from a particular IP address or a range of IP addresses, manually put the IP address (e.g. "192.168.1.7") or the address block (e.g. "192.168.1.1/24") in /etc/poprelax, one entry per line.  This will prevent the address or address block from being registered in /etc/poprelay in the future, as if <time_stamp> is always set to 1 for matching addresses.  If a matching address (e.g. "192.168.1.7") is already in /etc/poprelay, it will be flushed out by the next "vhost --poprelay 192.168.1.7" command, or by other "vhost --poprelay" commands when the relay time window defined by $popTimer passes.  

Obviously, one way to disable pop relay is to put "0.0.0.0/0" in /etc/poprelax, but a more efficient way is to set $popRelay to 0 (module V25pop3d).  

# vhost --netpulse [pulse_rate ip_address [...]]

This is a future command which will be functional in the next release.  Should only be run on distributed systems.  It will start and sustain network pulse on a system and enable the DNS fail-over feature.  

# vhost --uninstall

Uninstall vHost.  

# vhost --install [-f|-d]

Install vHost.  This command must be run under the unzipped vHost source directory.  The "-f" switch bypasses version checking and forces a complete install instead of an upgrade.  

# vhost --version|-v

Display version and copyright notice.  

# vhost --support

Display supported OSes.  

# vhost --require

Display required system files and commands.  

# vhost --history

Display change history.  

# vhost -q

Do nothing.  Actually, every time a non performance-critical command runs, vHost and its modules check their own configurations and if necessary, reconfigure themselves.  This is true when running vHost without any parameters or switches.  Sometimes it might be convenient to use the "-q" switch to suppress the usage info page.  

4. Data and Directory Structure

4.1 Files and Directories

Two index files, /etc/vhosts and /etc/vusers, list all virtual hosts, virtual host owners, and virtual root users on a system.  Actual host and user data are stored under directory /vhost (or the equivalent directory defined by $VHOME in module V00hostconf).  Directory /etc/vdata contains user password and host profile information.  

All virtual host owners and virtual root users created by vHost will have their home directories placed under /vhost/home.  If a host is added to an existing user on the system, the user's home directory will be moved to /vhost/home.  Virtual hosts' root directories reside in their respective owners' home directories, and also symlinked under /vhost.  

Each virtual host has a directory tree that closely follows Unix conventions.  For example, /var/www is the web space, /var/mysql stores databases (assuming relevant modules such as V10apche, V40mysql are enabled), /var/mail is the virtual user mail spool, while /home contains virtual user home directories.  

Following is a list of system files and directories that are created or affected by vHost.  Note that this list assumes all modules are enabled with default settings, and exact names/locations of the files/directories are system dependent.  

/etc/passwd
/etc/shadow
/etc/aliases
/etc/group
/etc/shells
/etc/vhosts
/etc/vusers
/etc/vdeliver
/etc/poprelax
/etc/poprelay
/etc/poprelay.db
/etc/netpulse
/etc/vhost.d/
/etc/vdata/
/etc/vmail/
/etc/named.conf
/etc/rc.d/rc.local
/etc/sysconfig/network-scripts/ifcfg-*:*
/etc/httpd/conf/httpd.conf
/etc/ftpaccess
/etc/proftpd.conf
/etc/mail/sendmail.cf
/etc/mail/sendmail.cV
/etc/mail/access
/etc/mail/access.db
/etc/postfix/main.cf
/etc/postfix/master.cf
/etc/postfix/postfix.cV
/etc/postfix/postfix.cV.db
/etc/inetd.conf
/etc/xinetd.d/ipop3
/etc/xinetd.d/vpop3d
/var/named/
/var/lib/mysql/
/var/log/messages
/var/spool/cron/root
/var/spool/mail/
/var/spool/vmail/
/var/www/html/admin/
/var/www/html/webmail/
/vhost/
/vhost/home/
/usr/sbin/vhost
/usr/sbin/vhost.pl
/usr/local/vhost/
/tmp/.vhost/

4.2 Special Groups and Users

Two user groups, group vhost with id 1999, and group vuser with id 2000, are created by vHost.  These two groups play an important role in permission and access control of the /vhost directory tree.  

All newly created virtual host owners, virtual host users, and virtual root users are assigned to group vuser, while virtual service users such as apache, mysql are assigned to group vhost.  $RUSER (module V00hostconf) which is automatically created by vHost, also belongs to group vhost.  Group vhost is considered a privileged group because its members have access to the entire /vhost directory tree.  Caution needs to be taken when adding a user to this group.  

5. Profiles, Modules, and Virtual Services

5.1 Introduction

As introduced in Chapter 3. vHost Commands, profiles and modules are important aspects of vHost functionality.  

The main vHost script, or the core module, /usr/sbin/vhost.pl, takes care of basic but essential core operations of vHost;  while service related modules, such as the Apache module V10apche, handle virtualizations of specific services.  This modular architecture allows arbitrary services and features to be added and expanded with ease.  

Modules reside in profile directories.  Different profiles may (or may not) contain different sets of modules, or modules with different configurations.  Everything in vHost, including commands, hosts, owners, vroots, are associated with certain profiles.  These associations not only offer great configurability and flexibility, but also naturally give rise to access and security relations among commands, hosts, owners, and vroots.  

5.2 Profile Essentials

The default profile is /etc/vhost.d, which is automatically associated with root.  New profiles can be created by making copies or symlinks of existing profiles, or with command "vhost --addvroot", which associates a profile with a vroot.  A host and its owner are associated with a profile via command "vhost --addhost".  

A vroot has one or more associated profiles, and has access to owners and hosts associated with those profiles.  An owner has one or more associated profiles, and only has access to himself and hosts he owns.  A host has one associated profile.  A profile can have multiple associated vroots, owners, and hosts.  

A command has an associated profile at run time, where the core module /usr/sbin/vhost.pl looks for service modules.  The profile can be specified with the "-p" option, defined by environment variable VHOST_PROFILE, or derived from host/owner specified at the command line or the user who's running the command.  The logic steps behind command and profile association are detailed in 3.2 Command and Profile.  

5.3 Module Essentials

vHost relies on modules to provide virtual services.  It comes with a set of default modules which are explained in details below.  These default modules can be modified, or new modules can be created, in order to add and expand services and features in vHost.  

Module file names must be in the form of "Vxx*", where "xx" is a two digit decimal number.  When a vHost command runs, modules in the associated profile directory are executed in alphanumeric order of their file names.  File names not in the form of "Vxx*" are ignored.  To disable a module, simply rename it to something other than "Vxx*", although it is recommended to rename a disabled module to "Xxx*".  vHost recognizes file names in the form of "Xxx*" in a profile directory as disabled modules, and carries out special operations on them when upgrading, such as retaining values of configuration variables.  

There are dependencies among modules.  For example the OpenWebmail module V30openwebmail depends on the Apache module V10apache.  It is important to make a module's "xx" number larger than the ones it depends on, so that it gets executed later in the dependency chain.  

Each module contains a "configuration" section, an "initialization" section, various command sections, and a "finalization" section.  All these sections are optional.  When executing modules, vHost firstly executes all available configuration sections from the first module to the last, and then all available initialization sections, followed by the command sections corresponding to a particular command, and finally all finalization sections.  

The configuration section of a module usually contains global configuration variables whose values can be adjusted in order to modify vHost's functionality or make vHost work properly on a particular system.  All default modules come with detailed comments documenting these configuration variables.  

For upgrade compatibility, configuration variables with single-line values (including blank values) should use single or double quotes, while multiple-line values should use the Perl here-doc format with the end marker in single or double quotes.  Do not comment out a variable, instead leave it blank with an empty string ("").  The reason for these is so that existing values are retained through the upgrade process instead of reverted back to defaults.  

Configuration variables that specify directories should not have the trailing slash.  A "root" (e.g. $docRoot, $owRoot) specifies the full path of a directory and requires the leading slash.  A "dir" (e.g. $guiDir, $wmDir) specifies the name of a directory and should not contain any slash at all.  

Unlike standard Perl modules, vHost modules are script files executed by the main script with the Perl "do" function.   As one result, all modules share the same namespace with the core module.  Global variables defined in one module are visible in all modules.  As another result, errors in one module will disrupt all vHost commands using that module.  When developing a module, it is recommended to put the module in a non-production profile and use the profile for testing purpose with the command-line "-p" switch.  

The default modules handle virtualizations of common services.  However they do not install service packages.  In order for virtualizations to work, service packages such as Apache, OpenWebmail must be already installed and working properly on the system.  

5.4 Modules and Virtual Services

# V00hostconf

This is the module for general system and DNS configurations.  It is the only required module in a profile directory, without which vHost will not run.  It is also the first module that gets executed, regardless of the naming order of other modules.  

Some of the configuration variables in this module are system dependent, among them $dotChar and $unameLen are of particular importance.  Although to some extent vHost attempts to detect the correct settings of these variables during installation,  it is important to go through the entire module file to make sure the variables reflect the proper settings of the system.  

IF $DNSs is blank, commands "vhost --addnds" and "vhost --deldns" will treat the system as a DNS server and add/delete DNS records locally.  The master/slave status of the DNS server depends on the presence/absence of $masterC/$slaveC.  In case both are present, the master status is assumed.  

If $DNSs is not blank, vHost will add/delete DNS records remotely on systems listed in $DNSs.  In that case password-less login needs to be configured for $RUSER on all systems.  The master/slave status of a system, in case both $masterC and $slaveC are present, depends on whether the system's main hostname or IP address is listed as the first entry in $DNSs, once a vHost DNS command reaches the system.  For more details regarding $DNSs, $RUSER, and distributed systems in general, see Chapter 8. Distributed Systems (Clustering).  

IF $DNSAWARE is enabled, vHost will automatically add/delete DNS records when adding/deleting virtual hosts and host aliases.  

Although the default contents of $masterC, $slaveC, and $zoneC are sensible for most cases, they should be modified to accommodate specific needs.  Re-adding an existing DNS record will have it updated with the latest contents of these variables.  

# V01network

This module handles automatic IP aliasing.  It's used for IP-based virtual hosting systems with a pool of IP addresses that need to be dynamically aliased and de-aliased by vHost, in which case the IP address pool should be defined in $IPs (module V00hostconf).  For other systems, including systems with single IP or multiple static IP aliases, this module does nothing, unless a new IP address is explicitly specified in command "vhost --addhost".  

$nicCf can be set to any shell script file (even an empty but executable file) on systems without the "network-scripts" setup, as long as the script file gets executed at the system startup.  

It is recommended to keep this module enabled even if IP aliasing is not needed.  It provides useful network information for the core module and other modules.  

# V10apache

Apache virtualization module.  Should automatically work with default Apache installations on most systems.  

$guiDir has the default value "admin", which can be changed to e.g. "vadmin", if it's causing conflict on a system.  

$docRoot and $webUser will be automatically detected by vHost if they are left blank.  However, for improved performance, it is recommended to fill in the known values.  

$apacheC and $apacheA have sensible default contents.  However they should be modified to accommodate specific needs.  

Command "vhost --uphost" can be used to update virtual hosts (that are associated with the profiles containing this module) when changes are made to configuration variables such as $guiDir, $apacheC, $apacheA.  

# V15proftpd

ProFTPD virtualization module.  See 10.* Virtual FTP for more information.  

# V15wu-ftpd

WU-FTPD virtualization module.  See 10.* Virtual FTP for more information.  

# V20postfix

Postfix virtualization module.  Should automatically work with default Postfix installations on most systems.  

# V20sendmail

Sendmail virtualization module.  Should automatically work with default Sendmail installations on most systems.  

# V25pop3d

This module enables vpop3d for virtual POP3, and provides the "pop relay" feature.  

$pop3d can be set to blank so that vpop3d will be added as a separate inetd/xinetd service independent of the default POP3 service, in which case there must not be any other inetd/xinetd or stand-alone pop3 daemon running on the system.  

In case of dovecot, for example, edit /etc/dovecot.conf and add (or modify) line "protocols = imap imaps" to disable the stand-alone pop3 daemon.  

# V30openwebmail

OpenWebmail virtualization module.  OpenWebmail needs to be installed and working on the main host.  

Although not "officially" supported, both the OpenWebmail module and the SquirrelMail module can be enabled (manually) at the same time without any problem.  However, "http://virtual.com/webmail" will point to SquirelMail instead of OpenWebmail, because the SquirrelMail module gets executed later and its index.php file under "/webmail" overwrites OpenWebmail's index.php (which is a simple redirect to "http://virtual.com/cgi-bin/openwebmail/openwebmail.pl").  To reverse this situation, either delete index.php in SquirrelMail's source, or make simple change to this module's finalization section to re-write index.php.  

# V30squirrelmail

SquirrelMail virtualization module.  SquirrelMail needs to be installed on the main host.  Some systems come with vendor customized SquirrelMail packages, often with settings configured for single host purposes.  vHost will try to work with these packages.  However, to avoid potential problems, it is recommended to use the standard package distributed by the SquirrelMail team.  Simply download the standard package, unzip, and point $smRoot to the unzipped directory.  

Although not "officially" supported, both the SquirrelMail module and the OpenWebmail module can be enabled (manually) at the same time without any problem.  

# V35awstats

AWStats virtualization module.  AWStats needs to be installed on the main host.  Simply download AWStats, unzip, and point $asCgiRoot and $asIconRoot to the cgi-bin and icon directories.  

Although not "officially" supported, both the AWStats module and the Webalizer module can be enabled (manually) at the same time without any problem.  

# V35webalizer

Webalizer virtualization module.  Webalizer needs to be installed on the main host.  

Although not "officially" supported, both the Webalizer module and the AWStats module can be enabled (manually) at the same time without any problem.  

# V40mysql

MySQL virtualization module.  It's disabled by default.  To enable the module, simply change its file name from X40mysql to V40mysql.  Once enabled, this module will add two new commands: "vhost --addmydb" and "vhost --delmydb".  The MySQL daemon may need a restart if new databases are being created for the first time.  

$mysqlRoot and $mysqlUser will be automatically detected by vHost if they are left blank.  However, for improved performance, it is recommended to fill in the known values.  

# Vxxsample

Module template.  Provides a skeleton and start point for new module development.  

6. Security and Login Levels

7. Quota Control

8. Distributed Setup (Clustering)

8.1 Introduction

In the real world, a hosting and DNS all-in-one system is quite common for casual hosting purposes.  However, for a production environment, it is recommended to have at least two DNS servers running on separate systems.  vHost can be configured to accommodate this distributed hosting/DNS setup.  (One reason for this is mail delivery.  If a domain's hosting system goes down but DNS queries still return its MX record, mail delivery to the domain will simply be delayed and retried in a typical period of five days.  However if a domain's DNS record can not be found because none of its name servers is available, email messages will be immediately bounced back to the sender marked as undeliverable.)  

In some cases it's a good idea to separate performance-sensitive services such as web, database, web-based email etc. from POP3 and SMTP services, especially for virtual hosts with high mail traffic volumes.  vHost can be configured for this purpose.  

For systems running a large number of virtual hosts, resource consumption will inevitably become an issue at some point.  Instead of randomly split virtual hosts onto separate boxes, a virtual hosting cluster can be configured in vHost for load balancing, using the round robin DNS feature.  A cluster also offers benefits such as redundancy and high availability.  

8.2 Configuration

In order for a distributed system to work, following are the requirements:  1. The latest version of vHost is installed on all participating systems ("nodes");  2. each node has a public IP address;  3. All hosting nodes, but not necessary DNS nodes, have access to a shared network file system, where the /vhost directory (or the equivalent directory defined by $VHOME in module V00hostconf) resides.  

The third requirement can be fulfilled using either a turn-key NAS solution, or a customized setup with NFS or distributed file systems such as DRDB, PVFS.  This topic is beyond the scope of this discussion, for which there are numerous how-to documents available.  vHost will still function without a shared /vhost directory, but obviously data will be scattered across hosting nodes.  Nevertheless it can be useful for testing purpose without first implementing the network file system.  

To start distributed configuration on a node, change $HOSTs and $DNSs (module V00hostconf) to list all nodes, including the node itself, and run command "vhost" so that vHost will check the settings and configure itself.  You should not see any error message.  Repeat on all nodes.  

Once $HOSTs and $DNSs are in place, configure $RUSER and $REXEC (module V00hostconf) to allow password-less login between nodes.  The general concept is that $RUSER on a hosting node should be able to run remote shell commands on all hosting nodes (including itself) and DNS nodes, while $RUSER on a DNS node should be able to run remote shell commands on all DNS nodes (including itself) but not necessary hosting nodes.  From the receiving point of view, $RUSER on a hosting node should be able to receive remote shell commands from all hosting nodes (including itself) but no necessary DNS nodes, while $RUSER on a DNS node should be able to receive remote shell commands from all DNS nodes (including itself) and hosting nodes.  

An easy way to accomplish this is to run rshd on all nodes.  vHost automatically works with rshd.  This is acceptable if firewalls are properly configured to only allow rsh connections between nodes, and all rsh traffic is secured between nodes without going through a third party.  

Otherwise, ssh should be used instead, in which case change $REXEC to "ssh -l $RUSER".  It may seem a lot of work to set up password-less ssh login on all systems involved, but a simple shell script like the following can automate things in one step.  Simply Run the script once on a DNS node.  

su - ruser
rm -rf .ssh
ssh-keygen -t rsa  #(press enter for all prompts)
cp .ssh/id_rsa.pub .ssh/authorized_keys
for h in `cat .rhosts`; do ssh $h hostname; done  #(answer yes to all prompts and then Ctrl-C to abort)
su
for h in `cat .rhosts`; do scp -rp .ssh $h:`pwd` && ssh $h chown -R ruser `pwd`/.ssh; done
exit
for h in `cat .rhosts`; do ssh $h 'echo `/usr/sbin/vhost -v` [`hostname`]'; done

Here a $RUSER named "ruser" is assumed.  For multiple profiles with different $RUSER setup, the script needs to be run for every $RUSER.  

The reason to run this on a DNS node is because .rhosts on a DNS node contains both $HOSTs and $DNSs entries, while .rhosts on a hosting node contains only $HOSTs entries.  In reality, however, a hosting box usually also dobules as a DNS box, in which case .rhosts will contain both $HOSTs and $DNSs.  Alternatively, a text file listing all $HOSTs and $DNSs can be used in place of .rhosts in the script, in which case the script can be run on either a DNS node or a hosting node.  

If all nodes share the same /vhost network directory, things will be simpler.  The "scp" step will not be necessary, because the ".ssh" directory resides under /vhost/home/vhost which will appear identical across all nodes.  Simply generate the private/public key pair, the "authorized_keys" file, and populate the "known_hosts" file, and $RUSER will immediately have password-less login among all nodes.  

In the last step, you should not encounter any prompt and should see the vHost version/copyright notice from all nodes.  

Now configure DNS settings on DNS nodes (see module V00hostconf for more details), and enable $DNSAWARE (module V00hostconf) on hosting nodes.  Try adding a virtual host with command "vhost --addhost" on any hosting node, and it should be added on all hosting nodes, with their respective DNS records added on all DNS nodes.  At this point, the cluster is ready.  

A vHost cluster is peer-to-peer, meaning that all nodes are equal.  vHost commands issued on one node will operate on all nodes.  Not all commands are cluster-aware though.  Some of them only run on the node where they are issued.  These include --lshost, --lsuser, --cphost, and --cmdlog.  For testing purpose sometimes it's desirable to force a command to only run on the local node.  This can be done by root, by setting the environment variable VHOST_LOCAL to 1 before running a command.  

(In the next release, there will be an optional "vhost --netpulse" command which should be run at this point.  It will start and sustain network pulse on each node and enable the DNS fail-over feature.)  

For testing purpose, the above procedure can be done on a single system.  Simply list a system's main hostname or IP address as a single entry in both $HOSTs and $DNSs, and it will become a "cluster" consisting of one node.  $RUSER and $REXEC still need to be set up to enable remote shell commands to/from itself.  

To add a new node into an existing cluster, first repeat the above proecedure for the node, and then use command "vhost --cphost" to populate the node with existing virtual hosts, or in case of a DNS-only node, run command "vhost --uphost" on a hosting node to populate the new node with existing DNS records.  

9. WebGUI

10. Misc. Tips, Hacks, and FAQs

10.* Perl RegEx and UTF8 Bug

Some versions of RedHat 8/9 and derived systems have a known bug related to Perl 5.8 regular expression and UTF-8 encoding.  If you get "unexpected EOF" error, invalid $webUser/$docRoot error, empty "--lshost" output, or other anomalies while running vHost commands, try setting environment variable "export LANG=C" (sh style) or "setenv LANG C" (csh style).  To fix this permanently, edit "/etc/sysconfig/i18n" and remove ".UTF-8" from the end of the "LANG=..." line, and reboot the system.  

10.* vHost and SELinux

vHost is SELinux conscious and should work transparently with most applications under SELinux.  However one exception is Apache.  The default Apache policy on most SELinux systems has various problems and does not work well with vHost and may other applications.  For that reason, the Apache policy is disabled during vHost installation ("httpd_disable_trans" set to 1).  If you believe the Apache policy on your system is well-devised, it can be enabled with command "setsebool httpd_disable_trans 0" (run as root).  

Another issue is Postfix.  The Postfix policy on some SELinux systems prevents the Postfix pipe from executing command "vhost --vdeliver", or for that matter, any command at all.  This issue can not be easily fixed without compiling and loading a new policy into the kernel.  Of course, an obvious work-around is to disable SELinux enforcing with command "setenforce 0" (runs as root).  

Extensive SELinux support in vHost will likely be implemented in the future when SELinux becomes more matured for production environments.  

10.* $dotChar, $unameLen

The correct settings of $dotChar and $unameLen (module V00hostconf) are system dependent, and they are crucial for the proper creation and operation of virtual users and their respective alternative logins.  It is important to check these two settings and make sure they work on a particular system.  

Command "vhost --cphost" will have problems when copying virtual hosts between systems with different $dotChar or $unameLen settings.  For more details regarding this issue and a work-around, see command "vhost --cphost".  

10.* About the Main Host

Some systems automatically set up the main hostname in /etc/hosts so that it points to 127.0.0.1, which will be treated by vHost as the main IP address.  While vHost will still work in this scenario, it is obviously not very useful for real-world hosting purposes.  Make sure the real-world main hostname and IP address are properly specified in /etc/hosts.  

It is a good idea to add the main host as a virtual host.  However, vHost treats the main host differently than other virtual hosts.  The major difference is that users on the main host are real users instead of virtual ones.  For that reason, command "vhost --cphost" does not copy the main host from one system to another.  On a virtual hosting system, the main host should only be used for identification purpose, and should not be a production virtual host.  

10.* DNS on an All-in-One Box

Although not recommended, both primary and secondary (master/slave) DNS can be setup on the same box that does virtual hosting.  In order to do this, you will need to have two IP addresses aliased on the system, and register two domain name servers on those two IP addresses (contact your favorite domain name registrar for details).  Your system will appear to the outside world as two distinctive name servers.  You can arbitrarily designate primary/secondary to the two servers registered.  The distinction is only meaningful to the outside world.  

Once that's done, start named on the system.  Enable $DNSAWARE (module V00hostconf), and DNS records will be automatically added/deleted when adding/deleting virtual hosts.  See module V00hostconf and command "vhost --adddns" for more details.  

10.* A Non-root Superuser

It's often desirable not to login as root in order to perform root-level vHost tasks.  A regular user can be set up for that purpose, i.e. a "superuser".  Simply add a user to group vhost, and also as a vroot to all profiles (with command "vhost --addvroot").  Group vhost is reserved for system service users such as apache, mysql so that these services have access to virtual hosts' directories.  Once added to the group, the superuser will be able to get into any virtual host's directory, and have read access to the host's data.  

10.* vhost --lshost Speedup

On a system with a large number of virtual hosts, command "vhost --lshost" will be slow.  Turn on $DUCACHE (module V00hostconf) for significant performance improvement.  See command "vhost --lshost" for more details.  

10.* Virtual FTP

On a name-based virtual hosting system (i.e., all virtual hosts sharing one IP address), virtual FTP is not necessary.  The two default FTP modules, V15proftpd and V15wu-ftpd, can be disabled.  Even on a system with IP-based virtual hosting, vHost can still function without virtual FTP.  Virtual users will just have to use their alternative logins for virtual FTP access.  However it is important to turn on the chroot feature for group vuser in FTP configuration.  In case of ProFTPD or WU-FTPD, chroot for group vuser is automatically configured by the corresponding module, so it's harmless to leave the relevant module enabled.  In other cases, manual configuration is necessary.  

In case of vsftpd, for example, edit /etc/vsftpd/vsftpd.conf and add line "chroot_local_user=YES" to enable chroot.  

For web-based FTP (phpWebFTP), virtual users should always log in at their respective virtual host's website with virtual user names.  

10.* Virtual POP3

Virtual POP3 is done through vpop3d, which is installed by vHost and enabled by module V25pop3d.  Module V25pop3d also provides the "pop relay" ("POP before SMTP") feature by registering IP addresses authenticated through vpop3d (see command "vhost --poprelay" for more details).  However in certain cases vpop3d will hand the POP3 connection to the default POP3 service defined by $pop3d (module V25pop3d), and pop relay will not work.  To make sure vpop3d always handles the POP3 connection, there are two options:  1. add the main host as a virtual host;  or 2. disable the default POP3 service and set $pop3d to blank, so that vpop3d will be added as a separate inetd/xinetd service independent of the default POP3 service, in which case there must not be any other inetd/xinetd or stand-alone pop3 daemon running on the system.  

In case of dovecot, for example, edit /etc/dovecot.conf and add (or modify) line "protocols = imap imaps" to disable the stand-alone pop3 daemon.  

10.* Virtual POP3/Webmail Login

For the following discussion, "joe@virtual.com" will be used as an example, assuming "virtual.com" is a virtual host on the system, and "joe" is a virtual user on "virtual.com".  

For POP3, the user should login at hostname "virtual.com" or "mail.virtual.com" (see command "vhost --addhost" for more details regarding "mail.virtual.com").  Assuming vpop3d handles the POP3 connection as described in the section above:  if virtual.com is an IP-based virtual host (i.e., its IP address resolves back to virtual.com), the POP3 login can be either "joe" or "joe@virtual.com";  if virtual.com is a name-based virtual host (i.e., its IP address resolves back to something else), the POP3 login should be "joe@virtual.com".  In case that vpop3d does not handle the POP3 connection, joe's althernative login must be used.  Generally speaking, "joe@virtual.com" is the safest bet in most cases.  

For web-based mail (OpenWebmail or SquirrelMail), the user should always login as "joe" at "http://virtual.com/webmail".  

10.* Virtual SMTP and SpamAssassin, ClamAV

Virtual SMTP is done through vdeliver, which is installed by vHost and enabled by module V20sendmail/V20postfix.  For the following discussion, "joe@virtual.com" will be used as an example, assuming "virtual.com" is a virtual host on the system, and "joe" is a virtual user on "virtual.com".  Note that a virtual host's owner is also a virtual user on that host, whom we will call "owner".  

In short, an email message sent to "joe@virtual.com" will go through two filters, if they exist: "/etc/procmailrc", and "/vhost/virtual.com/home/joe/.procmailrc" (in that order).  

When a message arrives at the system, it is, of course, first intercepted by sendmail/postfix. The vHost virtual hosting rule set in sendmail/postfix is invoked quite early.  Essentially the only thing sendmail/postfix checks against the message is whether relay is allowed for "virtual.com".  Since "virtual.com" is a virtual host on the system, relay is always allowed in the rule set.  Without further inspection, the message is passed to STDIN of command "vhost --vdeliver", which in turn passes the message to vHost module V20sendmail/V20postfix.  

If procmail is enabled in V20sendmail/V20postfix by $procmail, the message is then passed to STDIN of command "procmail HOME=/vhost/virtual.com/home/joe DEFAULT=/vhost/virtual.com/tmp/.out.32765", with procmail's running userid set to joe's userid (and assuming "32765", as an example, is the process id of command "vhost --vdeliver").  The effect of this command is that procmail first filters the message through "/etc/procmailrc", and then "/vhost/virtual.com/home/joe/.procmailrc", and finally writes the filtered message to ".out.32765".  Upon the completion of the procmail command, vHost (or rather module V20sendmail/V20postfix) records the exit code of procmail, and inspects the existence and size of ".out.32765".  If the file does not exist or has a size of 0, vHost does nothing and exits with the recorded exit code of procmail, and the flow of the message stops.  Otherwise, vHost feeds the entire content of ".out.32765" to vdeliver as STDIN.  

If procmail is disabled in V20sendmail/V20postfix, the above step is skipped and the message is passed directly to vdeliver.

Finally, vdeliver writes the message to joe's mailbox "/vhost/virtual.com/var/mail/joe", and command "vhost--vdeliver" exits with vdeliver's exit code.  In case that "joe@virtual.com" is redirected to various local and remote accounts (either by command "vhost --adduali" or by ".forward" under joe's home directory), for example "joe john mary@virtual.com anne@other.com", vdeliver writes the message directly to "var/mail/joe" and "var/mail/john", and sends the message off to "mary@virtual.com" and "anne@other.com".  

Once the above message flow sequence is established, it becomes clear that special purpose filters such as SpamAssassin, ClamAV need to be set up through procmail.  

For SpamAssassin, a system-wide filter can be set up in "/etc/procmailrc" like this:  

MAILDIR=$HOME/mail

:0fw: spamc.lock
| /usr/bin/spamc

:0:
* ^X-Spam-Status: Yes
INBOX.Spam

The effect of this filter is that if a message is flagged as spam by spamc/spamd, it will be written to "/vhost/virtual.com/home/joe/mail/INBOX.Spam" (notice that $HOME is already set to "/vhost/virtual.com/home/joe" by the procmail command mentioned earlier), and the flow of the message will stop at procmail;  vdeliver will not be invoked at all, so nothing will be written in joe's mailbox.  

One particular behavior of SpamAssassin, however, needs to be noted regarding the above filter.  SpamAssassin has it's own config directories.  Besides system-wide config directories such as "/usr/share/spamassassin" and "/etc/mail/spamassassin", it also reads a per-user config directory ".spamassassin" under a user's home directory.  Since procmail is invoked by "vhost --vdeliver" with joe's userid, spamc/spamd also runs with joe's userid since it is invoked by procmail.  Now, because virtual host users share the same userid with the host owner, spamc/spamd always ends up reading ".spamassassin" under the host owner's home directory, which is "/vhost/home/owner/.spamassassin", while "/vhost/virtual.com/home/joe/.spamassassin" does not have any effect.  

In other words, spam filtering is done at the domain level using owner's ".spamassassin" settings.  If this behavior is undesired, it can be modified to enable filtering at the virtual user level.  There are three alternatives:  

1. Specify the spamd option "-c -x --virtual-config-dir=/vhost/%d/home/%l/.spamassassin" to explicitly set the per-user config directory.  
2. Replace "/usr/bin/spamc" above with "/usr/bin/spamassassin".  The difference is that unlike spamc/spamd, spamassassin (the binary executable) respects the $HOME environment variable set by procmail.  
3. Turn off domain level filtering in "vhost/home/owner/.spamassassin/user_prefs" (with option "whiltelist_to *@virtual.com"), and then set up user level filtering in "/vhost/virtual.com/home/joe/.procmailrc", using the same procmail recipe above, replacing "/usr/bin/spamc" with "/usr/bin/spamassassin".  

For ClamAV, a system-wide filter can be set up in "/etc/procmailrc", following the SpamAssassin filter:  

MAILDIR=$HOME/mail

:0fw: spamc.lock
| /usr/bin/spamc

:0:
* ^X-Spam-Status: Yes
INBOX.Spam

:0fw: clamd.lock
| /usr/bin/proclam INBOX.Virus

:0
* < 1
/dev/null

Here "/usr/bin/proclam" is a simple wrapper script which looks something like this:  

#!/usr/bin/perl

$clamdscan = "/usr/local/bin/clamdscan";
$clamdmail = $ARGV[0];

@stdin = <STDIN>;
open PIPE, "|$clamdscan - --quiet";
print PIPE @stdin;
close PIPE;

if ($? >> 8 == 1)
{
   open FILE, ">>$clamdmail";
   print FILE @stdin;
   close FILE;
} else {
   print @stdin;
}

When clamdscan detects a virus, it returns exit code 1;  the above script checks the code and writes the message to "/vhost/virtual.com/home/joe/mail/INBOX.Virus".  

The last recipe in "/etc/procmailrc" is a work-around to get rid of the empty new line added by procmail after the pipe recipe.  

As a summary, following are the simple steps to set up SpamAssassin, ClamAV filters for virtual hosts:

1. Install SpamAssassin, ClamAV (both in daemon mode)
2. Make sure procmail is enabled in V20sendmail/V20postfix
3. Create and customize /etc/procmailrc based on examples shown above

10.* Mail Forwarder, Autoresponder

vHost supports the traditional Unix ".forward" file.  If the ".forward" file exists under a virtual user's home directory, emails sent to the user will be forwarded to address(es) defined in the file.  

vHost supports the "autoresponder" feature.  If a file named ".autoresponder.msg" exists under a virtual user's home directory, the sender of an email will get the ".autoresponder.msg" message, while the email will be delivered following standard prodecures.  

In addition to autoresponder, vhost also supports the "vacation" feature.  If two files named ".vacation.msg" and  ".vacation.db" exist under a virtual user's home directory, the sender of an email will get the ".vacation.msg" message once, and the email address will be logged in ".vacation.db" so that subsequent emails from the same sender will not trigger a reply again.  The email will be delivered following standard procedures.  Obviously, it's important for the virtual user to delete both files when the vacation is over.  

Note that aliases defined with command "vhost --adduali" takes precedence over ".forward", while ".forward" takes precedence over ".autoresponder.msg" and ".vacation.msg".  

11. vHost API

12. Credits

Jake Fan, author of vHost and this document. This entire project was started as an attempt to create some logic out of the virtual hosting chaos.  

Jacques Gelinas, author of Linuxconf.  Two utilites in Linuxconf - vpop3d and vdeliver, are heavily modified and redistributed in vHost for virtual email handling.  

Tom Zoerner, author of Quota.pm.  vHost uses Quota.pm to implement host owner disk quota.  

Roland Giersig et.al., author of IO-Tty.pm.  vHost uses IO-Tty.pm to communicate with the system command "passwd".  

Numerous users have been providing invaluable feedbacks ever since the beginning of the project.  Please keep up your support for vHost!