Simple Debian Squeeze LAMP Config

Want the instant gratification solution?  Scroll down to “All In One” below.

Several of the Linux (Debian Squeeze) / Apache2 / MySQL / PHP (LAMP) configs I’ve seen on the ‘net include complexity you just don’t need (like suEXEC or suPHP).  If you’re setting up a basic server (physical, VPS, Xen, OpenVZ, whatever) and you’re going to be the only person running it, then setting up a LAMP environment is trivial.

This post assumes your server boots and you can log in and that it’s a basic Squeeze install with none of the relevant software pre-installed.  I hate sudo, so I’m going to assume you have either su’d to root (su – root) or that you’ve switched to root via sudo (sudo su – root).  If not, you’ll need to prefix all of these commands with sudo (after setting sudo up).

Although this little guide is for Debian, I think it’ll work unchanged on Ubuntu as well.  This guide also assumes that your server hosts a single website, so nothing fancy with any Apache2 VirtualHosts.

All of the follow steps can be combined, but I like to install by stages so that I can test each element on it’s own, and not get overwhelmed.

One of the big mistakes people new to Debian or Ubuntu do, is they think they have to manually edit config files to get things working.  The Debian packagers spend a lot of time making Debian packages work properly with each other with the absolute minimum manual effort.

Install Apache2

While Apache2 might be a bloated-warthog in the eyes of some system administrators, it’s ubiquitous, reliable, feature rich, well documented and well supported.  You can play with lighttpd, nginx and other options later, but this is LAMP, so let’s install the A.

The default Apache2 install on Debian will try and use the Worker MPM for Apache2.  We want the Prefork MPM when we use PHP5 later, so we’ll specify that straight away.

apt-get install apache2 apache2-mpm-prefork

And that’s it.  Assuming that runs successfully (errors are outside the scope of this walkthrough), you should be able to connect to the web server of your server on port 80 (iptables is also outside the scope of this, but a blank Debian install won’t have any firewalling in the way anyway).

If the install worked, connecting should return a page which says “It works!” and some information about this being the default web page.

Install PHP

Again, PHP gets bad press these days and maybe rightly so, but again it’s well used, well supported and well understood.  It’s probably easier to install it along with Apache2 in reality, because Debian does all the post config work at once then, but if you do it later, you are at least in control of the various stages.

We need to install two things, PHP5 and the Apache2 PHP module (on Debian, this package is libapache2-mod-php).

apt-get install php5 libapache2-mod-php5

and then restart Apache2 (I use the following command, any method that reloads the Apache2 config file works)

/etc/init.d/apache2 restart

That’s it.  You don’t need to edit anything, enable anything, configure anything.  Debian handles all that for you.  The default install of Apache2 creates a /var/www directory which it uses as the root for your web site.  If you go to that directory and create a file called test.php, and put this into it,

<?php phpinfo(); ?>

You can then test the PHP5 install has worked by connecting to your web server and requesting the file test.php.  If it asks you to save it, something went wrong (or you didn’t restart Apache2), otherwise you should get a full list of the PHP settings.

NB: Debian installs Suhosin by default.  This should be okay, but it can cause issues with some features of WordPress and phpMyAdmin.

Install MySQL

The MySQL install is the most complex, because you’ll have to create a password!  Otherwise, it’s as simple as the above steps.  As well as MySQL we need to remember to install the PHP5 MySQL module, otherwise we won’t be able to interact with the database.

apt-get install mysql-server php5-mysql

After some packages are downloaded and installed, you’ll be asked to set a password for the MySQL root user.  The dialog says this is not mandatory.  I think it should be.  You should absolutely set this password.  It does not need to match the Linux root user password, and as in all cases, it should actually differ significantly.

Restart Apache2 for good measure, and you’re done.  MySQL will be started, the relevant libraries are installed, and Apache2 / PHP5 / MySQL can all communicate as required.

By default, MySQL won’t be listening on any external interfaces, which is a good thing, so only your website can communicate with it.  Some guides recommend installing phpMyAdmin at this point, and you can if you want, although I prefer not to.

Permissions

In a default Debian install, Apache2 and PHP5 run as the www-data user.  By default, the permissions on /var/www are

drwxr-xr-x root root

That means the web server can’t create any files or directories in /var/www.  That’s a problem when installing things like WordPress which want to create their own config files or .htaccess files.  Because we’re not worried about multiple users on our server, or different customers, it’s safe to set the owner of /var/www to www-data:www-data, and do the same for all files in that directory.  This advice is only true for a server where you don’t mind all the websites running as the same user, but that’s the point of this example anyway!

All In One

The following command will install the whole thing in one go, and all you need to do is set the MySQL password.

apt-get install apache2 apache2-mpm-prefork php5 libapache2-mod-php5 mysql-server php5-mysql

Follow Up Steps

Later on you might want to install additional PHP modules (such as php5-curl, php5-gd, php5-mcrypt), and for sites which you expect to be busy on servers with not much memory you might want to look at using apache2-mpm-worker and FastCGI.

Debian, apache2, virtualhosts, FastCGI and PHP5

I’ve spent an amusing evening revisiting FastCGI under Apache2, in order to server PHP5 content through Apache’s threaded MPM (worker).  I set this up ages ago on my previous web server and then forgot about it.

It was fine for a long time, but I hadn’t really customised it and to be frank, wasn’t really sure what it was doing.  I just know at the time it was very confusing reading a lot of conflicting stuff on the web.  But it worked.  Until recently, when I noticed the server was running out of memory and processes were being killed.  I didn’t really spend much time looking at the cause though.

When I moved to the new server, I thought I’d try out the prefork MPM again, as per my previous posts and it seemed okay.  However, it’s not okay (although I may do some more load testing if I get a chance).  So I quickly switched back to the worker MPM and FastCGI.

Which is where I started getting frustrated again – I wanted to understand better what’s going on with FastCGI and make sure I was handling it correctly.

If you search the web, there’s a lot of stuff, much of it from 2007 – 2009 with conflicting information and stuff you might or might not need to do.

So, first some caveats,

  1. this is Debian Squeeze, other distributions might be different.
  2. I run PHP5 under FastCGI and nothing else, so my config changes only affect PHP5.
  3. I’m guessing about most of this stuff – so if I’m wrong, please feel free to provide constructive comments.

Here’s what I learned.

Two FastCGI Modules?

Debian comes with two FastCGI modules, those being libapache2-mod-fcgid and libapache2-mod-fastcgi.  They are binary compatible, I’m lead to believe, but fcgid is newer and works better with suexec.  So you should use libapache2-mod-fcgid unless you know you need libapache2-mod-fastcgi for some specific reason.  If you read examples talking about libapache2-mod-fastcgi you can probably just use libapache2-mod-fcgid instead.

Don’t install them both at once – you can do, but there’s no point and it’ll only cause confusion.  You only need one.

Some Fcgid settings are per virtual host.

I run with a low memory setup, so I wanted the PHP5 processes to shut down after a while, rather than hang around.  I couldn’t work out why they weren’t going away.  Also, I couldn’t work out why there were so many.  But it looks to me like you get at least one PHP5 process per virtual host, sometimes more (if the load is high, but remember, these are mostly vanity VPS’s, low load).  The default settings for fcgid processes is to start with none, and create as many as needed, and then drop back to 3.  But it looks like with the way I’ve got it configured (maybe all ways), that’s per virtual host.  I had to set the FcgidMinProcessesPerClass to be 0, so that on each virtual host, fcgid will close all the unused PHP5 processes after a while.

Wrappers?

Most of the articles online suggest you write a little wrapper to launch your PHP5 stuff via Fast CGI.  I couldn’t remember doing that on the previous server and spent a while looking for my wrapper script – until I realised I’d not created one.  You don’t need a wrapper script, but you do need to tell your virtual host to run PHP5 code using the Fast CGI module.  I have this in each of my virtualhost Apache2 config sections.

AddHandler fcgid-script .php
FCGIWrapper /usr/lib/cgi-bin/php5 .php
Options ExecCGI

You need to add the ExecCGI to the Options directive to ensure the PHP pages can be run as CGI apps, and the Handler and FCGIWrapper lines tell Apache2 how to run the PHP.  The default wrapper is just the PHP5 CGI binary (as shown above).  You can put a shell script there and set some defaults, but you don’t have to, it ran fine for over a year on my other server without doing so.

You can set values in fcgid.conf

Because I’m only running PHP5 stuff via Fast CGI, I can happily put settings in Apache’s fcgid.conf file.  Some articles suggest creating a PHP specific one, and putting the wrapper script stuff above in that as well.  I’m sure that works, but so does the way I did it (there’s always more than one way!).  Here’s my fcgid.conf,

<IfModule mod_fcgid.c>
 AddHandler    fcgid-script .fcgi
 FcgidConnectTimeout 20
 FcgidIOTimeout              60
 FcgidMaxRequestsPerProcess  400
 FcgidIdleTimeout            60
 FcgidMinProcessesPerClass   0
</IfModule>

The two Timeout entries ensure unused PHP5 processes are closed down.  The MinProcessesPerClass is required as mentioned above, otherwise it defaults to 3 per virtualhost.  The MaxRequestsPerProcess I’ve set at 400.  PHP will by default handle 500 and then shutdown, it can do that even if Fast CGI has already made a connection, resulting in a 500 error at the client.  If you force Fast CGI to stop PHP after <500 requests, you avoid that issue.  You can if you want write a PHP Wrapper script, and increase PHP’s max requests value, but you don’t have to.

There’s always another way

This is one way of setting it up, there’s always another way, and with Linux there’s usually another 10 ways.  I may do some more testing to narrow down some confusion I still have and see what the benefits of wrapper scripts may or may not be, and whether it’s worth moving some of the per-virtualhost config entries into the fcgid.conf file (like the handler bits).

WordPress Plugins

Wrote my first WordPress plugin today (for www.bookthing.co.uk), it’s a pretty simple plugin architecture especially if you’re not trying to do anything too clever.  I just wanted a shortcode (some text you put into a post which is expanded by a plugin) to read some values from some custom fields and include them in the article footer.  It saves having to paste lots of formatting HTML into each post and lets you just suck content from the custom fields.

I was surprised I couldn’t find a simple ‘template’ style plugin on the WordPress site, maybe I was just using the wrong search terms.  It’s the kind of thing that would be very useful for building common information boxes for reviews, etc.  Anyway, I hacked together a 59 line php file, of which around 1/3rd is info and license to read two custom fields and whack them into a div.

Took about 9000% less time than I expected.