Usually ignored features of suPHP

This is not a generic suPHP tutorial as there are many, many of them already; it is merely an attempt to debunk commonly preached misinformation regarding suPHP with cold, hard facts.

suPHP Also works with Lighttpd

suPHP does not just consist of the Apache module mod_suphp; it also consists of a setuid root binary (located at /usr/local/sbin/suphp on FreeBSD; /usr/lib/suphp/suphp on recent Ubuntu releases) which does the actual work. mod_suphp is just an interface to this binary. The binary also works with lighttpd provided you use a configuration file in lighttpd such as the following:

server.modules += ( "mod_setenv" ) # Load Env
server.modules += ( "mod_cgi" ) # Load CGI
$HTTP["url"] =~ ".php|\/$" { # match .php files
setenv.add-environment = (
"SUPHP_HANDLER" => "application/x-httpd-php"
)
}
$HTTP["url"] =~ ".pl|.py|.cgi$" { # Also handle normal CGI scripts
setenv.add-environment = (
"SUPHP_HANDLER" => "x-suphp-cgi"
)
}
cgi.assign = ( # Actually use suphp
".pl" => "/usr/local/sbin/suphp",
".py" => "/usr/local/sbin/suphp",
".cgi" => "/usr/local/sbin/suphp",
".php" => "/usr/local/sbin/suphp"
)

Make sure the path to the suphp binary is correct and the mimetypes match those specified in the main suphp.conf file.

With regards to the “$HTTP[“url”] =~ “.php|\/$” {” line, the “|\/” part is so it matches calling folders with index.php inside of them, for example http://domain.com instead of http://domain.com/index.php because lighttpd’s $HTTP[“url”] variable is exactly the URL passed to the sever and not the file that the web server determines you really requested. From what I recall, in a future version of lighttpd the $HTTP[“file”] variable will exist to point to the requested file so this kludge with specifically matching the directory will no longer be needed.

suPHP can also handle CGI scripts and binaries

suPHP is a third party-developed program that was partially intended to be a drop in replacement for Apache’s built in suEXEC module, as well as being better for PHP than just running it as CGI with suEXEC. It also easily lends itself to supporting Perl/Python/Ruby and other CGI scripts as well as CGI binaries themselves (such as git-httpd-backend). This is done with this excerpt of the suphp.conf file:


x-suphp-cgi="execute:!self"

You also need these lines in part of your Apache configuration (or the last two blocks at the end of my lighttpd excerpt above):


<FilesMatch "\.(pl|py|cgi)$">
SetHandler x-suphp-cgi
</FilesMatch>
suPHP_AddHandler x-suphp-cgi

I use the above FilesMatch method instead of “AddType x-suphp-cgi .pl .py .cgi” because using AddType appears to give warnings saying it can’t find the proper mime type or something similar for “x-suphp-cgi”. It’d be cool if someone could find a work around for that.

suPHP can automatically syntax highlight .phps files

It can, you just need these lines in your Apache configuration, and make sure the path goes to the normal CLI php binary, rather than the php-cgi binary.


suPHP_PHPPath /usr/local/bin/php
AddType application/x-httpd-php-source .phps

You do not, however, need to use a suPHP_AddHandler line for that mimetype because suPHP apparently autoamtically looks for it and adding a suPHP_AddHandler directive breaks its functionality.

suPHP can run scripts as root

It can, provided you se these values in the suphp.conf file:


min_uid=0
min_gid=0

The same file/folder ownership and permissions restrictions apply, except this time for the user `root` itself. eg, keep files at root:root 644 and folders at root:root 755. This can be useful for things such as PHP alternatives to cPanel/WHM, but please be aware that if the script you’re designating to run as root has security vulnerabilites that can be exploited, your entire server is at the mercy of the attacker since he/she has root access. However, the same applies if you were using a Perl based server manager if that ran as root as well. The main matter here is to make sure you only run scripts that you 110% trust and keep updated.

suPHP compared, speed-wise, to mod_php

The difference in speed between suPHP and mod_php is the result of additional foring. With each suPHP page request, the web server forks a call to the suphp binary I mentioned earlier which uses the setuid/setgid system calls to become the user owning the script and then forks again to run the script. mod_php has PHP loaded into Apache itself so with each PHP page request it just runs the script on the fly without needing to fork an additional external process specifically to handle the PHP script.

This means that the speed difference is just due to forking. If you have a script that runs extremely slow under suPHP due to MySQL queries or intense number crunching/text parsing, it will likely run just as slow under mod_php since forking is not the bottle neck at that point.

This concept applies similarly to using PHP with mod_fastcgi except that fastcgi keeps a number of worker php processes running 24/7 and assigns the current PHP page request to each one randomly to balance the load, rather than having the web server itself run the script directly.

It is possible to run suPHP at the same time as mod_php/mod_fastcgi

You can, provided you use different MIMETYPES (the application/whatever part related to the Apache handlers) and you can set up each virtual host to use a different one within the VirtualHost settings block. While doing this set up is largely nonsensical, I feel it’s better to know that it is indeed doable rather than just blindly assuming it it’s impossible.

Fixing a dpkg io error

I encountered a dpkg related error a little while ago while upgrading packages on my Ubuntu Lucid server. I couldn’t find a fix on the internet and spent a little while investigating the cause. You can see from the command output that dpkg failed to properly install the Linux kernel package:

root@aeroplane:~# apt-get dist-upgrade
Reading package lists... Done
Building dependency tree
Reading state information... Done
Calculating upgrade... Done
The following packages will be upgraded:
linux-image-2.6.32-33-generic
1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
3 not fully installed or removed.
Need to get 0B/31.6MB of archives.
After this operation, 0B of additional disk space will be used.
Do you want to continue [Y/n]? y
(Reading database ... 178303 files and directories currently installed.)
Preparing to replace linux-image-2.6.32-33-generic 2.6.32-33.70 (using .../linux-image-2.6.32-33-generic_2.6.32-33.71_i386.deb) ...
Done.
Unpacking replacement linux-image-2.6.32-33-generic ...
dpkg-deb: subprocess paste killed by signal (Broken pipe)
dpkg: error processing /var/cache/apt/archives/linux-image-2.6.32-33-generic_2.6.32-33.71_i386.deb (--unpack):
short read in buffer_copy (backend dpkg-deb during `./lib/modules/2.6.32-33-generic/kernel/drivers/ata/sata_mv.ko')
No apport report written because the error message indicates a dpkg I/O error
Running postrm hook script /usr/sbin/update-grub.
Generating grub.cfg ...
Found initrd image: /boot/initrd.img-2.6.32-33-generic
Found linux image: /boot/vmlinuz-2.6.32-32-generic
Found initrd image: /boot/initrd.img-2.6.32-32-generic
Found linux image: /boot/vmlinuz-2.6.32-31-generic
Found initrd image: /boot/initrd.img-2.6.32-31-generic
Found linux image: /boot/vmlinuz-2.6.32-30-generic
Found initrd image: /boot/initrd.img-2.6.32-30-generic
Found linux image: /boot/vmlinuz-2.6.32-29-generic
Found initrd image: /boot/initrd.img-2.6.32-29-generic
Found linux image: /boot/vmlinuz-2.6.32-28-generic
Found initrd image: /boot/initrd.img-2.6.32-28-generic
Found linux image: /boot/vmlinuz-2.6.32-27-generic
Found initrd image: /boot/initrd.img-2.6.32-27-generic
Found linux image: /boot/vmlinuz-2.6.32-26-generic
Found initrd image: /boot/initrd.img-2.6.32-26-generic
Found linux image: /boot/vmlinuz-2.6.32-25-generic
Found initrd image: /boot/initrd.img-2.6.32-25-generic
Found linux image: /boot/vmlinuz-2.6.32-24-generic
Found initrd image: /boot/initrd.img-2.6.32-24-generic
Found linux image: /boot/vmlinuz-2.6.32-21-generic
Found initrd image: /boot/initrd.img-2.6.32-21-generic
Found memtest86+ image: /boot/memtest86+.bin
done
Errors were encountered while processing:
/var/cache/apt/archives/linux-image-2.6.32-33-generic_2.6.32-33.71_i386.deb
E: Sub-process /usr/bin/dpkg returned an error code (1)
root@aeroplane:~#

Somehow the package archive file /var/cache/apt/archives/linux-image-2.6.32-33-generic_2.6.32-33.71_i386.deb became corrupt. Cleaning the local cache of deb packages and then upgrading again fixed the issue:

root@aeroplane:~# apt-get clean
root@aeroplane:~# apt-get dist-upgrade