Installing PHP and suPHP on Ubuntu VPS

So, uptil now, we have successfully secured our Ubuntu VPS, installed Apache and hosted three sites (two using domains and one sub domain). Now, it is time to install some real server side scripting language, which in our case is going to be PHP. Let us see how.

#1: Install PHP:

#1.1: Basic Installation:

sudo apt-get install libapache2-mod-php5

This will install and enable PHP as an apache module. Just to be on the safer side, make sure you execute:

sudo a2enmod php5

#1.2: Install other PHP dependencies:

To make proper use of PHP, we are going to need some dependencies, namely:

  • php5-gd : For image related stuff.
  • php5-mysql : For connecting to mysql database.
  • php5-mcrypt : To have mcrypt library.
  • php5-imagick : To have image magic libraries.
  • php5-suhosin : To install suhosin security patches. Please note that if you are having PHP version 5.4 or greater, then you do not need this package. So I am not going to put it in the example. For version 5.3.x it is recommended to install.
  • php5-curl: CURL library to enable remote connectivity.

We can install them in a single shot by executing:

sudo apt-get install php5-mysql php5-gd php5-mcrypt php5-imagick php5-curl

#1.3: Editing the php5.conf file:

We have all our sites hosted inside /home/user/public_html file. Now, by default, execution of PHP files inside such directory is disabled. So we will need to manually enable them.

Edit the file /etc/apache2/mods-available/php5.conf and search for something like:

            php_admin_value engine Off

Comment those lines so it becomes:

#            php_admin_value engine Off

#1.4: Restart the server:

sudo service apache2 restart

And you are done. For testing, place a file phpinfo.php inside /home/localhost/public_html with the following content:

<?php phpinfo();
<!--?php phpinfo();<br ?-->

And access it from mainsite.com/phpinfo.php. You should see the output of phpinfo.

#2: All about suPHP on Ubuntu VPS:

suPHP gives additional layer of security to PHP. I highly recommend installing it, and in fact it necessary if you wish to run different sites under different users in order to avoid accidental conflicts. You may skip it if you want, but our guide will continue considering you will run suPHP for safety.

#2.1: Install suPHP:

Simply execute:

sudo apt-get install suphp-common libapache2-mod-suphp

And it will install suPHP with all its basic configuration.

#2.2: Configuring suPHP to make it Work!

At this point, you probably have broken apache server. If you run any php file, then you will simply not be able to access it. Apache will return with an 500 Internal Server error. Do not worry though, as we are going to fix this.

#2.2.1: Editing your Virtual Host Directive:

Edit your Virtual Host Directive:

nano /etc/apache2/sites-available/mysites

And inside every directive, add the following lines:

php_admin_flag engine off
#AddHandler application/x-httpd-php .php .php3 .php4 .php5 .phtml
#suPHP_AddHandler application/x-httpd-php
suPHP_Engine on

So, now my virtual host file looks like this:

#Mainsite.com

    ServerAdmin webmaster@mainsite.com
    ServerName mainsite.com
    ServerAlias www.mainsite.com

    DocumentRoot /home/localhost/public_html

    php_admin_flag engine off
    #AddHandler application/x-httpd-php .php .php3 .php4 .php5 .phtml
    #suPHP_AddHandler application/x-httpd-php
    suPHP_Engine on

        Options FollowSymLinks
        AllowOverride None

        Options Indexes FollowSymLinks MultiViews
        AllowOverride None
        Order allow,deny
        allow from all

    ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
    <Directory "/usr/lib/cgi-bin">
        AllowOverride None
        Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
        Order allow,deny
        Allow from all

    ErrorLog /home/localhost/logs/error.log

    # Possible values include: debug, info, notice, warn, error, crit,
    # alert, emerg.
    LogLevel warn

    CustomLog /home/localhost/logs/access.log combined

#PHPMyAdmin

    ServerAdmin webmaster@localhost
    ServerName phpmyadmin.mainsite.com
    ServerAlias www.phpmyadmin.mainsite.com

    DocumentRoot /home/phpmyadmin/public_html

    php_admin_flag engine off
    #AddHandler application/x-httpd-php .php .php3 .php4 .php5 .phtml
    #suPHP_AddHandler application/x-httpd-php
    suPHP_Engine on

        Options FollowSymLinks
        AllowOverride None

        Options Indexes FollowSymLinks MultiViews
        AllowOverride None
        Order allow,deny
        allow from all

    ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
    <Directory "/usr/lib/cgi-bin">
        AllowOverride None
        Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
        Order allow,deny
        Allow from all

    ErrorLog /home/phpmyadmin/logs/error.log

    # Possible values include: debug, info, notice, warn, error, crit,
    # alert, emerg.
    LogLevel warn

    CustomLog /home/phpmyadmin/logs/access.log combined

#MyWordPress.com

    ServerAdmin webmaster@localhost
    ServerName mywordpress.com
    ServerAlias www.mywordpress.com

    DocumentRoot /home/wordpress/public_html

    php_admin_flag engine off
    #AddHandler application/x-httpd-php .php .php3 .php4 .php5 .phtml
    #suPHP_AddHandler application/x-httpd-php
    suPHP_Engine on

        Options FollowSymLinks
        AllowOverride None

        Options Indexes FollowSymLinks MultiViews
        AllowOverride None
        Order allow,deny
        allow from all

    ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
    <Directory "/usr/lib/cgi-bin">
        AllowOverride None
        Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
        Order allow,deny
        Allow from all

    ErrorLog /home/wordpress/logs/error.log

    # Possible values include: debug, info, notice, warn, error, crit,
    # alert, emerg.
    LogLevel warn

    CustomLog /home/wordpress/logs/access.log combined

PS: There’s a reason of adding those commented lines. We are coming to that shortly.

#2.2.2: Editing suphp configuration files:

At this point, probably everything is working, but not ideally. For example, the files created by PHP scripts will not be readable by apache user, the logs generated by suPHP will not be stored properly etc. To fix all these, we need to edit two files:

Edit /etc/suphp/suphp.conf:

sudo nano /etc/suphp/suphp.conf

And change the following values:

  • docroot=${HOME}/public_html
  • umask=0022

Here is my suphp.conf, feel free to copy it:

[global]
;Path to logfile
logfile=/var/log/suphp/suphp.log

;Loglevel
loglevel=info

;User Apache is running as
webserver_user=www-data

;Path all scripts have to be in
docroot=${HOME}/public_html

;Path to chroot() to before executing script
;chroot=/mychroot

; Security options
allow_file_group_writeable=false
allow_file_others_writeable=false
allow_directory_group_writeable=false
allow_directory_others_writeable=false

;Check wheter script is within DOCUMENT_ROOT
check_vhost_docroot=true

;Send minor error messages to browser
errors_to_browser=false

;PATH environment variable
env_path="/bin:/usr/bin"

;Umask to set, specify in octal notation
umask=0022

; Minimum UID
min_uid=100

; Minimum GID
min_gid=100

[handlers]
;Handler for php-scripts
application/x-httpd-suphp="php:/usr/bin/php-cgi"

;Handler for CGI-scripts
x-suphp-cgi="execute:!self"

Notes for PHP 5.3.x:

It seems the above configuration is not enough to run PHP version 5.3.x with suPHP. We are going to need something more.

1. Uncomment in your virtual host file:

    #AddHandler application/x-httpd-php .php .php3 .php4 .php5 .phtml
    #suPHP_AddHandler application/x-httpd-php

Now, open the /etc/suphp/suphp.conf and change

application/x-httpd-suphp="php:/usr/bin/php-cgi"

To

application/x-httpd-php="php:/usr/bin/php-cgi"

Thanks to Mike at MikeBeach.org for this tutorial, which gave us the solution.

If it is still not running, then yell at the comment section. We will figure something out.

Further Testing:

Create a file inside /home/localhost/public_html/whoami.php and put inside:

<!--?php echo exec('/usr/bin/whoami'); ?--><?php
echo exec('/usr/bin/whoami');

Access it from mainsite.com/whoami.php and if the output is localhost, then you are doing great.

500 Internal Server Error:

This can happen because of a number of facts. Although, suPHP is running fine, it is blocking the script execution. Probably reasons are:

1. Insufficent file permission:

suPHP requires the permission to be atmost 755. If yours give more, then it will fail. Simply chmod:

chmod -Rv og-w public_html

And this should solve the problem. Also, make sure your user has default umask set to 0022 (as said in the part one of this series).

2. You do have PHP OPCode caching:

Disable the module and restart your webserver.

3.Check log

Check /home/localhost/log/suphp.log for more information.