How to Build a LAMP


Getting Started

This step-by-step guide shows how to build a LAMP (Linux-Apache-MySQL-PHP). There are many ways to build a LAMP, including using freely-available packaged frameworks, etc. This guide builds the LAMP from scratch using primarily source software distributions; additionally, Oracle (OCI) support is compiled in. The guide assumes a Linux machine – bare metal or VM – is already available; performing the OS installation/configuration is beyond the scope of this demo. This guide was developed using a x64 VM with Cent OS 5.6 (final) installed using VMWare’s ‘Easy Install.’ If you are using a different distribution of Linux then you will need to change certain steps to account for subtle difference between distributions (e.g. yum vs. up2date). The host has a static IP address added to DNS and so forth. Ports expected to be used by HTTP/HTTPS have been opened as appropriate.


We will be installing/updating OS packages via traditional package management tools.
Additionally, we will be installing other software from source, etc. from outside sources; here is where to get the software appropriate for you distribution/platform:

Install Apache HTTP Server

Create ‘apache’ user/group

If the user and group don’t already exist, create them:

$ groupadd -g 48 apache
$ useradd -d /dev/null -g apache -s /sbin/nologin -u 48 apache

Build OpenSSL (from source)

This guide compiles Apache with support for SSL. OpenSSL is required in order to do this. If you already have OpenSSL installed, you can skip this step; otherwise, download the latest stable source distribution to the machine:
Download OpenSSL source to temporary location:

$ cd /tmp
$ wget

Unpack tarball:

$ tar -xvf openssl-1.0.0g.tar.gz --no-same-owner


$ cd openssl-1.0.0g
$ ./config --prefix=/usr/local/ssl
$ make
$ make install

The preceding will install OpenSSL from source, installing it into /usr/local/ssl. Adjust the path – ‘prefix’ denotes the target install location – as appropriate for your system; just be sure to update relevant, subsequent commands for the new location.

Build Apache HTTP Server (from source)

Create directories and symbolic links:

$ export APACHE_BASE=/u01/app/LAMP/apache
$ mkdir -p $APACHE_BASE/build
$ mkdir -p $APACHE_BASE/httpd-2.2.22
$ ln -s $APACHE_BASE/httpd-2.2.22 $APACHE_BASE/httpd

Note the version-specific directory and ‘httpd’ symbolic link to it.
Download Apache HTTP Server source:

$ cd $APACHE_BASE/build
$ wget

Unpack tarball:

$ tar -xvf httpd-2.2.22.tar.gz --no-same-owner


$ cd httpd-2.2.22
$ ./configure --prefix=$APACHE_BASE/httpd --enable-ssl --with-ssl=/usr/local/ssl --enable-so
$ make
$ make install

The above installs Apache from source with support for SSL, assuming that OpenSSL is installed in /usr/local/ssl; again, adjust any paths as appropriate.

Post-install Steps

Change owner/group ‘httpd’ runs as

$ sed -i -e "s/User daemon/User apache/" \
-e "s/Group daemon/Group apache/" \

In this case, 2 lines in the configuration file are being changed so that the ‘httpd’ process will run as ‘apache.’

Secure Apache

Reasonable lock-down of binaries:

$ chmod 511 $APACHE_BASE/httpd-2.2.22/bin/httpd
$ cd $APACHE_BASE/httpd-2.2.22
$ chown 0 . bin conf logs
$ chgrp 0 . bin conf logs
$ chmod 755 . bin conf logs

Create new ‘DocumentRoot,’ change its ownership and modify permissions:

$ rm -rf $APACHE_BASE/httpd-2.2.22/htdocs
$ export DOC_BASE=/u01/app/LAMP/www
$ sudo groupadd -r lamp
$ usermod -a -G lamp jcolestock
$ mkdir -p $DOC_BASE
$ mkdir -p $DOC_BASE/html
$ chown root:lamp $DOC_BASE
$ chmod u=rwx,g=rwx,o=rx $DOC_BASE
$ chown root:lamp $DOC_BASE/html
$ chmod u=rwx,g=rwx,o=rx $DOC_BASE/html
$ find $DOC_BASE/html -depth -type d -exec chgrp lamp -- '{}' ';'
$ find $DOC_BASE/html -depth -type d -exec chmod u=rwx,g=rwxs,o=rx -- '{}' ';'
$ find $DOC_BASE/html -depth -type f -exec chgrp lamp -- '{}' ';'
$ find $DOC_BASE/html -depth -type f -exec chmod u=rw,g=rw,o-x -- '{}' ';'
$ sed -i -e "s|$APACHE_BASE/httpd/htdocs|$DOC_BASE/html|" $APACHE_BASE/httpd-2.2.22/conf/httpd.conf

We start by removing the old ‘DocumentRoot.’ Then we create a new ‘DocumentRoot,’ which will be owned by ‘root:lamp,’ where ‘lamp’ is a new OS group we created for the authors of web content, etc. I also granted ‘lamp’ to ‘jcolestock’ – my personal user – so that I can publish content to the LAMP. You will want to grant this group to any users whom will publish content. Additionally, users who publish content must have their ‘umask’ set to ’0002′ while publishing content. After that, we lock down the permissions on the new ‘DocumentRoot’ as appropriate. The last step is to update Apache’s configuration file to specify the new location of the ‘DocumentRoot.’

Add PHP MIME type support

$ vi $APACHE_BASE/httpd-2.2.22/conf/httpd.conf

Inside the ‘IfModule mime_module’ block add “AddType application/x-httpd-php .php .phtml”

$ grep .php $APACHE_BASE/httpd-2.2.22/conf/httpd.conf
LoadModule php5_module modules/
AddType application/x-httpd-php .php .phtml

Create /etc/init.d startup script for httpd

Create /etc/init.d/httpd-2.2.22 startup script

$ vi /etc/init.d/httpd-2.2.22

Modify the following script as appropriate for your environment:

# httpd-2.2.22 Startup script for custom user LAMP
# chkconfig: - 85 15
# description: custom user LAMP plus Oracle support
# processname: httpd

TNS_ADMIN=/u01/app/oracle/network/admin; export TNS_ADMIN
LD_LIBRARY_PATH=/usr/lib:/usr/lib64:$APACHE_HOME/lib:/usr/lib/oracle/11.2/client64/lib:/usr/lib/oracle/11.2/lib; export LD_LIBRARY_PATH

if [ ! -f ${CONF_FILE} ]; then
exit 0

case "$1" in
/bin/rm -f ${PIDFILE}
echo "Usage: $0 {start|stop|restart}"
exit 1

echo "httpd $cmdtext."

status=`${APACHE_HOME}/bin/apachectl $cmdparm 2>&1`

if [ $? != 0 ]; then
echo "$status"
exit 1
exit 0

Set to startup automatically:

$ chkconfig --add httpd-2.2.22
$ chkconfig --list httpd-2.2.22
httpd-2.2.22 0:off 1:off 2:on 3:on 4:on 5:on 6:off

The above is very much a barebones startup script, but should do the trick

Install PHP

Required Packages

In most cases, some packages required for PHP are missing. Any missing packages will need to be installed prior to building PHP. Usually the following packages are missing and need to be installed: libxml2-devel, libpng-devel, libjpeg-devel, freetype-devel, fontconfig-devel, and zlib-devel.

$ rpm -qa libxml2-devel libpng-devel libjpeg-devel freetype-devel fontconfig-devel zlib-devel | sort -u

Install any missing packages using your package management utility:

$ yum install libxml2-devel libpng-devel libjpeg-devel freetype-devel fontconfig-devel zlib-devel

MySQL Packages

Since we are building a LAMP, MySQL libraries are required in order to compile MySQL support into PHP.

Ensure the following MySQL packages are installed: mysql and mysql-devel.

$ rpm -qa mysql mysql-devel | sort -u

If the packages are not installed, do so:

$ yum install mysql mysql-devel

Oracle Instant Client Packages

This guide builds in support for Oracle/OCI as well by installing the Oracle Instant Client and then compiling the appropriate libraries into PHP using the appropriate flags.

Download the appropriate RPMs from Oracle and install:

$ rpm -Uvh oracle-instantclient11.2-basic- \
oracle-instantclient11.2-sqlplus- \

If you would like to skip this step, feel free; however, remember to omit the ‘–with-oci8′ flag when configuring PHP.

Build PHP from source

Download PHP source:

$ cd $APACHE_BASE/build
$ wget

Unpack tarball:

$ tar -xvf php-5.3.10.tar.gz --no-same-owner


At this point, the prerequisites for compiling PHP should be satisfied. Remember to include the ‘–with-oci8′ flag if you wish to compile Oracle/OCI support in (and have installed the Oracle Instant Client or equivalent). Additionally, make sure to update the ‘configure’ command to reflect the true path – on your system – to all relevant libraries and executables. Study this command carefully, making sure to identify the installation locations on your specific system. Path should diverge from 32-bit vs. 64-bit systems, different distributions of Linux, etc. Feel free to modify/add compiler flags as appropriate for your needs, etc. After you have updated the ‘configure’ command, run the following:

$ cd php-5.3.10
$ ./configure --prefix=$APACHE_BASE/httpd-2.2.22 --with-openssl-dir=/usr/local/ssl --with-zlib --with-zlib-dir=/usr/include --with-apxs2=$APACHE_BASE/httpd-2.2.22/bin/apxs --with-libdir=lib64 --with-gd --with-png-dir --with-jpeg-dir --with-freetype-dir --with-mysql=/usr/lib64/mysql --enable-mbstring --with-oci8=instantclient,/usr/lib/oracle/11.2/client64/lib
$ make
$ make install

Post-install Steps

Create ‘php.ini’ from template:

$ cp php.ini-production $APACHE_BASE/httpd-2.2.22/lib/php.ini

Add dynamic extensions to ‘php.ini’:

$ vi $APACHE_BASE/httpd-2.2.22/lib/php.ini

Add “” to ‘php.ini’

$ grep extension=oci $APACHE_BASE/httpd-2.2.22/lib/php.ini

Functional Test

Start Apache

Before you can begin testing, you must start Apache:

$ service httpd-2.2.22 start
httpd starting.
$ ps -ef | grep httpd | grep -v grep
root 9221 1 0 Feb13 ? 00:00:00 /u01/app/LAMP/apache/httpd/bin/httpd -k start
apache 9222 9221 0 Feb13 ? 00:00:00 /u01/app/LAMP/apache/httpd/bin/httpd -k start
apache 9223 9221 0 Feb13 ? 00:00:00 /u01/app/LAMP/apache/httpd/bin/httpd -k start
apache 9224 9221 0 Feb13 ? 00:00:00 /u01/app/LAMP/apache/httpd/bin/httpd -k start
apache 9225 9221 0 Feb13 ? 00:00:00 /u01/app/LAMP/apache/httpd/bin/httpd -k start
apache 9226 9221 0 Feb13 ? 00:00:00 /u01/app/LAMP/apache/httpd/bin/httpd -k start
apache 9227 9221 0 Feb13 ? 00:00:00 /u01/app/LAMP/apache/httpd/bin/httpd -k start

Verify PHP

Login as someone in the ‘lamp’ group – in my case, jcolestock – and publish a ‘phpinfo’ page in order to verify correct operation/configuration:

$ su - jcolestock
$ export DOC_ROOT=/u01/app/LAMP/www/html
$ umask 0002
$ echo '' > $DOC_ROOT/phpinfo.php

Navigate to a browser and verify the page; for instance in my enviornment: ‘http://lamp1.colestock.test/phpinfo.php’

Verify Oracle

The example startup script in this demo uses ‘/u01/app/oracle/network/admin’ as ‘TNS_ADMIN’; this is where PHP will look for ‘tnsnames.ora’ and the like. To verify oracle, I will place a valid service entry into this file and then try to connect to the service in question with a simple PHP script.

Add an entry to your ‘tnsnames.ora’; for example:

$ more /u01/app/oracle/network/admin/tnsnames.ora
(ADDRESS = (PROTOCOL = TCP)(HOST = oradb1.colestock.test)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = oradb2.colestock.test)(PORT = 1521))
(SERVICE_NAME = dgsvc.colestock.test)

Publish the following PHP script, adjusting the username, password, and service name as appropriate

$ su - jcolestock
$ umask 0002
$ export DOC_ROOT=/u01/app/LAMP/www/html
$ vi $DOC_ROOT/test-oracle.php


/* Change the username, password, service name to yours */
$db_conn = ocilogon('lamp_owner', 'lamp_password', 'dgsvc');
$sql = "SELECT sys_context('userenv','instance_name') AS \"Instance\" FROM dual";
$parsed = ociparse($db_conn,$sql);
$nrows = ocifetchstatement($parsed,$results);
for ($i = 0; $i < $nrows; $i++ ) {
echo "You are connected to the following instance: " . $results["Instance"][$i];

Navigate to a browser and verify the page; for instance in my enviornment: ‘http://lamp1.colestock.test/test-oracle.php’

You should get a response similar to mine: ‘You are connected to the following instance: dgstdby’; in my case ‘dgstdby’ is the instance name that I am connected to

Tagged with: , , , ,
Posted in Apache, LAMP, Linux, MySQL, PHP