Lighttpd 1.5 and PHP (Uber-Uploader too)

Lighttpd is awesome, but 1.4.18 broke the upload progress bar on my file-sending site. After extensive research, I figured out that moving to the unreleased 1.5 version was the solution.

There’s no centralized documentation for getting PHP working with 1.5, so read below to find out how to do it. I’ll also include my experience with Uber-Uploader.

Apache played nicely with UU, but it chokes (hits MaxClients and stops responding) on huge file downloads sent by PHP. Lighttpd solves my problem in two places — it doesn’t choke and it comes with a very smart way to send downloads from scripts.

Unfortunately, since it uses fcgi, it breaks Uber-Uploader. UU’s perl upload script accepts the file in chunks and writes to a status file, which is read by an AJAX-y progress bar. Lighttpd waits for the entire file before passing any to UU.

I figured I’d proxy to Apache for the perl script, then when that didn’t work I tried running everything through Apache and proxying the downloads to lighttpd. Don’t bother. Very frustrating.

So, setting up 1.5 with PHP…

The example lighttpd.conf file included with the source uses a deprecated key that will give you an error on startup.

Here’s how the fastcgi section of your /etc/lighttpd/lighttpd.conf should look.


#### fastcgi module
## read fastcgi.txt for more info
## for PHP don't forget to set cgi.fix_pathinfo = 1 in the php.ini
$PHYSICAL["existing-path"] =~ "\.php$" {
proxy-core.balancer = "round-robin"
proxy-core.allow-x-sendfile = "enable"
# proxy-core.check-local = "enable"
proxy-core.protocol = "fastcgi"
proxy-core.backends = ( "unix:/tmp/php-fastcgi.sock" )
proxy-core.max-pool-size = 16
# proxy-core.rewrite-request = (
# "_pathinfo" => ( "\.php(/.*)" => "$1" )
# )
}

The “check-local” line gives me an error when uncommented. The rewrite-request line is presumably to ensure that GET requests work, but everything works for me with these lines commented.

And like they say in the comment there, don’t forget to add the cgi.fix_pathinfo key to your php.ini.

Here’s the big one. No one tells you to set up fcgi-spawn. You have to run this command before you start lighttpd.

# /usr/bin/spawn-fcgi -s /tmp/php-fastcgi.sock -f /usr/bin/php-cgi -u lighttpd -g lighttpd -C 5 -P /var/run/spawn-fcgi.pid

You can do it manually to try it out, or modify your /etc/init.d/lighttpd like this.


start() {
echo -n $"Starting $prog: "
daemon $lighttpd -f $LIGHTTPD_CONF_PATH
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog
/usr/bin/spawn-fcgi -s /tmp/php-fastcgi.sock -f /usr/bin/php-cgi -u lighttpd -g lighttpd -C 5 -P /var/run/spawn-fcgi.pid
return $RETVAL
}
stop() {
echo -n $"Stopping $prog: "
killproc $lighttpd
killproc php-cgi
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog
[ -f /tmp/php-fastcgi.sock ] && /bin/rm -f /tmp/php-fastcgi.sock || :
[ -f /var/run/spawn-fcgi.pid ] && /bin/rm -f /var/run/spawn-fcgi.pid || :
return $RETVAL
}

Maybe because I’m running CentOS, spawn-fcgi is in /usr/local/bin/spawn-fcgi. If you’re getting an error, try typing “which spawn-fcgi” to see where it is on your server. Check for Ubuntu, Red Hat, Debian, Gentoo, etc.

To get Uber-Uploader working again, just add this to your /etc/lighttpd/lighttpd.conf.

server.network-backend = "writev"

As for the super-smart way to send downloads…

Running a file-hosting site, you can’t just use direct links. Then any popular file could bankrupt you. However tight or loose, you need control over the downloads.

I had a PHP script that would load the file and send it to a user authorized to download. It was presumably memory-efficient, sending the file in chunks, but in reality it killed Apache. That’s because each prefork process can serve a huge PHP request and get bloated, then serve a tiny image while another process serves a monster PHP request and gets bloated. Rinse and repeat.

Instead, you can have PHP send a header with the local filename and user-facing filename that will be intercepted by lighttpd. Then, as long as it can access the file, it’ll send it. As they put it, why use PHP to send static files when that’s lighttpd’s specialty? It’s called X-Sendfile.

Hope you find this useful. I struggled for a few hours to find all this info, but it’s worth it.

Lighttpd slaughters Apache for my purposes, and probably for yours.

Spawn-fcgi
Uber-Uploader forum thread on lighttpd
Lighttpd download headers: X-Sendfile

One thought on “Lighttpd 1.5 and PHP (Uber-Uploader too)”

Comments are closed.