(dv) 4.0 - Making It Better :: Using mod suphp with Plesk

  • This page was last modified on December 16, 2011, at 01:09.
The (mt) Community Wiki is a collaborative project. Any (mt) Media Temple customer or employee may contribute. Not all articles and/or content have been tested for accuracy by (mt) Media Temple.

For officially moderated and tested articles, be sure to visit our KnowledgeBase.

From (mt) Community Wiki

This is part of the (dv) 4.0 - Making It Better series. Please see the parent article for related articles and information on downloading the script that includes options to automate the instructions included in this article. This series of articles is not directly supported by (mt) Media Temple.

The Apache module mod_suphp is one of the many ways that has been developed for the web server to handle PHP code so that it is executed as a user other than apache. In many cases, this is considered a more secure option. Also, in many cases, this avoids permissions issues that PHP-based applications will encounter, such as

  • "this directory/htaccess file is not write-able"
  • errors when trying to upload
  • having to resort to 777 permissions on directories or files

The end-result of this guide is to have mod_suphp installed and configured so that automatically ties in to Plesk to work with both existing domains and those added in the future.

It is very important to note that Plesk 10 already has its own PHP handler that runs PHP as the domain user using FCGI. The guide for that can be found at (dv) 4.0:Enable FastCGI

This guide is an alternative to the method already provided by Plesk and will entirely replace it. Running PHP as FCGI will often have more potential in terms of optimization. It provides the ability to separate PHP processes from Apache itself and allows for opcaching such as APC. However, it is much more difficult to create something that takes advantage of this potential and is still somewhat one-size-fits-all for those that would prefer to avoid too much server administration.

To goal here is to create a compromise that will help the average (dv) Dedicated-Virtual user - high-end users and server administrators may get more mileage out of a more customized FCGI setup. The footprint for mod_suphp is normally very manageable and it will address many of the common issues PHP applications run into.

This guide will make significant changes to file permissions and general server configuration. It it highly advisable that you make a backup of meta data (file permissions, ownerships, and timestamps) that you will want to revert to if this does not work for your specific set up.

Before you continue, you may have a few additional questions. Hopefully this FAQ can address them.

Will this guide allow my Wordpress, Drupal, Joomla, etc CMS to work without any additional changes?

  • Yes. The only thing suPHP requires is that PHP files are owned by your domain user. So if you upload your files as your subscription's FTP user, you're already good to go. No checkboxes or SSH commands required from here on out.

What if I want to change a specific PHP value for one of my domains - can I still use php_value in an .htaccess file?

  • No, suPHP will not allow setting PHP values in a .htaccess file. However, it does allow custom php.ini files. To that end, this guide sets up every domain with their own php.ini file that can be accessed via FTP. Hopefully, this makes things easier on users with minimal SSH experience. If you connect over FTP with your subscription's user, you can find these at the following locations:
    • primary domain: etc/php.ini
      • absolute path: /var/www/vhosts/<parent_domain>/etc/php.ini
    • additional domains: other_domains_etc/<other_domain>/php.ini
      • absolute path: /var/www/vhosts/<parent_domain>/other_domains_etc/<other_domain>/php.ini
      • this is a symlink to /var/www/vhosts/<other_domain>/etc/php.ini

Wait, does this mean I have to make a php.ini for every domain?

  • Not at all. Any values not specified in those custom files will just be inherited by the main configuration in /etc/php.ini. This simply allows you to over-ride those settings on a domain-by-domain basis if the need arises.
  1. Since we need to ensure that this will cooperate with Plesk, we'll be compiling mod_suphp from source. A prerequisite for this is a compiler, which is included in yum's development tools. We will also need to install http-devel:
    yum -y groupinstall "development tools"
    
    yum -y install httpd-devel
    
  2. You will need to download mod_suphp to your server. For organizational purposes, it is good practice to use /usr/local/src. That way, you always know where to find the temperamental data/source code you use for new installations. So we can step into that directory:
    cd /usr/local/src
    

    And download and unpack mod_suphp:

    wget http://www.suphp.org/download/suphp-0.7.1.tar.gz
    
    tar xzf suphp-0.7.1.tar.gz
    
    rm -f suphp-0.7.1.tar.gz
    
    cd suphp-0.7.1
    
  3. Next, everything is put together and installed, specified with settings that will cooperate with Plesk:
    ./configure --prefix=/usr --sysconfdir=/etc --with-apr=/usr/bin/apr-1-config --with-apache-user=apache --with-setid-mode=paranoid --with-php=/usr/bin/php-cgi --with-apxs=/usr/sbin/apxs
    
    make
    
    make install
    
  4. The first thing mod_suphp will require in order to run are a few configuration files. Each can be created with a single command.
    • Basic config file:
    cat <<EOF > /etc/suphp.conf
    [global]
    logfile=/var/log/httpd/suphp.log
    loglevel=error
    webserver_user=apache
    docroot=/var/www
    allow_file_group_writeable=true
    allow_file_others_writeable=true
    allow_directory_group_writeable=true
    allow_directory_others_writeable=true
    check_vhost_docroot=false
    errors_to_browser=false
    umask=0022
    min_uid=30
    min_gid=30
    
    [handlers]
    php5-script="php:/usr/bin/php-cgi"
    EOF
    
    • Apache configuration:
    cat <<EOF > /etc/httpd/conf.d/mod_suphp.conf
    LoadModule suphp_module modules/mod_suphp.so
    suPHP_AddHandler php5-script
    EOF
    

    You may notice that the suPHP engine is not being turned on yet. The reason for this is so that it will not interfere with root-owned web files such as webmail. Instead, it will be turned on later for each domain individually as part of their VirtualHost entry.

  5. Hooks now need tied into the Plesk system so that when domains are added or updated, the suPHP settings come along for the ride. This requires creating a number of scripts that will be run as event handlers.
    1. Script to handle changes to existing hosting settings:
      • create the script
      cat <<EOF > /usr/local/psa/admin/sbin/suphp_settings_change.sh
      #!/bin/bash
      oldUser=\$1
      newUser=\$2
      
      ls -ld /var/www/vhosts/*/etc /var/www/vhosts/*/subdomains/*/etc |\
      perl -ne '\$_ =~ /^([^\s]+\s+){2}'"\$oldUser"'.*?([^\s]+)$/ and print "\$2\n"'|\
      while read x; do
      chown \$newUser \$x
      chown \$newUser \$x/php.ini
      perl -0 -p -i -e 's/(^\#\#\#mt-opt[^\n]*(\n|[^\n])+?)'"\$oldUser"'/\1'"\$newUser"'/' \$x/../conf/vhost.conf
      done
      
      /usr/local/psa/admin/sbin/httpdmng --reconfigure-all
      /etc/init.d/httpd stop
      /etc/init.d/httpd start
      EOF
      
      • chmod the script
      chmod 755 /usr/local/psa/admin/sbin/suphp_settings_change.sh
      
      • insert the script as an event handler in Plesk
      mysql -u'admin' -p$(cat /etc/psa/.psa.shadow) psa -e"insert into event_handlers values(default,(select id from actions where descr='Update Physical Hosting'),0,'root','/usr/local/psa/admin/sbin/suphp_settings_change.sh <old_system_user> <new_system_user>');"
      
    2. Script to handle adding new domains:
      • create the script
      cat <<EOF > /usr/local/psa/admin/sbin/suphp_domain_add.sh
      #!/bin/bash
      newDom=/var/www/vhosts/\$1
      domUser=\$2
      
      if [ -d \$newDom/etc ]; then
      mkdir \$newDom/other_domains_etc
      else
      mkdir \$newDom/etc
      ln -s \$newDom/etc `mysql -u'admin' -p\$(cat /etc/psa/.psa.shadow) -Ns psa \
      -e"select home from sys_users where login='\$domUser';"`/other_domains_etc/\$1; fi
      chown \$domUser:psacln \$newDom/etc
      touch \$newDom/etc/php.ini
      chown \$domUser:psacln \$newDom/etc/php.ini
      
      cat <<EndOF > \$newDom/conf/vhost.conf
      ###mt-opt - comment the following lines to disable mod_suphp for this domain
      suPHP_Engine On
      suPHP_UserGroup \$domUser psacln
      suPHP_ConfigPath \$newDom/etc
      ###mt-opt
      EndOF
      
      /usr/local/psa/admin/sbin/httpdmng --reconfigure-all
      /etc/init.d/httpd stop
      /etc/init.d/httpd start
      EOF
      
      • chmod the script
      chmod 755 /usr/local/psa/admin/sbin/suphp_domain_add.sh
      
      • insert the script as an event handler in Plesk
      mysql -u'admin' -p$(cat /etc/psa/.psa.shadow) psa -e"insert into event_handlers values(default,(select id from actions where descr='Create Physical Hosting'),0,'root','/usr/local/psa/admin/sbin/suphp_domain_add.sh <new_domain_name> <new_system_user>');"
      
    3. Script to handle adding new subdomains:
      • create the script
      cat <<EOF > /usr/local/psa/admin/sbin/suphp_subdomain_add.sh
      #!/bin/bash
      newDom=/var/www/vhosts/\$1/subdomains/\$2
      domUser=\$3
      
      mkdir \$newDom/etc
      chown \$domUser:psacln \$newDom/etc
      touch \$newDom/etc/php.ini
      chown \$domUser:psacln \$newDom/etc/php.ini
      
      cat <<EndOF > \$newDom/conf/vhost.conf
      ###mt-opt - comment the following lines to disable mod_suphp for this domain
      suPHP_Engine On
      suPHP_UserGroup \$domUser psacln
      suPHP_ConfigPath \$newDom/etc
      ###mt-opt
      EndOF
      
      /usr/local/psa/admin/sbin/httpdmng --reconfigure-all
      /etc/init.d/httpd stop
      /etc/init.d/httpd start
      EOF
      
      • chmod the script
      chmod 755 /usr/local/psa/admin/sbin/suphp_subdomain_add.sh
      
      • insert the script as an event handler in Plesk
      mysql -u'admin' -p`cat /etc/psa/.psa.shadow` psa -e"insert into event_handlers values(default,(select id from actions where descr='Create Subdomain'),0,'root','/usr/local/psa/admin/sbin/suphp_subdomain_add.sh <new_domain_name> <new_subdomain_name> <new_system_user>');"
      
    4. Script to handle adding changing subdomains:
      • create the script
      cat <<EOF > /usr/local/psa/admin/sbin/suphp_subdomain_change.sh
      #!/bin/bash
      newDom=/var/www/vhosts/\$1/subdomains/\$2
      domUser=\$3
      
      mkdir \$newDom/etc
      chown \$domUser:psacln \$newDom/etc
      touch \$newDom/etc/php.ini
      chown \$domUser:psacln \$newDom/etc/php.ini
      
      cat <<EndOF > \$newDom/conf/vhost.conf
      ###mt-opt - comment the following lines to disable mod_suphp for this domain
      suPHP_Engine On
      suPHP_UserGroup \$domUser psacln
      suPHP_ConfigPath \$newDom/etc
      ###mt-opt
      EndOF
      
      /usr/local/psa/admin/sbin/httpdmng --reconfigure-all
      /etc/init.d/httpd stop
      /etc/init.d/httpd start
      EOF
      
      • chmod the script
      chmod 755 /usr/local/psa/admin/sbin/suphp_subdomain_change.sh
      
      • insert the script as an event handler in Plesk
      mysql -u'admin' -p`cat /etc/psa/.psa.shadow` psa -e"insert into event_handlers values(default,(select id from actions where descr='Update Subdomain'),0,'root','/usr/local/psa/admin/sbin/suphp_subdomain_change.sh <new_domain_name> <new_subdomain_name> <new_system_user>');"
      
  6. Since PHP scripts will now be running as the domain user rather than apache, the permissions on the sessions folder need updated to allow for this:
    chmod 1777 /var/lib/php/session
    
  7. Now that the server is ready to handle any new content that will be added, existing domains and subdomains need updated to include correct permissions and suPHP directives. These commands are very lengthy and are designed to set everything in one run.
    • Configure existing domains for suPHP
    mysql -u'admin' -p$(cat /etc/psa/.psa.shadow) -Ns psa -e"select name,www_root,login,home from domains join \
    hosting on domains.id=hosting.dom_id join sys_users on sys_users.id=hosting.sys_user_id;" | \
    while read x; do
    domName=`echo $x | awk '{print $1}'`
    wwwRoot=`echo $x | awk '{print $2}'`
    domUser=`echo $x | awk '{print $3}'`
    userRoot=`echo $x | awk '{print $4}'`
    domPath="/var/www/vhosts/$domName"
    
    chown -R $domUser:psacln $wwwRoot
    chgrp psaserv $wwwRoot
    [ -d $domPath/etc ] || mkdir $domPath/etc
    chown $domUser:psacln $domPath/etc
    touch $domPath/etc/php.ini
    chown $domUser:psacln $domPath/etc/php.ini
    
    if ! echo $wwwRoot | grep -q "^/var/www/vhosts/$domName/"; then
    [ -d $userRoot/other_domains_etc ] || mkdir $userRoot/other_domains_etc
    [ -h $userRoot/other_domains_etc/$domName ] && rm -f $userRoot/other_domains_etc/$domName
    ln -s $domPath/etc $userRoot/other_domains_etc/$domName; fi
    
    touch $domPath/conf/vhost.conf
    perl -0 -p -i -e 's/^\#\#\#mt-opt(\n|[^\n])+?\#\#\#mt-opt\n?//g' $domPath/conf/vhost.conf
    cat <<EndOF >> $domPath/conf/vhost.conf
    ###mt-opt - comment the following lines to disable mod_suphp for this domain
    suPHP_Engine On
    suPHP_UserGroup $domUser psacln
    suPHP_ConfigPath $domPath/etc
    ###mt-opt
    EndOF
    done
    
    • Configure existing subdomains
    mysql -u'admin' -p$(cat /etc/psa/.psa.shadow) -Ns psa -e"select domains.name,subdomains.name,login,subdomains.www_root from domains join \
    subdomains on domains.id=subdomains.dom_id join sys_users on sys_users.id=subdomains.sys_user_id;" | \
    while read x; do
    domName=`echo $x | awk '{print $1}'`
    subName=`echo $x | awk '{print $2}'`
    domUser=`echo $x | awk '{print $3}'`
    wwwRoot=`echo $x | awk '{print $4}'`
    domPath="/var/www/vhosts/$domName/subdomains/$subName"
    
    chown -R $domUser:psacln $wwwRoot
    chgrp psaserv $wwwRoot
    [ -d $domPath/etc ] || mkdir $domPath/etc
    chown $domUser:psacln $domPath/etc
    touch $domPath/etc/php.ini
    chown $domUser:psacln $domPath/etc/php.ini
    
    touch $domPath/conf/vhost.conf
    perl -p -n -i -e 's/^\#\#\#mt-opt(\n|[^\n])+\#\#\#mt-opt\n?//g' $domPath/conf/vhost.conf
    cat <<EndOF >> $domPath/conf/vhost.conf
    ###mt-opt - comment the following lines to disable mod_suphp for this domain
    suPHP_Engine On
    suPHP_UserGroup $domUser psacln
    suPHP_ConfigPath $domPath/etc
    ###mt-opt
    EndOF
    done
    
  8. With everything now configured, the vhost.conf files that have been added for each VirtualHost now need loaded into Apache:
    /usr/local/psa/admin/sbin/httpdmng --reconfigure-all
    
    /etc/init.d/httpd restart
    

The (dv) Dedicated-Virtual is now set to use mod_suphp to handle all PHP code for your domains!