How To Set Up Mass Virtualhosting With Apache2 + mod_rewrite + mod_userdir + mod_suexec On CentOS 5.3
How To Set Up Mass Virtualhosting With Apache2 + mod_rewrite + mod_userdir + mod_suexec On CentOS 5.3Version: 1.2 This howto shows one method of doing mass virtualhosting using mod_rewrite to dynamically map a list of directories on your filesystem to virtual hosts. Additionally, by rewriting the incoming URL to the user's home directory we can make use of suEXEC to have Apache execute CGI scripts as the owner of the script. NOTE: this config has not been tested in a production environment.
Before we startUsing Centos 5.3 as the OS platform. For illustration purposes, I'm assuming that www.example.com exists and points to the our web server IP 192.168.1.1. The webroot for example.com is located in /home/vhosts/example.com/public_html.
Apache2Install Apache: yum install httpd (Centos httpd package includes mod_rewrite + mod_userdir + mod_suexec.)
Configure mass virtual hostingvim /etc/httpd/conf/httpd.conf Add the following towards the top somewhere: LoadModule rewrite_module modules/mod_rewrite.so At the bottom of the file add the following: ## get the server name from the Host: header
UseCanonicalName Off
## splittable logs
LogFormat "%{Host}i %h %l %u %t \"%r\" %s %b" vcommon
CustomLog logs/access_log vcommon
RewriteEngine On
## Create a handle to convert upper or mixed-case to lower-case
RewriteMap lowercase int:tolower
##-----------------------------------
## where hostname has www prefix
##-----------------------------------
## Firstly create custom variable that contains the host without the www prefix
RewriteCond %{HTTP_HOST} ^www\.(.*)$
RewriteRule .? - [E=noWWWHost:%1]
## Map the virtualhost to the documentroot
RewriteCond %{REQUEST_URI} !^/~
RewriteCond %{HTTP_HOST} ^www\.
RewriteRule ^/(.*)$ /home/vhosts/${lowercase:%{ENV:noWWWHost}}/public_html/$1
##-----------------------------------
## where hostname *does not* have www prefix
##-----------------------------------
## Map the virtualhost to the documentroot
RewriteCond %{REQUEST_URI} !^/~
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^/(.*)$ /home/vhosts/${lowercase:%{HTTP_HOST}}/public_html/$1
Some things to note about the above config:
Create index.html in the virtual host's public_html: echo "index.html Hello World" > /home/vhosts/example.com/public_html/index.html Start Apache: /etc/init.d/httpd start Now, browsing to http://www.example.com/ should result in 'index.html Hello World' being displayed. If this doesn't happen, check the Apache error log: tail /var/log/httpd/error_log
Executing our CGI scripts using suEXEC + mod_userdirAs this is a shared web hosting platform, with many different users & websites we want to execute CGI scripts as the owner of the website rather than as the webserver process. suEXEC allows us to do this a) statically using virtualhost config or b) dynamically using mod_userdir. Firstly, each website must be owned by a user with the same name as the website's domain name. For example website example.com: useradd -d /home/vhosts/example.com example.com This will create a user example.com whose home directory is /home/vhosts/example.com. All the webfiles for www.example.com will go into /home/vhosts/example.com/public_html. You could either add each user manually to /etc/passwd or set up your host to look up an LDAP directory for account information. Enable mod_userdir: vim /etc/httpd/conf/httpd.conf Ensure the following lines appear somewhere in your config: LoadModule userdir_module modules/mod_userdir.so
<IfModule mod_userdir.c>
UserDir public_html
</IfModule>
Now when we request a page from the webserver using the form http://192.168.1.1/~example.com Apache will look in the home directory for username example.com for the public_html directory. This by itself isn't very useful as we don't want people to have to use the ~/ bit in their URLs. Instead we will silently rewrite the URL from www.example.com to http://192.168.1.1/~example.com behind the scenes. This particular rewrite doesn't need to be done for every page - only for CGI scripts that we want to run under suEXEC. Other pages will get handled by the earlier re-write rules. Edit /etc/httpd/conf/httpd.conf. Below the existing rewrite rules, insert the following: ## Rewrite script to userdir so we can use suEXEC
RewriteCond %{REQUEST_URI} !^/~
RewriteCond %{SCRIPT_FILENAME} /home/vhosts/(.*)/public_html/(.*\.(pl|cgi))
RewriteRule .* /~%1/%2 [PT,L]
<Directory /home/vhosts/*/public_html>
AddHandler cgi-script .pl .cgi
Options +ExecCGI
</Directory>
Reload Apache config: /etc/init.d/httpd reload Create the Perl script test.pl in the virtual host's public_html with the following contents: #!/usr/bin/perl print "Content-type: text/html\n\n"; print "<H1>test.pl Hello World</H1>\n"; Give the script executable permissions & change ownership to the correct user: chmod +x test.pl chown example.com:example.com test.pl Now, browsing to http://www.example.com/test.pl should result in 'test.pl Hello World' being displayed. If this doesn't happen, check the following log files: tail /var/log/httpd/error_log tail /var/log/httpd/suexec.log PHP + PythonExtending suEXEC processing to include PHP & Python (or anything else) is simple. First, make sure php-cli and python packages and their dependencies are installed: yum install php-cli yum install python Create a couple of 'hello world' scripts in your public_html folder as follows: test.py #!/usr/bin/python print "Content-type: text/html\n\n" print "test.py Hello world!" test.php #!/usr/bin/php-cgi <? echo "test.php Hello world!"; ?> Chown the files to be owned by the correct user, and set the executable bit with chmod +x. Note: each script needs to have the interpreter specified on the first line e.g. #!/usr/bin/python. To avoid having to do this with each file, you can do the following: echo ":PHP:E::php::/usr/bin/php-cgi:" > /proc/sys/fs/binfmt_misc/register Now modify Apache config to rewrite requests for files with .php and .py extensions. We also need to add these extensions to the handler for cgi-script /etc/httpd/conf/httpd.conf ## Rewrite script to userdir so we can use suEXEC
RewriteCond %{REQUEST_URI} !^/~
RewriteCond %{SCRIPT_FILENAME} /home/vhosts/(.*)/public_html/(.*\.(pl|cgi|php|py))
RewriteRule .* /~%1/%2 [PT,L]
<Directory /home/vhosts/*/public_html>
AddHandler cgi-script .pl .cgi .php .py
Options +ExecCGI
</Directory>
PHP NOTE: Set cgi.force_redirect = 0 in /etc/php.ini to avoid CGI REDIRECT_STATUS errors Reload Apache config: /etc/init.d/httpd reload Now, browsing to http://www.example.com/test.py or http://www.example.com/test.php should result in 'Hello World' being displayed. If this doesn't happen, check the following log files: tail /var/log/httpd/error_log tail /var/log/httpd/suexec.log CatchallIf you'd like to direct requests for non-existent virtual hosts to one catchall site, make this your last rewrite rule in /etc/httpd/conf/httpd.conf: ## Redirect non-existent virtualhosts
RewriteCond %{REQUEST_URI} !^/~
RewriteCond %{SCRIPT_FILENAME} (/home/vhosts/.*)/public_html/.*
RewriteCond %1 !-d
RewriteRule .? http://www.google.com [R,NS,L]
|
www.seamlessenterprise.com
One number. One voicemail. Seize the lead. Sprint Mobile Integration.
www.seamlessenterprise.com
One Number. One Voicemail.
Make it easier for clients to reach you. Turn your desk phone and mobile phone into one with Sprint Mobile Integration.
www.seamlessenterprise.com
One number. One voicemail. Sprint Mobile Integration.
www.seamlessenterprise.com
One number. one voicemail. Seize the lead with Sprint. Learn more
AT&T Synaptic Compute as a Service. Boost your power on demand.
Trial: IBM Cognos Express Reporting, Analysis & Planning
Learn benefits of Simpana software.
View the Gartner Video
Sprint 4G - The Ultimate Mobile Broadband
Click here
SAP-Business Objects Crystal Reports Server
Complete reporting without hidden costs. Free Trial







Recent comments
18 hours 14 min ago
20 hours 12 min ago
20 hours 30 min ago
1 day 10 hours ago
1 day 16 hours ago
2 days 4 hours ago
2 days 4 hours ago
2 days 8 hours ago
2 days 12 hours ago
2 days 12 hours ago