Setting Up CentOS 5 to Host a LAMP Web Application
CentOS is far from my favorite Linux distribution, but I don't think that there is any particularly rational reason for that. It does the job. Perhaps I look on it with disfavor because out of the box it isn't set up with good package repositories by default, so you have to go looking for those before you can get started on setting up a new server. In any case, this post outlines the steps I take when setting up a new CentOS 5 machine for use as a standalone Drupal server, though it works just as well for any LAMP web application.
Log in, Sudo to Root
sudo su -
You want that "-" at the end there - omit it and you'll have issues because you won't get the full root environment path.
Add the Necessary RPM Repositories
You will be using the Yum package manager. Unfortunately the default repositories are a little light on software for CentOS, unlike Fedora, which means you'll have to use other tools along the way. So first off you'll want to add a decent repository to your system, a short process which starts by finding your version of CentOS and server architecture (i.e. i*86 or x86_64):
cat /etc/redhat-release uname -a
Then go find the RPM server that matches your architecture at http://dag.wieers.com/rpm/FAQ.php#B2. e.g. for CentOS 5.6 on i386 you want the RHEL5 server:
rpm -Uhv [rpmforge-release url goes here] yum update yum
That will set you up to use the new package repository in addition to the defaults. Or if you know your way around the package management system pretty well, you do skip the above instructions and add the appropriate repositories manually - your choice.
Install The Basics
You might start with this, which will get most of Apache, PHP and MySQL, and a bunch of necessary supporting packages through their dependencies:
yum install httpd mod_ssl php php-mysql php-pdo php-xml php-imap yum install php-mcrypt php-mbstring php-pecl-memcache php-gd php-common yum install mysql mysql-server gd gd-devel ImageMagick
Note that php* and php53* are two different sets of packages for CentOS, and they will conflict - which is not the case for repositories for Fedora, for example. Here I'm going with the older set of packages for the sake of momentary convenience.
Next, you want to get the APC bytecode cache installed, which requires a side-trip off into PECL. PHP is slow without a bytecode cache, and all modern PHP frameworks and applications tend to assume that you are using one:
yum install php-pear php-devel httpd-devel pcre-devel pecl install apc echo "extension=apc.so" > /etc/php.d/apc.ini
Now try to install memcached:
yum install memcached
This may or may not work. On CentOS 5.6, the package for perl-Net-SSLeay available through yum is 1.30, and it needs to be 1.33 or later for the package dependencies to resolve. You may also have issues with perl-IO-Socket-SSL. You will have to take the following actions on CentOS 5.* on x86_64 to solve these problems by updating the packages through RPM. Some of the package names will be different for other versions of CentOS, and it should hopefully be easy to see where and how they will be different:
cd /root rpm -e perl-Net-SSLeay-1.30-4.fc6 rpm -e perl-IO-Socket-SSL-1.01-1.fc6 wget http://packages.sw.be/perl-Net-SSLeay/perl-Net-SSLeay-1.36-1.el5.rfx.x86_64.rpm wget http://packages.sw.be/perl-IO-Socket-SSL/perl-IO-Socket-SSL-1.34-1.el5.rfx.noarch.rpm rpm -i perl-Net-SSLeay-1.36-1.el5.rfx.x86_64.rpm rpm -i perl-IO-Socket-SSL-1.34-1.el5.rfx.noarch.rpm
Then once again try:
yum install memcached
Which should now work.
Monit is a monitoring and alerting package. If you aren't using it, you probably should be. This installation is easy:
yum install monit
Set up Services
Using chkconfig makes it trivial to set various necessary services to run on startup:
chkconfig --levels 2345 httpd on chkconfig --levels 2345 mysqld on chkconfig --levels 2345 memcached on chkconfig --levels 2345 monit on
Open up /etc/init.d/memcached in your favorite text editor and alter these lines:
PORT="11211" USER="nobody" MAXCONN="1024" CACHESIZE="64" OPTIONS=""
Change them as follows, to boost the number of connections and cache, and ensure that memcached is only listening on localhost.
PORT="11211" USER="nobody" MAXCONN="20480" CACHESIZE="512" OPTIONS="-l 127.0.0.1"
These are generally useful production values, and cachesize is measured in Megabytes - if you are setting up a test server, you'll probably want to scale back the memory to 64. In fact, you should probably ignore any recommendation I make on cache size and maximum number of concurrent connections and think through what your application and server hardware demand that those numbers should be.
Then restart Memcached:
Turn on the query cache: in /etc/my.cnf add the following under the [mysqld] heading, add the following lines for a sensibly sized query cache for most applications. You will hopefully have a better idea as to how large a cache benefits your own web application, so adjust as you see fit.
Then restart MySQL:
Now add the users and databases you need, and set a root user password.
Add these lines to the default APC file you created in /etc/php.d/apc.ini:
apc.enabled=1 apc.shm_segments=1 apc.optimization=0 apc.shm_size=64
The important item is the definition for apc.shm_size, as the default of 32 is too small for most PHP applications. Tinkering with APC beyond this point is something to look into when you get to the optimization stage of your work, but that's far beyond the scope of this post. Use Google and you'll find a lot of discussion and many pointers on this topic.
Make whatever changes are needed by your application to the PHP configuration - it will work as-is, but you will probably want to adjust memory allocations, alter error reporting, set expose_php = Off, and so forth.
Set up the Apache configuration as needed - in particular note that Monit will treat the default out of the box behavior of an empty Apache root directory as a failure, as this returns a 403 error code. You will probably want to put an empty index.html file into /var/www/html to make things go more smoothly.
The version of Monit installed through Yum may be initially set to store its running ID and state in either an unhelpful or non-existent directory. That will have to be changed, and you will also want to alter some of the configuration parameters in any case - so create a file /etc/monit.d/monitrc and put the following lines in it:
set idfile /var/run/monit-id set statefile /var/run/monit-state set daemon 60 set logfile /var/log/monit.log
For most of my simple single-server applications, I then create a trivial set of instructions that set monit to watch over the httpd, mysql, and memcached processes without issuing notifications or doing much more than restarting on failure. Create the file /etc/monit.d/httpd and put the following instructions into it:
check process httpd with pidfile /var/run/httpd.pid group www start program = "/etc/init.d/httpd start" stop program = "/etc/init.d/httpd stop" if failed host localhost port 80 protocol HTTP with timeout 10 seconds then restart if 5 restarts within 5 cycles then timeout
check process mysqld with pidfile /var/run/mysqld/mysqld.pid group database start program = "/etc/init.d/mysqld start" stop program = "/etc/init.d/mysqld stop" if failed host localhost port 3306 protocol mysql then restart if 5 restarts within 5 cycles then timeout
check process memcached with pidfile /var/lock/subsys/memcached group www start program = "/etc/init.d/memcached start" stop program = "/etc/init.d/memcached stop" if failed host localhost port 11211 then restart if 5 restarts within 5 cycles then timeout
Monit also offers options for notifications, restarting on high load, logging activity, and many other amenities, so you may want to add more to this very basic configuration.
Install Your Web Application
The basic server set up is now done. You can carry on to the next step of installing your web application code, schema, and data - and then you're ready for visitors.