- Install Apache HTTP Server
- Create ‘apache’ user/group
- Build OpenSSL (from source)
- Build Apache HTTP Server (from source)
- Post-install Steps
- Install PHP
- Required Packages
- MySQL Packages
- Oracle Instant Client Packages
- Build PHP from source
- Post-install Steps
Introduction
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.
Software
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 http://www.openssl.org/source/openssl-1.0.0g.tar.gz
Unpack tarball:
$ tar -xvf openssl-1.0.0g.tar.gz --no-same-owner
Configure/Make/Install:
$ 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 http://www.apache.org/dist/httpd/httpd-2.2.22.tar.gz
Unpack tarball:
$ tar -xvf httpd-2.2.22.tar.gz --no-same-owner
Configure/Make/Install:
$ 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/" \
$APACHE_BASE/httpd-2.2.22/conf/httpd.conf
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/libphp5.so
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:
#!/bin/bash
#
# httpd-2.2.22 Startup script for custom user LAMP
#
# chkconfig: - 85 15
# description: custom user LAMP plus Oracle support
# processname: httpd
APACHE_HOME=/u01/app/LAMP/apache/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
CONF_FILE=$APACHE_HOME/conf/httpd.conf
PIDFILE=$APACHE_HOME/logs/httpd-2.2.22.pid
if [ ! -f ${CONF_FILE} ]; then
exit 0
fi
case "$1" in
start)
/bin/rm -f ${PIDFILE}
cmdparm="start"
cmdtext="starting"
;;
restart)
cmdparm="restart"
cmdtext="restarting"
;;
stop)
cmdparm="stop"
cmdtext="stopping"
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
;;
esac
echo "httpd $cmdtext."
status=`${APACHE_HOME}/bin/apachectl $cmdparm 2>&1`
if [ $? != 0 ]; then
echo "$status"
exit 1
fi
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
fontconfig-devel-2.4.1-7.el5
freetype-devel-2.2.1-28.el5_7.2
libjpeg-devel-6b-37
libpng-devel-1.2.10-7.1.el5_7.5
libxml2-devel-2.6.26-2.1.12.el5_7.2
zlib-devel-1.2.3-4.el5
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
mysql-5.0.77-4.el5_6.6
mysql-devel-5.0.77-4.el5_6.6
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-11.2.0.3.0-1.x86_64.rpm \
oracle-instantclient11.2-sqlplus-11.2.0.3.0-1.x86_64.rpm \
oracle-instantclient11.2-devel-11.2.0.3.0-1.x86_64.rpm
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 http://us3.php.net/get/php-5.3.10.tar.gz/from/us.php.net/mirror
Unpack tarball:
$ tar -xvf php-5.3.10.tar.gz --no-same-owner
Configure/Make/Install:
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 “extension=oci8.so” to ‘php.ini’
$ grep extension=oci $APACHE_BASE/httpd-2.2.22/lib/php.ini
extension=oci8.so
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 '<?php phpinfo(); ?>' > $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
DGSVC =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = oradb1.colestock.test)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = oradb2.colestock.test)(PORT = 1521))
)
(CONNECT_DATA =
(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
test-oracle.php
<?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);
ociexecute($parsed);
$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