Where Does cPanel Put It?

Posted by Nessa | Posted in uncategorized | Posted on 17-12-2008


I can think of a few things that are wrong with that title but in all seriousness…don’t you ever wonder where cPanel stores the config changes that you make in WHM?  Automation is the key nowadays, and lately that’s required me to get a little down and dirty with cPanel to find its deepest secrets. *This information is not official documentation, nor is it backed up by cPanel or set in stone.  In other words, don’t blame me if you mess up your server.

These are files that store the information read and used by WHM (as of 11.23.6)

  • IP addresses: /etc/ips
  • Reserved IPs: /etc/reservedips
  • Reserved IP reasons: /etc/reservedipreasons
  • IP address pool: /etc/ipaddrpool
  • Access hash (WHM remote access key): /home/user/.accesshash or /root/.accesshash
  • cPanel update preferences: /etc/cpupdate.conf
  • Basic cPanel/WHM setup:  /etc/wwwacct.conf
  • System mail preferences: /etc/localaliases
  • Exim open relay list: /etc/alwaysrelay
  • Server-wide max emails per hour: /var/cpanel/maxemailsperhour
  • Tweak settings: /var/cpanel/cpanel.config
  • Packages: /var/cpanel/packages/
  • Features: /var/cpanel/features/
  • User data: /var/cpanel/users/ and /var/cpanel/userdata
  • Apache templates: /var/cpanel/templates/apache(1,2)
  • Exim config template: /etc/exim.conf.localopts
  • Exim mail IPs: /etc/mailips
  • rDNS for mail ips: /etc/mail_reverse_dns
  • Clustering: /var/cpanel/cluster/root/config
  • Service manager: /etc/chkserv.d
  • Users and their domains: /etc/userdomains
  • Users and their main domains: /etc/trueuserdomains
  • Users and their owners: /etc/trueuserowners
  • Main cPanel IP: /var/cpanel/mainip
  • cPanel version: /usr/local/cpanel/version
  • Resellers: /var/cpanel/resellers
  • Reseller nameservers: /var/cpanel/resellers-nameservers

These are a few scripst that you can use to achieve the same  results of their WHM equivalents:

  • Initialize quotes: /scripts/initquotas
  • Compile Apache: /scripts/easyapache  (you can pass additional options – see EasyApache 2 docs)
  • Update cPanel: /scripts/upcp
  • Enable/disable tweak settings: /scripts/smtpmailgidonly on|off
  • Change PHP API and suExec settings: /usr/local/cpanel/bin/rebuild_phpconf
  • Suspend an account: /scripts/suspendacct <user> <reason>
  • Terminate an account: /scripts/killacct <user>

Obviously there are a ton more, and just about anything done in WHM can be done directly on the server.  The main things to remember:

Scripts are mainly stored in /scripts and /usr/local/cpanel/bin

Data files are in /var/cpanel

Config files are in /etc/ and /usr/local/cpanel


Setting up cPanel Proxies

Posted by Nessa | Posted in uncategorized | Posted on 26-07-2008


It’s been about a while since cPanel 11.1 came out and the proxy script from cpanelproxy.net that we all know and love stopped working. Well, the cPanel devs came through for us again and incorporated an Apache-based proxy feature to natively allow users behind firewalls to connect to cPanel over port 80, similar to the way the previous php-based cpanel proxy worked. This was a peace of cake on new server setups, where all you had to do was check on the proxy options in WHM “Tweak Settings” and include mod_proxy in your Apache build. However, I had a very difficult time getting this to work on previous servers that did not already have those features. After bringing this up to Mr. Ken from cPanel (who, by the way, is the most awesomest person in the cpanel bunch), I was finally able to come up with a procedure for getting this to work without having to completely recompile Apache which is a no-no on more mature production servers.

First, if you haven’t already, run a cpanel update to the latest version which at the time of my writing is 11.23. Once the update is complete, log into WHM > Tweak Settings and check off these options (only the first is required):

Add proxy VirtualHost to httpd.conf to automatically redirect unconfigured cpanel, webmail, webdisk and whm subdomains to the correct port

Automatically create cpanel, webmail, webdisk and whm proxy subdomain DNS entries for new accounts.

Allow users to create cpanel, webmail, webdisk and whm subdomains that override automatically generated proxy subdomains

Now, to install mod_proxy (for Apache 1.3 and 2.x)

Download the source for your Apache version. If you’re not sure what that is, you can find out from your phpinfo file or in some cases by typing ‘httpd -v’ from command line.

wget http://apache.mirrors.tds.net/httpd/apache_1.3.41.tar.gz
tar -xvzf apache_1.3.41.tar.gz
cd apache_1.3.41/src/modules/proxy (will just be /modules/proxy for Apache 2 sources)

You need to compile the mod_proxy module with apxs to add it to httpd.conf. For Apache 1.3.x:

/usr/local/apache/bin/apxs -i -a -c mod_proxy.c

For Apache 2.2 (not sure about 2.0 since we don’t run that version on any of our systems) I found that you have to compile mod_proxy with two of its submodules in order for the proxy feature in cpanel to work:

/usr/local/apache/bin/apxs -i -a -c mod_proxy.c proxy_util.c
/usr/local/apache/bin/apxs -i -a -c mod_proxy_http.c

The restart Apache and verify that it is able to start. In my case, when I just compiled the mod_proxy module I got some error about ap_proxy_lb_workers, but when I added proxy_util that fixed the problem. Then I wasn’t able to get the cpanel proxy feature to work without mod_proxy_http. There is one last step with Apache, where you need to add the proxy virtualhost entries in. cPanel has this set up as one virtualhost entry for all the subdomains as well as https, which didn’t quite work in my case because we have shared SSL certificates on the main IP. So I added the following lines between the <VirtualHost> tags for the main hostname and shared ssl hostname:

ServerAlias cpanel.* webmail.*
RewriteEngine On
RewriteCond %{HTTP_HOST} ^cpanel\.
RewriteRule ^/(.*)$1 [P]
RewriteCond %{HTTP_HOST} ^webmail\.
RewriteRule ^/(.*)$1 [P]
UseCanonicalName Off

These are just the ones for webmail and cpanel, but webdisk and whm ones can be added as well.

All you need to do now is setup the subdomains so that customers can access them. The best way to do this is to specify the username:

/scripts/proxydomains --user=username add

To do all accounts on the server (which can take a while):

/scripts/proxydomains add

To list all the options for this script simply type /scripts/proxydomains .

Moving Towards PCI Compliance with cPanel

Posted by Nessa | Posted in uncategorized | Posted on 14-04-2008


See also: http://www.thecpaneladmin.com/pci-compliance-package-cpanel-servers/

Those of you who are server admins or use certain merchant services know what I’m taking about — it’s that dreaded security scan that picks apart your server to tell you everything that it thinks is wrong, assuming you have the knowledge or access to fix it: yes, the PCI scan. PCI compliancy is a somewhat new procedure used by security companies and financial institutions to measure the security of a webserver that collects and stores sensitive information. The reasons for getting a scan vary, but are most commonly for legal reasons or just the assurance that your server is subject to certain vulnerabilities.

After dealing with 2-3 PCI scans a week for the last year, I’ve put together a common procedure for how to make your server compliant to current PCI standards. Note that each scan company is different and may report other issues, and if you’re using ControlScan then, well, I feel sorry for you. I’m also assuming that you are on a Linux server running cPanel and LAMP.

Step 1: Make sure you have a firewall

PCI scans are nazis about unjustified open ports, so only open the ones that you need in order for services to run effectively. Manually configuring iptables is a pain in the ass, so I recommend using APF or CSF (if you have cPanel) and then configuring the allow rules to only allow ports for active services.

Note that both indicate the opening of cPanel ports 2082, 2095, and 2086, but some scans will complain about these being nonsecure. If that is the case you can configure within WHM to only use the secure ports, then remove the nonsecure ones from the firewall so they can’t be accessed. You should also close MySQL port 3306 for external hosts and allow them on a per-IP basis to anyone other than localhost has to be allowed.

Step 2: Update your system

This is an obvious one, but you’d be surprised how many people still have old packages installed on the server. With cPanel, running /scripts/upcp will usually update the vital system software as long as you have your update configuration in WHM set to allow it, but otherwise I would recommend doing a yum update, up2date, or whatever else you use to manage packages to make sure everything is up to date.

Nowadays old versions of MySQL, PHP, and Apache are no longer squeezing through either, so you need to upgrade to at least MySQL 4.1.22, PHP 5.2.5, and Apache 1.3.39 (some scans will want Apache 2.0.x).

Step 3: FIx OpenSSL

If you did a package update this was probably already taken care of, but if you installed via source you need to make sure you’re using at least 0.9.7j, which is the oldest version that most PCI scans allow. You can get your sources from here, and it may require a recompile of Apache and other services that use it. To check your OpenSSL version, type ‘openssl‘ from your SSH prompt and then type ‘version‘.

Note to Redhat/Fedora/CentOS users: If you’re running a somewhat recent version of your OS your openSSL version probably is something like 0.9.7a, but due to Redhat backporting this may be a false-positive. If you’re on any Redhat-based distribution, just tell your scan company and they’ll bypass OpenSSL checks.

Step 4: Check your SSL certificates

In order to pass a PCI scan your server must have at least one SSL certificate signed by a recognized certificate authority, and any services using SSL need to be using a certificate as well. Go cough up $30-$100 and buy a decent 264-bit SSL certificate and install it not just for Apache, but also for all of your active services. WebHost Manager has a section for installing service SSL certificates to make this process easier.

Step 5: Disable SSLv2 and other weak encryption methods

This one always gets me, because there is no way to disable SSLv2 for everything at once, at least not one that I know of. What makes this part the worse is that not all services support the choosing of SSL protocols and ciphers, but luckily unless you are using ControlScan the ones that don’t are probably not going to show up. Here’s how you do it for common services that are reported:


Add these lines to your httpd.conf (you may to add them to each secure vhost as well):

SSLProtocol -ALL +SSLv3 +TLSv1

POP3 and IMAP:

Edit the following files:


Comment out the existing TLS_CIPHER_LIST line and replace it with the following and restart courier-imap:



Add the following to exim.conf:

tls_require_ciphers = ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM:!SSLv2

For other services that might be on your system, take a look at this guide.

Step 6: Disable mod_userdir (or whatever cPanel is calling it nowadays)

If you are able to go to http://yourserverip/~yourusername, then you have mod_userdir enabled and the scan will probably complain. You can disable this in WHM under Security Center > Apache mod_userdir Tweak, or in httpd.conf add “userdir disabled user1 user2 user3 …etc”

Step 7: Put Apache in incognito mode and disable the bad stuff

If you try to get an Apache error (like a 404 error), the footer of that page probably contains more information that you may want to share about your Apache setup. You can disable this in your httpd.conf by adding these lines:

ServerSignature Off
ServerTokens Prod
FileETag None

You can read more about these here.

Another thing that some scans report is the use of 413 errors. You should add this line to httpd.conf as a workaround:

ErrorDocument 413 /index.php (or any other file)

Just about all scans will complain if the ‘trace’ and ‘track’ apache methods are enabled on your server. You can fix this by adding these lines to your Virtualhost entries or .htaccess files:

RewriteRule ^.*$ - [F]

You should also disable directory indexes, which can be done most easily in your cPanel’s index manager. Directory indexes allow the listing of files inside folders that do not have an index page. You can also disable these in your .htaccess files:

Options All -Indexes

Ending notes

Really, it doesn’t matter how secure your server is if your web application scan is poorly programmed, so your server should not be the ending point in security. Some PCI scan companies are able to detect common vulnerabilities in web applications, but you should take the extra steps to stay ahead of the game and update your site software on a regular basis.

Common PHP Errors

Posted by Nessa | Posted in uncategorized | Posted on 07-12-2007


I’m going back to the basics here, you know, when you wrote your first PHP script and saw an ugly-ass error message pop up on your screen? Error messages are the best tool a programmer has.

Set up Error Reporting

Most PHP errors are straight forward, but there are times where you don’t see any which makes it very difficult to tell what the problem is.

The first step of PHP troubleshooting is to turn error reporting on. For security reasons you’ll want error reporting off by default, but if something goes wrong you’ll need the information for debugging. You can usually enable error reporting by adding this line to the problem script:

<?php error_reporting(E_ALL) ?>

Or you can add these lines to the root .htaccess:

php_flag display_errors on
php_value error_reporting 6143

This will usually display an error useful for troubleshooting, that is, if the software and your server configuration allows it.

Parse Errors

Parse error: parse error, unexpected T_STRING in……

This is a syntax error. Perhaps you forgot a semi-colon at the end of a line, or you forgot a double quote (“) or an end bracket (}) after you started one. For quote and semicolon issues, the problem is usually the line above the one reported in the error. For brackets, it may be at the end of the script.

Parse error: syntax error, unexpected $end in

You’re most likely missing a } somewhere. Make sure that each { you have is also closed with a }.

Parse error: syntax error, unexpected T_STRING, expecting ‘,’ or ‘;’ in..

There may be double quotes within double quotes. They either need to be escaped or brought to single quotes. It’s also possible that a new PHP statement was started before the previous was finished.

Header Errors

Warning: Cannot add header information – headers already sent by (output started at /home/vnessa5/www/errors.php:9) in….

Warning: Cannot send session cache limiter – headers already sent in somefile.php on line 222

Naturally, HTML will parse before PHP. The script is trying to send header information after you’ve already sent output to the browser. HTTP headers are required to be sent before any output from your script, which means that a header function must be placed before any html or even a white space. There are two solutions for this. Either (1) Set the header tags the top of the document, or (2) insert a header redirect by adding this to the very top of the page to force the output buffer:

<?php ob_start();

Then this at the very end of the page (not usually required)

ob_end_flush(); ?>

mySQL Result Source Errors

Warning: Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in…

You need to take a look at the $result variable used to define the loop. More than likely there is a syntax error on the reported line before the $result field, or the value of $result does not exist.

Supplied argument is not a valid stream resource…

This is usually caused when your code is looking for a table or other resource in the database that does not exist.

Sessions are not being created or maintained

This can apply to any of the scenarios below:

(1) The program isn’t remembering your login
(2) Your shopping cart won’t hold items
(3) Your php script is redirecting like crazy
(4) “Call undefined function session_start” error
(5) PHP isn’t processing pages called by something like index.php?page=home&id=7

Your site is most likely dependent on register_globals. You can enable them by putting this line in your .htaccess (or just enabling in your php.ini if you have access):

php_flag register_globals On

Stream Errors

Warning: failed to open stream…

Warning: main(/index.php): failed to open stream: No such file or directory in…

This is usually because either the specified file is missing, or a file declared in a require() or include() function is missing. The easiest way to fix this is by re-installing the PHP program from a freshly-uploaded copy, or restoring the original config.php and just changing the db information. The include path may also be incorrect, but either way your script is looking for a file that isn’t there, or it is looking in the wrong place.

Warning: fopen(…): failed to open stream: Permission denied in…

This is a permissions and/or ownership issue. Try first setting the permissions to 777 just to see if the script will run. If so, you should narrow down the permissions to 775. If not, set the user/group to user:nobody.

Warning: <…> is not a valid stream resource…

Warning: fread(): supplied argument is not a valid stream resource in…

This is an error seen when trying to use functions like fopen(), fread(), feof(), etc. and are usually caused by an invalid or unavailable resource that is being called in the line specified. For instance, if the fread() function is returning this error, it could be that the file it is trying to access does not have the correct permissions or does not exist.

Warning: Failed opening….

Warning: Failed opening ‘…’ for inclusion (include_path=’.:/usr/local/lib/php’) in Unknown on line 0

Make the sure that the file mentioned (and its holding directorie) has read + execute permissions, and that the path to the file is correct. If not, you’ll need to add the path into the PHP code: (or .htaccess)

Blank PHP Pages

You go to a .php page, but it’s blank.

The scope of what can cause blank pages is very broad, but there are a few things to look at:

-Is error reporting turned off anywhere in the script or in the .htaccess? If so, turn it on to see what is happening (php_flag display_errors on), or add the lines at the top of this page into the script.

-Is the PHP script even generating any output (usually you can tell my finding the print function?

-Check the database connection, i.e, username, dbname, user added to db, etc.

-Try using the full <?PHP ?> tags, rather than the shorter versions <? ?>

Also, if the software is prebundled (like phpBB or Gallery), then the index or one of the include pages could be corrupted. Usually you can just replace the problem page with a working version from another installation.
Max Execution Time Error

You receive some variant of a “Max_execution_time” error when loading a page.

This is caused when a PHP script takes longer to execute than the server allows, but can be adjusted by adding a PHP directive to your .htaccess: (in seconds, 0 = unlimited) or modifying the value in php.ini.

php_value max_execution_time 0

Open_basedir Errors

Warning: Unknown(): open_basedir restriction in effect.

This is a protective feature of Apache that restricts PHP from accessing files/folders outside the user’s home directory. Most of the time this is due to an incorrect include path in one or more of the config files (which are usually mentioned). Look for something like this:


The heading / tells the filesystem that these folders are on the server root, and thus prevents PHP from accessing them. You can usually fix this by changing the path to these files to be absolute to their location:




Using an .htaccess with PHP Compiled as CGI

Posted by Nessa | Posted in uncategorized | Posted on 06-12-2007


We recently started installing suPHP on a few of our servers, which is an implementation of phpsuexec, only a ton faster and with less overhead. Yesterday I posted a tutorial on how to install suPHP on a PHP5/Apache server outside of EasyApache, but today I shall go over how to enable PHP directives in your .htaccess instead of using the php.ini.

First of all, if you’d rather use the .htaccess than the php.ini capabilities of a phpsuexec environment, then shame on you. But, we have some customers who are terrified of php.ini and would rather use the .htaccess. So what? Ok, well there is a workaround. Mr. Joye released a newer version of htscanner that now works with suPHP, and allows you to use php directives in your .htaccess just like you did when PHP was installed as and Apache module. All you have to do is download the tarball and install like any other PHP module:

wget http://pecl.php.net/get/htscanner-0.8.1.tgz

tar -xvzf htscanner-0.8.1.tgz

cd .htscanner-0.8.1

./configure && make && make install

Then add a loader for the resulting binary to your php.ini:


From here, you can add your php_value and php_flag statements to your .htaccess as usual within <ifmodule> tags. I should note that the reason why you normally would not be able to overwrite php.ini values in your .htaccess is because .htaccess is an Apache file. Under phpsuexec/suPHP, PHP runs as a CGI module so Apache does not understand what those mean, so it will either ignore them all together or return a nasty 500 error.

Installing Mod_Python

Posted by Nessa | Posted in uncategorized | Posted on 11-11-2007


Update: These instructions may be outdated for most people. I’ve posted newer instructions on my collaborated sister site:


I figured I’d put this out here because it’s come up quite recently with people who are using Apache 1.3.x. If you haven’t gotten the balls to upgrade to Apache 2.x yet, you can still install mod_python…just not as easily. This simple walk through is for Apache 1.x and 2.x.

First, you need to determine what version of Python you are running. To check, type ‘python -V‘ at the command line. If you are running Apache 1.3.x, you should use mod_python version 2.7.11. For Apache 2.2.x, use 3.3.1.

1. Download the Python sources for the version of Python that you have installed, the run a configure and make (no install) just to compile them. If you are running Apache 1.3, you should add –without-threads to your configure line.

2. Once you have this, follow these steps to compile mod_python:

cd /usr/src
wget http://www.trieuvan.com/apache/httpd/modpython/mod_python-2.7.11.tgz
tar -xvzf mod_python-2.7.11.tgz
cd mod_python-2.7.11

./configure –with-apxs=/usr/local/apache/bin/apxs –with-python=/usr/src/Python2.5.5

The –with-python path should reflect the location of the sources you downloaded and compiled earlier.

3. If you are on Apache 1.3, you now need to perform the steps below. If not, skip to step 4:

pico src/Makefile

Locate the ‘CFLAGS’ line, and add the -DEAPI switch so it looks like this:


Then add -lutil to the LIBS line like so:

LIBS=-lm /usr/src/Python-2.5.1/libpython2.5.a -lutil

4. Run the make and make install.

5. Now edit httpd.conf and create your handlers. This will tell Apache which file extensions to interpret through mod_python. If you have mod_rewrite installed and enabled, users can override this in their .htaccess files:

LoadModule python_module libexec/mod_python.so
AddModule mod_python.c
AddHandler mod_python .psp .py

Using PHP to Display Version Info

Posted by Nessa | Posted in Uncategorized | Posted on 15-10-2007


I’ve been working on this application for work that does some simple server reporting, part of which involves displaying the versions of major software running on the machines. The importance of this to me personally is that since we have over 30 shared servers hosting multiple customers, we are continually moving websites between servers. Some of our older generation servers are still running MySQL 4.0 and PHP 4.3, so I need to be aware of this to make sure that customers are being moved to servers with compatible versions. It’s also good in tracking and planning upgrades.

I find it best to use the exec() function since it’s not blocked by most hosts. However, if you are on a shared host it’s very likely that certain PHP functions are disallowed in the php.ini. In that case you may be able to subsitute exec with system, passthru, escapeshellcmd, or shell_exec…unless those are blocked too. Then I guess you’re out of luck.

Start by creating some variables to store ordinary shell commands. If you wanted to find the php version from command line, you would usually type:

php -v

This will give a huge chunk of crap that you really don’t need if you’re making a simple version display script. In this case, you can use grep, awk, sed, and cut to trim down the output into a one-liner:

php -v |grep built |awk {‘print $2′}

The awk command prints out columns, so in the above example I’m printing out the second column of the line that contains the word ‘built’. Once the desired output is figured out, you simply assign it to a variable passed through exec() or a similar function:

$phpver = exec("php -v |grep built |awk {'print $2'}");

Then you can call the variable $phpver anywhere in your script:

echo "PHP Version: $phpver";

You can probably go through and figure out the commands to show other software versions on your server. In my script I’m showing the perl, php, mysql, apache, python, cpanel, and ruby versions. Here are the commands I used:


$perlver = exec("perl -v |grep linux |awk {'print $4'}|sed -e 's/v//'");
$phpver = exec("php -v |grep built |awk {'print $2'}");
$mysqlver = exec("mysql -V |awk {'print $5'} | sed -e 's/,//'");
$apachever = exec("apachectl -v |grep version |awk {'print $3 $4'}|sed -e 's/Apache\///'");
$pythonver = exec("python -V 2>&1 | sed -e 's/Python //'");
$cpanelver = exec("cat /usr/local/cpanel/version");
$rubyver = exec("ruby -v |awk {'print $2'}"); ?>

Then I just echoed out all the variables to display my version numbers:

See here .

Installing suPHP on cPanel

Posted by Nessa | Posted in uncategorized | Posted on 05-06-2007



I wrote this tutorial a while back and figured it would be good to post because suPHP is growing more popular as an alternative to phpSuExec. The instructions assume that you are on a Linux cPanel server and are familiar with how to install PHP, but do not want to use EasyApache’s suPHP installer in WHM (you stubborn bitches)

Note also that these instructions use suPHP 0.6.1 with a cPanel patch that makes it equivalent to 0.6.2. I personally have had issues with the actual 0.6.2 version installing, so I stuck with the patch.

Next, download suPHP and the apply the patch:

wget http://v-nessa.net/imh_files/suphp-0.6.1.tar.gz
tar -xvzf suphp-0.6.1.tar.gz
cd suphp-0.6.1

wget http://v-nessa.net/imh_files/suphp-0.6.1-cpanel.patch
patch -p1 < suphp-0.6.1-cpanel.patch

Then compile the binary:

./configure –prefix=/usr –sysconfdir=/etc –with-apxs=/usr/local/apache/bin/apxs –with-apache-user=nobody
make && make install

Now locate your PHP binaries for installation. If you previously used EasyApache, you should be able to find them somewhere in your home directory within a directory named ‘cpeasyapache’ or something similar depending on your cPanel version. Otherwise you will need to fetch the PHP sources from php.net if you do not have the original sources you used to compile.

Check the server’s phpinfo file and grab the configure path, then copy and paste it into notepad and remove all the single quotes. You’re basically compiling PHP exactly the same way as it was before, only not as an Apache module.

cd /home/cpapachebuild/buildapache/php-5.2.3
make clean

The only difference is that you need to remove the ‘–with-apxs=’ switch from the configure line. The prefix can stay the same, but it’s recommended to install this in a different directory, like /usr/cgiphp or something.

So technically your configure would look like this:

./configure –prefix=/usr/cgiphp –with-xml –with-mm ………
make install

Now check that the installation was successful (should say cli for this one, but cgi will work as well) :

/usr/cgiphp/bin/php -v

PHP 5.2.3 (cli) (built: Aug 3 2007 07:22:58)
Copyright (c) 1997-2007 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies

Download the suphp.conf into /etc, which is the location you specified during the configuration of suphp:

cd /etc
wget http://v-nessa.net/imh_files/suphp.conf

Now you need to edit /etc/suphp.conf and change the handler paths to (lines 47/48):


Check httpd.conf to see if there is already an suphp module setup in the virtualhost entries. If not, set up the apache template to automatically add it for new accounts:

pico /usr/local/cpanel/etc/httptemplates/apache1/default

Under <IfModule mod_php4.c> (exactly as is) add these lines:

<IfModule mod_suphp.c>
suPHP_UserGroup %user% %user%
suPHP_ConfigPath /home/%user%/php

suPHP_ConfigPath /home/%user%/php specifies the location of the user’s php.ini file, which will be created later. This is completely optional, as it is only necessary if you want to specify where the users’ php.ini files are going to be location (default location is public_html). Recent versions of cPanel already have an suPHP module loader, so you may only have to add the suPHP_ConfigPath line to the suPHP section.

You should do the same for SSL hosts in /usr/local/cpanel/etc/httptemplates/apache1/ssldefault.

Add the following lines to httpd.conf in their appropriate sections:

LoadModule suphp_module libexec/mod_suphp.so
AddModule mod_suphp.c

<IfModule mod_suphp.c>
suPHP_Engine On
suPHP_ConfigPath /usr/local/Zend/etc
suPHP_AddHandler x-httpd-php5
AddHandler x-httpd-php5 .php5
suPHP_AddHandler x-httpd-php
AddHandler x-httpd-php .php .php3 .php4 .phtml
suPHP_AddHandler x-httpd-php-source
AddHandler x-httpd-php-source .phps
<Files *.php5>
suPHP_ConfigPath /usr/cgiphp/lib

It’s also a good idea at this point to disable the loading of the Apache php module, so they can only run as CGI. Comment out these lines:

#LoadModule php5_module libexec/libphp5.so
#AddModule mod_php5.c

If you do the above, comment out the following lines:

#AddType application/x-httpd-php .php
#AddType application/x-httpd-php .php4
#AddType application/x-httpd-php .php3
#AddType application/x-httpd-php-source .phps
#AddType application/x-httpd-php .phtml

The users that already exist on the system should already have suphp directives in their virtualhost entries. If not, you will need to add them manually:

<IfModule mod_suphp.c>
suPHP_UserGroup user user
suPHP_ConfigPath /home/%user%/php

In this one you actually need to replace ‘user’ with the username and group of the account.

Now you need to fix the first VirtualHost entry as well, which is the website that is displayed when you go to http://server.com on a shared hosting environment. This is the site that is pulled from /usr/local/apache/htdocs and PHP will not work in this directory, because your suphp.conf file defines the docroot to be /home, meaning that suPHP will not execute PHP that is outside of /home. When you find the VirtualHost container for the main IP add the following into that VirtualHost:

<IfModule mod_suphp.c>
suPHP_UserGroup <user> <user>
<Directory /usr/local/apache/htdocs>
suPHP_GlobalDocRoot /usr/local/apache/htdocs
suPHP_DontCheckVHostDocRoot Yes

For the user, since PHP won’t execute as nobody or root, this needs to be a valid user on the system. Generally it’s best to create a neutral user on the system with no SSH access to be the owner of the htdocs folder. Whatever user you use, you will need to chown the entire htdocs directory to that user (or whatever directory you use as a default. The DontCheckVHostDocRoot part is necessary if you are running this outside of /home.

Last you should create a php folder in /root/cpanel3-skel with a copy of the server’s php.ini file, so new user accounts are created with a php.ini.

The path to the cgi php binary is /usr/local/bin/php, so you want to make sure that it is accessible when called from command line and that suPHP loads the new binary.

ln -s /usr/cgiphp/bin/php-cgi /usr/local/bin/php
ln -s /usr/cgiphp/bin/php-cgi /usr/local/bin/php5
ln -s /usr/cgiphp/bin/php /usr/bin/php
ln -s /usr/cgiphp/bin/php /usr/bin/php5

If you get an error about one already existing, simple delete it and try to link it again.

Now you have to copy the extentions:

cd /usr/cgiphp/lib/php/
mkdir -p extensions/no-debug-non-zts-20060613

pico /usr/local/lib/php.ini

Change the extension_dir value to that of the new folder you created, then copy all the files over:

cp /usr/local/lib/php/extensions/no-debug-non-zts-20060613/* extensions/no-debug-non-zts-2006061/

Depending on the server, the actual extension directory may be different!

Settings for suphp.conf

Suphp.conf lets you control the settings in place for suPHP. The following settings are the recommended in place for shared servers:


The location of the logfile on the server, will be created automatically.


What information to describe in the logs. ‘info’ is very broad, but you can also use ‘warn’ to only show warnings.


What use Apache runs as — this basically indicates what user no php scripts can run as, even ones in htdocs.


The base directory where php scripts have to be located in order to run, which prevents php scripts from executing from system folders. If a user for some reason needs to execute something from outside of home, you need to make a virtualhost directive containing:

<Directory /usr/local/apache/htdocs>
suPHP_GlobalDocRoot /<path to directory>
suPHP_DontCheckVHostDocRoot Yes


This is the most important for security, specifying the allowable permissions of files and folders by other users than the one owning the script.

If your server currently has accounts on it, you’ll need to run these followup scripts:


From /home:

find -perm 777 -exec chmod 755 {} \; -print
find -perm 666 -exec chmod 644 {} \; -print

For the php.ini, you’ll also need to copy it from /usr/bin/php.ini into /home/user/php for all users existing on the machine before the installation of suPHP. New user accounts will automatically have this, as long as it you followed the step of copying it to /root/cpanel3-skel/php

If the server is running Fantastico, make sure you set the config to use phpsuexec.

VirtualHost Hacking with Wildcard DNS

Posted by Nessa | Posted in Uncategorized | Posted on 19-05-2007


A recent topic in the webhosting business is wildcard DNS.  Setting up a wildcard record will allow you to essentially have infinite subdomains all pointing to the same place…. you can try this on my site if you’d like by typing in any random subdomain (like lkjairl.v-nessa.net) and then see if point back to my primary, unless it’s one that I’ve actually created.  Now if you combine this ‘technology’ with the power of .htaccess rewrites, then congratulations.  You’ve just cheated your host and obtained unlimited subdomains.

The first thing you would need to do is have a wildcard DNS record set up.  If you have access to your own zone files, that’s great, otherwise you’ll need to ask your host to set it up for you.  Fair warning though, your hosting company is not stupid (unless it’s Dreamhost) so don’t be surprised if they decline your request.  To set up the DNS zone you simple need to add an a-record “*” like so:

* 14400 IN A

*Note: Some argue that you need to use the full  *.domain.com. as the first field…this is actually not required at all, nor recommended!

Depending on your platform, you’ll likely find your domain’s zone file in /var/named/domain.com.db unless you have this feature in your host’s control panel.  Once you’ve added the record simply reload named/BIND with the /etc/init.d/named reload command if needed.   If you’re using an interface it will probably do this for you automatically.

Now you need to add ServerAlias line to your httpd.conf for the wildcard, if your host does not already have Apache configured this way.  Inside the <virtualhost> tags for your domain, add this line:

ServerAlias *.domain.com

Then restart Apache as usual (/etc/init.d/httpd restart) and test a random subdomain to see if it’s working.

So now you will notice that any non-distinguished subdomain shared the same document root as your primary….that’s great and all but it really serves no purpose, so that is where mod_rewrite comes in.  You can add and modify the follow code in your .htaccess to have Apache direct these subdomains to where they need to go:

RewriteEngine On
RewriteRule ^\.htaccess$ – [F]
RewriteCond %{HTTP_HOST} !^www\.example\.com?$
RewriteCond %{HTTP_HOST} ^([^.]+)\.example\.com?$
RewriteRule ^$ /folder/page.html [L]

Using your imagination you can write your own script that can create subdomains and the appropriate .htaccess entries on-demand (assuming that this is not blocked by mod_security).  The end result is seemingly unlimited subdomains on your account!  Also, the changes are usually immediate and do not require propagation.


Make Apache Faster

Posted by Nessa | Posted in Uncategorized | Posted on 09-05-2007


Apparently someone thinks that my website is too slow in its load time. I never really thought it was that bad, but his little handy danty Firefox plugin claims that it takes my site approximately 6-7 seconds to load initially, which kinda sucks. I know that I’ve written some stuff on optimizing php performance and I tell customers on a daily basis how to keep their sites from bogging down our servers, but I never really cared to optimize my own site because I have a v-dedicated server. So anyways, I’ve made a few modifications to both my site and the server environment to help speed things up a bit.

You might want to read my article on Optimizing PHP as well.

Enable Compression with Apache

If you are running on Apache 2, mod_deflate should already be installed on your system — all you have to do is enable it. I recently downgraded my server back to Apache 1.3.37 (mainly because of cPanel) so I’m using the mod_gzip alternative. Basically, mod_gzip compresses the contents of your site server-side and then passes the file onto your compression-enabled browser to decompress the file. The overhead on the server may be slightly higher during heavier traffic times, but you’ll find yourself saving bandwidth and load time since the server is passing less data between it and your clients.

To install mod_gzip on Apache:

wget http://easynews.dl.sourceforge.net/sourceforge/mod-gzip/mod_gzip-
tar -zxvf mod_gzip-
cd mod_gzip-

If you’re on a cPanel system, you’ll need to modify the path to apxs:

pico Makefile

Change APXS?=/usr/local/sbin/apxs to APXS?=/usr/local/apache/bin/apxs

Then just do the normal make && make install

Now enable the dynamic modules in the Apache config:

pico /usr/local/apache/conf/httpd.conf

Uncomment out these lines:

#LoadModule gzip_module libexec/mod_gzip.so
#AddModule mod_gzip.c

Now all you need to do is restart Apache as normal. To see if compression is working on your site, just hop on over to this page and run the test.

Change The KeepAliveTimeout

By default your Apache configuration will probably have keep connections alive for up to 15 seconds before they die off. For busier sites this can be a little too long. I suggest setting this to 3 or 5 seconds in your httpd.conf.

Adjust the PHP Output Handler

Your PHP scripts are constantly recompiiling themselves every time a page is loaded. If your site is heavily reliant on PHP, you may find it beneficial to have PHP send its output to a compression function in your php.ini

output_handler = ob_gzhandler

Check Your resolv.conf

It’s obvious that your settings are fine if your site and email are working, but your resolver may not be set to do the fastest lookups. If you have a caching or local nameserver, you will want that listed first in /etc/resolve.conf . I’ve seen a drastic decrease in performance on some customer VPS’s because the servers were doing DNS lookups through external nameservers. I have dedicated nameservers, so my resolve.conf looks like this:

search v-nessa.net


One of the major changes I made on my site was to the image and page sizes… I did a lot of code and image compression to decrease the amount of time it takes to load my site. A majority of this consisted of simply saving my images in .gif or .png formats and removing plugins and includes that were not needed.