Oxford website design and web developers
  • Home
  • Why Akriga?
  • Testimonials
  • Services
    • Technology for Marketing
    • Technology for Operations
  • Case Studies
  • News & Views
  • Contact
  • Blog
  • Search
  • Menu Menu

suexec php fcgi vhost on Apache 2.x

Introduction

This article is about setting up Apache to run PHP as a particular user (suexec), in a virtual hosting environment (vhost) and mitigating the performance hit from doing so (fcgi).
The article is aimed at web developers and webmasters who want to run PHP scripts more securely, do not want to recompile suexec and have sites hosted under user accounts within /home/.
The method shown here allows you to run PHP as an Apache module whilst also running it over CGI.
The article does not cover suphp or mod_fastcgi.
Spare me the web developer back-story, just show me how to get PHP, suexec and mod_fcgi working together.

Why suexec, php and fcgi?

What problem are we trying to solve? Short answer: security + performance. Long answer: When we started as web developers in late 1999 we were using perl and the Common Gateway Interface (CGI) protocol to deliver interactive websites. Apache allowed perl scripts to run as a particular user which meant that permissions for those scripts could be locked down to 700. In other words only that user could access those scripts. Web developers eventually turned to PHP and the most common way to run PHP was as a module (mod_php.so) which meant PHP scripts ran as an unprivileged user – typically www-data.
Consequently, PHP scripts and the directories they wrote to had to have less restrictive security permissions. Directories are normally set to 777 and the scripts themselves 644. This is true of all the well-known open source PHP project like Joomla, WordPress, Drupal, Plogger, OSCommerce, Zencart, Moodle, etc. Not only were directories world writeable but any script containing a password was now world-readable.
With the large scale adoption of Apache virtual hosting there were lots of sites, belonging to lots of users on one machine and their files were now readable by other users.
Lots of web developers would like to run PHP as a particular user, “suexec” with its tighter permissions model but it is not a common setup despite many articles on the subject. There is definitely a performance hit when running PHP with suexec. To overcome this web developers/sys admins also run PHP scripts using the FastCGI protocol; the Apache implementation of which is called mod_fcgid.

Why this article?

Does the web need another article on this? In my experience yes, all the guides I read on the web did not work for me, YMMV. Many guides require you to recompile suexec and this is not necessary. Others used fastcgi and I wanted to use fcgid because I knew and trusted the Apache brand. There are also differences between distros and versions across the same distro. I’ll be using Debian 6.0 (Lenny) for this article and indicating what changes are required for Debian 5.0 (Etch).

Software installation


apt-get install php5-cgi libapache2-mod-fcgid apache2-suexec apache2-suexec-custom

Once installed you can enable fcgid & suexec:


a2enmod fcgid ##may be enabled by dflt after install but requires a restart!
a2enmod suexec

Apache configuration


more /etc/apache2/mods-enabled/fcgid.conf
shows:

AddHandler fcgid-script .php
# AddHandler fcgid-script .fcgi
FcgidConnectTimeout 20 #IPCConnectTimeout on Lenny
FCGIWrapper /usr/bin/php5-cgi .php
# FCGIWrapper /usr/bin/php5-cgi .fcgi


more /etc/apache2/mods-enabled/php5.conf
shows

SetHandler application/x-httpd-php

SetHandler application/x-httpd-php-source

# To re-enable php in user directories comment the following lines
# (from to .) Do NOT set it to On as it
# prevents .htaccess files from disabling it.

php_admin_value engine Off


Do a restart and check everything is still ok … at the command line execute:

/etc/init.d/apache2 restart

The above 2 changes needs to be made at the same time, doing fcgid alone will break things!

Custom suexec

By installing Debian’s very handy apache2-suexec-custom we do not have to recompile suexec which, by default, wants to run under /var/www. Like most web developers using vhosting we want to run under /home/username. At the command line execute:


/usr/lib/apache2/suexec -V

which shows where the configuration directory is & where errors will be logged to:


D SUEXEC_CONFIG_DIR=/etc/apache2/suexec/
-D AP_GID_MIN=100
-D AP_LOG_EXEC="/var/log/apache2/suexec.log"
-D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin"
-D AP_UID_MIN=100

The first line tells us we need to create


more /etc/apache2/suexec/testsuexec

(where testsuexec is our username) to look like this, which allows us to run out of /home instead of the default /var/www.


/home
htdocs/cgi-bin
# The first two lines contain the suexec document root and the suexec userdir
# suffix. If one of them is disabled by prepending a # character, suexec will
# refuse the corresponding type of request.
# This config file is only used by the apache2-suexec-custom package. See the
# suexec man page included in the package for more details.

Site configuration

Everything up to this point is a one-time, initial set-up task. The remaining configuration is done on a per site basis.

Directory layout

directory layout for suexec php fcgi
/home/user/domain/htdocs is your document root.
php-fcgi-wrapper is a shell script that contains fcgi parameters and kicks off your php5-cgi binary.
php.ini lives in a conf directory outside the document root & holds any values formerly in .htaccess
prepend.php any php code your web app needs to execute to initialise itself.

Wrapper script


more php-fcgi-wrapper
#!/bin/sh
# Wrapper for PHP-fcgi
# This wrapper can be used to define settings before launching the PHP-fcgi binary.
# Define the path to php.ini. This defaults to /etc/phpX/cgi.
PHP_INI_SCAN_DIR=/home/user/domain/conf
export PHP_INI_SCAN_DIRexport PHPRC=/home/user/domain/conf# Define the number of PHP child processes that will be launched.
# This is low to control memory usage on a server that might launch
# these processes for lots of domains.
# Leave undefined to let PHP decide.
export PHP_FCGI_CHILDREN=1# Maximum requests before a process is stopped and a new one is launched
export PHP_FCGI_MAX_REQUESTS=5000# Launch the PHP CGI binary
# This can be any other version of PHP which is compiled with FCGI support.
exec /usr/bin/php5-cgi
#exec /your/own/compiled/version/bin/php-cgi

Vhost

These are Apache directives that live in /etc/apache2/sites-available/domain.conf:


DocumentRoot /home/user/domain/htdocs
ServerName www.domain.com
SuexecUserGroup user users

# SetHandler application/x-httpd-php
SetHandler fcgid-script

php_admin_flag engine off
AddHandler fcgid-script .php
AddHandler fcgid-script .php5
FcgidConnectTimeout 20
#FCGIWrapper /usr/bin/php5-cgi .php
FCGIWrapper /home/user/domain/htdocs/cgi-bin/php5-default/php-fcgi-wrapper .php
allow from all
Options +Indexes +ExecCGI
ErrorLog /home/user/domain/logs/error_log
LogLevel debug
CustomLog /home/user/domain/logs/access_log “combined”

After you’ve done this, restart Apache.
Note: file ownership and groups must match SuexecUserGroup user users line above.
Permissions can be 600

Approach

Do suexec last.
Get fcgid working first, if you have problems getting it to work with .php files start with .fcgi file extension.

Testing & Debugging

Create a simple first script called first.php that contains:



The first line will output which user the script is running as, it should be user from our example above, if its www-data something has gone wrong. Usually you are still running mod_php.so & you’ve yet to pick up your changes – have you restarted Apache?

In the output from phpinfo() you should see:

Server APICGI/FastCGI

A common error is to have first.php served as a download. This indicates mod_php.so is not being run (good!) but php-cgi cannot be found (bad!). Check FCGIWrapper directive in Apache vhost conf file.
500 Internal server errors are typically indicate a suexec permissions problem, look in
/var/log/apache/suexec.log
for error messages about permissions.

php.ini

If you make changes, e.g. to php.ini you must:

killall php-cgi
or
killall php5-cgi
otherwise your tests will connect with existing fcgid processes which have your old values.
If phpinfo() does not show your correct php.ini settings there is likely a syntax error in the .ini file. Typically caused by missing = and double quotes in path information where .htaccess style is used.

  • pink floyd pig over battersea power stationSEO & Support for SME businessApril 11, 2019 - 1:06 pm
  • pipettes in a laboratoryWeb development for “Big Pharma”April 10, 2019 - 2:24 pm
  • Orange motorcycle on a green and grassy bywayTrail Riders FellowshipMarch 1, 2019 - 2:40 pm
  • Goodmans filed horse sculpture by Hamish MackieHamishmackie.comMarch 1, 2019 - 2:35 pm

Categories

  • Blog
  • Client Sites
  • Development
  • News
  • SEO
  • Testimonials
  • Wordpress

CONTACT

  • hello@akriga.com
  • +44 (0)1235 521909
  • Akriga Ltd, 142 South Avenue Abingdon, Oxfordshire OX14 1QY
  • Home
  • Why Akriga?
  • Testimonials
  • Services
  • Case Studies
  • News & Views
  • Contact
  • Privacy Policy
  • LinkedIn
Copyright © 2021 · Akriga Ltd Registered in England and Wales
Company No. 4138178. Vat No. 792 6759 69.
Email problem – host refused to talk to me – error 554 CiviCRM and membership
Scroll to top

This site uses cookies. By continuing to browse the site, you are agreeing to our use of cookies.

OKPrivacy policy

Cookie and Privacy Settings



How we use cookies

We may request cookies to be set on your device. We use cookies to let us know when you visit our websites, how you interact with us, to enrich your user experience, and to customize your relationship with our website.

Click on the different category headings to find out more. You can also change some of your preferences. Note that blocking some types of cookies may impact your experience on our websites and the services we are able to offer.

Essential Website Cookies

These cookies are strictly necessary to provide you with services available through our website and to use some of its features.

Because these cookies are strictly necessary to deliver the website, refuseing them will have impact how our site functions. You always can block or delete cookies by changing your browser settings and force blocking all cookies on this website. But this will always prompt you to accept/refuse cookies when revisiting our site.

We fully respect if you want to refuse cookies but to avoid asking you again and again kindly allow us to store a cookie for that. You are free to opt out any time or opt in for other cookies to get a better experience. If you refuse cookies we will remove all set cookies in our domain.

We provide you with a list of stored cookies on your computer in our domain so you can check what we stored. Due to security reasons we are not able to show or modify cookies from other domains. You can check these in your browser security settings.

Google Analytics Cookies

These cookies collect information that is used either in aggregate form to help us understand how our website is being used or how effective our marketing campaigns are, or to help us customize our website and application for you in order to enhance your experience.

If you do not want that we track your visit to our site you can disable tracking in your browser here:

Other external services

We also use different external services like Google Webfonts, Google Maps, and external Video providers. Since these providers may collect personal data like your IP address we allow you to block them here. Please be aware that this might heavily reduce the functionality and appearance of our site. Changes will take effect once you reload the page.

Google Webfont Settings:

Google Map Settings:

Google reCaptcha Settings:

Vimeo and Youtube video embeds:

Other cookies

The following cookies are also needed - You can choose if you want to allow them:

Privacy Policy

You can read about our cookies and privacy settings in detail on our Privacy Policy Page.

Accept settingsHide notification only