Setting up Apache 2.2, MySQL 5.5 + Sphinx 2.0, PHP 5.3, a Scripted Guide

Similar to the previous scripted guide, this script will download the source for Apache, MySQL (and optionally with Sphinx, steps denoted in red font), and PHP and compile it under CentOS 5 and 6 on a x86-64 platform.

I’ve had this type of script for a few years now due to the amount of times I’ve had to provision a VPS from scratch. I simply copy/paste the script onto a clean VPS and away it goes setting up a LAMP server from source. This script should not require any existing requisites and should work out-of-the-box on a clean installation of CentOS 6.


#
# We need a few packages in order to compile apache, mysql and PHP from rpmforge.
# Import the key and install the repo.

cd
wget http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.2-2.el6.rf.x86_64.rpm
rpm --import http://apt.sw.be/RPM-GPG-KEY.dag.txt
rpm -K rpmforge-release-0.5.2-2.el6.rf.*.rpm
rpm -i rpmforge-release-0.5.2-2.el6.rf.*.rpm

# Install all prerequisites.
yum -y install make autoconf g++ gcc-c++ libtermcap-devel libgcc-c++ libtool gcc libpng-devel libjpeg-devel libxml1-devel libxml2-devel curl curl-devel libmcrypt libmcrypt-devel libtool-ltdl-devel libxml2.x86_64 libxml2-devel.x86_64 curl-devel.x86_64 openssl-devel

# Download the source files. Sphinx is optional.
mkdir src
cd ~/src
wget http://host.steamr.com/supportfiles/httpd-2.2.21.tar.gz
wget http://host.steamr.com/supportfiles/mysql-5.5.16.tar.gz
wget http://host.steamr.com/supportfiles/php-5.3.8.tar.gz
wget http://host.steamr.com/supportfiles/sphinx-2.0.1-beta.tar.gz

# Extract all archives
for f in `ls *.tar.gz` ; do tar -xzf $f ; done


#
# Setting up apache into /opt/apache
#

cd /root/src/http*/
./configure --prefix=/opt/apache --enable-so --enable-rewrite --enable-ssl --enable-setenvif
make
make install

#
# Setting up MySQL into /opt/mysql.
# Note: MySQL 5.5 and above will require cmake.
#

yum -y install cmake
cd /root/src/mysql*/


# If you wish to compile MySQL with Sphinx, run the following:
cp -R ../sphinx-*/mysqlse/ storage/sphinx
sh BUILD/autorun.sh
./configure --prefix=/opt/mysql --with-plugins=sphinx --with-unix-socket-path=/opt/mysql/mysql.sock --without-man --enable-shared --without-debug --enable-assembler --with-ssl CFLAGS=-O3 'CXXFLAGS=-O3 -fno-exceptions -felide-constructors -fno-rtti' CXX=gcc


# Otherwise, to compile MySQL without Sphinx run:
./configure --prefix=/opt/mysql --with-unix-socket-path=/opt/mysql/mysql.sock --without-man --enable-shared --without-debug --enable-assembler --with-ssl CFLAGS=-O3 'CXXFLAGS=-O3 -fno-exceptions -felide-constructors -fno-rtti' CXX=gcc

make
make install

# Setup the init scripts
/bin/cp support-files/mysql.server /etc/init.d/mysql
chmod 755 /etc/init.d/mysql
ln -s /etc/init.d/mysql /etc/rc3.d/S40mysql

# Copy the default configuration
/bin/cp support-files/my-medium.cnf /etc/my.cnf

# Setup the mysql system account
/usr/sbin/useradd -r mysql

# Update the MySQL permissions
cd /opt/mysql
chown -R mysql .
chgrp -R mysql .

# When setting up the initial database on MySQL 5.4 or earlier, run:
# /opt/mysql/bin/mysql_install_db --user=mysql
# On MySql 5.5 or later, run:

/opt/mysql/scripts/mysql_install_db --user=mysql --basedir=/opt/mysql

# Ensure the new database files created from the previous step is owned by mysql
chown -R mysql /opt/mysql

# Start MySQL manually:
/opt/mysql/bin/mysqld_safe --user=mysql &


#
# MySQL should now be running. You can verify this by running:
# ps -A|grep mysql
#

#
# Set the lib paths of mysql so the libmysqlclient.so or w/e can be found
#

echo "/opt/mysql/lib/mysql" > /etc/ld.so.conf.d/mysql.conf
/sbin/ldconfig


#
# Setting up Sphinx
# NOTE: You must have sphinx compiled with mysql from the previous step.
# You may skip this step if you do not wish to have Sphinx and continue to PHP.
#

cd /root/src/sphinx*
./configure --prefix=/opt/sphinx --with-mysql
make
make install

# The init script used by Sphinx requires sudo.
yum -y install sudo

# Setup the default config
/bin/cp /root/sphinx.conf /opt/sphinx/etc/sphinx.conf

# Setup the init scripts
cp contrib/scripts/searchd /etc/init.d/
chmod 777 /etc/init.d/searchd
ln -s /etc/init.d/searchd /etc/init.d/S55searchd

# Create the sphinx system account and ensure everything under /opt/sphinx/var is owned by sphinx.
useradd -r searchd
cd /opt/sphinx
chown -R searchd:searchd var

#
# Setup PHP as a module for apache:
#

cd /root/src/php*/
./configure --prefix=/opt/php5 --with-apxs2=/opt/apache/bin/apxs --with-config-file-path=/etc/ --with-gd --enable-shmop --enable-track-vars --enable-ftp --enable-sockets --enable-exif --enable-zip --enable-sysvsem --with-zlib --enable-sysvshm --enable-magic-quotes --with-jpeg-dir --with-png-dir --enable-mbstring --enable-embedded-mysqli=shared --with-curl --with-mcrypt --with-mysql=/opt/mysql --with-mysqli=/opt/mysql/bin/mysql_config
# If you want imap support: use options --with-imap --with-imap-ssl=/usr/include/openssl --with-kerberos
make
make install

#
# At this stage, apache should have the PHP module installed.
# NOTE: Since apache does not come with an init script, you must install
# this manually. Refer to http://leo.steamr.com/?p=229 for the complete
# script. Ensure to change the path (in red) to the correct path to httpd.
# In this case, /opt/apache/bin/httpd
#

Setting up Nagios 3.3.1, a scripted guide

Since I wanted to automate the task of setting up a clean install of Nagios, I’ve made a script which will setup Nagios with apache from source. This script can be used as a how-to guide for anyone who’s trying to setup nagios for the first time. However, the main purpose is to enable me to quickly deploy a Nagios installation using an existing script.

#
# Setting up nagios 3.3.1 + nagios plugins 1.4.15 How-To Guide
#
# This guide will compile nagios from source, configure apache to
# serve nagios from the /nagios/ directory, and basic configuration
# of nagios.
#
# Nagios will be installed in the default /usr/local/nagios/
# directory. Change this by providing the --prefix argument when
# configuring.
#
# Please read through the script throughly. Any known issues with
# this guide will be discussed in the troubleshooting section below.
#
# Requisites: Apache + PHP Setup, GCC, all running under CentOS 6
# Author: Leo Leung (Jan 15, 2012)
#
#######################################################################

# using /root as our working directory
cd ~

# download source
wget http://prdownloads.sourceforge.net/sourceforge/nagios/nagios-3.3.1.tar.gz
wget http://prdownloads.sourceforge.net/sourceforge/nagiosplug/nagios-plugins-1.4.15.tar.gz

# extract source
tar -xzf nagios-3*.tar.gz
tar -xzf nagios-plugins*.tar.gz

# add user 'nagios' as a system user, add apache to the group.
useradd -r -d /usr/local/nagios -s /bin/bash nagios
usermod -G nagios -a apache

# Compile nagios
cd ~/nagios
./configure --with-nagios-user=nagios --with-nagios-grp=nagios
make all
make install
make install-init
make install-config

# Compile nagios plugins
cd ~/nagios-plugins*
./configure
make install

# Configure apache
cd /etc/httpd/conf.d/

# vi nagios.conf (Put the following into nagios.conf):
# ScriptAlias /nagios/cgi-bin/ /usr/local/nagios/sbin/
#
# AllowOverride AuthConfig
# Options ExecCGI
# Allow from all
# Order allow,deny
#

#
# Alias /nagios/ /usr/local/nagios/share/
#
# Options None
# AllowOverride AuthConfig
# Order allow,deny
# Allow from all
#

echo "ScriptAlias /nagios/cgi-bin/ /usr/local/nagios/sbin/" >> nagios.conf
echo "" >> nagios.conf
echo " AllowOverride AuthConfig" >> nagios.conf
echo " Options ExecCGI" >> nagios.conf
echo " Allow from all" >> nagios.conf
echo " Order allow,deny" >> nagios.conf
echo "
" >> nagios.conf
echo "" >> nagios.conf
echo "Alias /nagios/ /usr/local/nagios/share/" >> nagios.conf
echo "" >> nagios.conf
echo " Options None" >> nagios.conf
echo " AllowOverride AuthConfig" >> nagios.conf
echo " Order allow,deny" >> nagios.conf
echo " Allow from all" >> nagios.conf
echo "
" >> nagios.conf

#
# Protect the nagios directory via htpasswd
#
# CONFIGURATION NOTE:
# The default nagios admin username is 'nagiosadmin'. If you wish
# to change this or add another user to have access to the nagios
# system, be sure to add the username to cgi.cfg as a comma
# delimited list.
#
cd /usr/local/nagios/share/

# vi .htaccess (Put the following into .htaccess)
# AuthName "Nagios Access"
# AuthType Basic
# AuthUserFile /usr/local/nagios/etc/htpasswd.users
# require valid-user
echo "AuthName \"Nagios Access\"" >> .htaccess
echo "AuthType Basic" >> .htaccess
echo "AuthUserFile /usr/local/nagios/etc/htpasswd.users" >> .htaccess
echo "require valid-user" >> .htaccess

cp .htaccess /usr/local/nagios/sbin/
cd /usr/local/nagios/etc/
htpasswd -bc htpasswd.users nagiosadmin defaultpassword
chmod 644 htpasswd.users
chown apache:apache htpasswd.users

# apply apache configuration
/etc/init.d/httpd restart

#
# Configuring Nagios
#
cd /usr/local/nagios/etc/

#
# CONFIGURATION NOTE:
# You will want to edit this file manually. However, to get nagios
# working through apache (via CGI), we will need to enable
# check_external_commands.
#
# vi nagios.cfg
# /check_external_commands
# * Set variable to 1 *
#
sed -i -e 's/check_external_commands=0/check_external_commands=1/g' nagios.cfg

# Create the var directory needed by nagios. If you change the paths in
# nagios.cfg to /var, please change the following command accordingly.
mkdir -p /usr/local/nagios/var/spool/checkresults
mkdir -p /usr/local/nagios/var/rw
chown -R nagios:nagios /usr/local/nagios/var/

#
# CONFIGURATION NOTE:
# As noted above, if you wish to add new users to the system, you
# must edit cgi.cfg and add the appropriate usernames for certain
# access roles.
# Example:
# authorized_for_system_information=nagiosadmin
# will let user 'nagiosadmin' access system information. To add user
# 'newadmin', change the line to:
# authoriozed_for_system_information=nagiosadmin,newadmin
# to let anyone who has authenticated, use *
#
# vi cgi.cfg
#
vi cgi.cfg

# Verify the configuration
/usr/local/nagios/bin/nagios -v /usr/local/nagios/etc/nagios.cfg

# If everything from above looks okay, then we should be set to go.
/etc/init.d/nagios start

#
# From here, you should have nagios setup. Going to http://server/nagios/
# should prompt for a username/password and display the nagios web panel.
#
# If you're seeing errors, please refer to the troubleshooting section.
#
# Your next order of business is to configure hosts and services to monitor.
# But that's beyond the scope of this guide.
#

####################################################################
#
# Troubleshooting
#
# PROBLEM 1: When running 'make install' on nagios, an error:
#
# /usr/bin/install: omitting directory `includes/rss/extlib'
# /usr/bin/install: omitting directory `includes/rss/htdocs'
# /usr/bin/install: omitting directory `includes/rss/scripts'
# make[1]: *** [install] Error 1
# make[1]: Leaving directory `/root/nagios/html'
# make: *** [install] Error 2
#
# When accessing main.php, you get a PHP error.
#
# SOLUTION 1:
# It appears that the make file isn't copying the php libraries over properly.
# To fix this, you'll need to copy the files manually:
#
# rm -rf /usr/local/nagios/share/includes/rss/
# cp -R /root/nagios/html/includes/rss/ /usr/local/nagios/share/includes/rss/
# chown -R nagios:nagios /usr/local/nagios/share/includes/rss/
#
# ------------------------
#
# PROBLEM 2: From the web panel, you get the following error when
# updating services or notification settings:
# Error: Could not open command file '/usr/local/nagios/var/rw/nagios.cmd' for update!
#
# SOLUTION 2:
# You need to add apache to the nagios group. Do this by running:
#
# usermod -G nagios -a apache
#
# You might need to restart apache for the changes to take affect.
# /etc/init.d/httpd restart
#
# ------------------------
#
# PROBLEM 3: The .cgi pages are giving 500 errors. error_log shows something similar
# to: (13)Permission denied: exec of '/usr/local/nagios/sbin/status.cgi' failed
#
# SOLUTION 3: There is a permission issue. Try disabling SELinux and see what happens.
#

Solving “Error occurred during initialization of VM” on a VPS

After installing java (via yum) on a VPS, running java results in:

Error occurred during initialization of VM
Could not reserve enough space for object heap
*** glibc detected *** java: double free or corruption (out): 0x0000000041040f30 ***
======= Backtrace: =========
/lib64/libc.so.6[0x2afe08ed12ef]
/lib64/libc.so.6(cfree+0x4b)[0x2afe08ed173b]
/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/amd64/server/libjvm.so[0x2afe0978cbb4]
/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/amd64/server/libjvm.so[0x2afe0978cd78]
/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/amd64/server/libjvm.so[0x2afe09791733]
/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/amd64/server/libjvm.so(JNI_CreateJavaVM+0x74)[0x2afe0950eb14]
java(JavaMain+0x96)[0x4026c6]
/lib64/libpthread.so.0[0x2afe08841617]
/lib64/libc.so.6(clone+0x6d)[0x2afe08f32c2d]
======= Memory map: ========

This can be solved by running:

export _JAVA_OPTIONS="-Xms20m -Xmx64m -XX:MinHeapFreeRatio=20 -XX:MaxHeapFreeRatio=40 -XX:NewSize=10m -XX:MaxNewSize=10m -XX:SurvivorRatio=6 -XX:TargetSurvivorRatio=80 -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled"

Or placing it in the bashrc file.

Note: You will need to change the Xms (initial java heap size), Xmx (maximum java heap size) above depending on the amount of free memory your container has. See addendum II


Addendum I actually attempted to run this in a OpenVZ VPS. There is absolutely no hope in getting java to run under OpenVZ unless you have a lot of guaranteed memory. If you really need to get java working in your VPS, try to get a Xen or vmware based VPS.


Addendum II I got java to run on an openVZ container with 256 MB guaranteed ram using the following java arguments:

-Xms8m -Xmx16m -Xss4m

However, upon creating threads and executing commands, java failed immediately with cannot fork memory messages.

I just got a XEN 128MB / 256MB swap VPS and it ran the same java application without a single problem. I didn’t even need those arguments.

Logging in via SSH keys

Let user@ServerA be the host that wants to connect to user@ServerB.

Run the following commands as user@ServerA

ssh-keygen -t rsa          # use empty pass phrase, save the keys to ~/.ssh/id_rsa and ~/.ssh/id_rsa.pub
chmod 700 ~/.ssh           # set the permissions of the .ssh directory to 700.
chmod 600 ~/.ssh/*         # set the permissions of the keys so no one else can read them.

It’s important to set the permissions! Otherwise SSH will not use the keys without a warning or message. I’ve wasted enough time to learn this the hard way.

Copy the ~/.ssh/id_rsa.pub from user@ServerA to user@ServerB:~/.ssh/authorized_keys. Again, set the permissions.

chmod 700 ~/.ssh         # set the permissions of the .ssh directory to 700.
chmod 600 ~/.ssh/*       # set the permissions of the keys so no one else can read them.

Compiling & Installing vnstat-1.10

Run the following commands to install vnstat. This will also configure vnstat to listen on eth0 and start automatically on boot.

This was done in CentOS5.4, but it should also work for any *NIX based machines.

Note: You may want to check on the vnstat website for the latest build. At the time of this writing, the latest version is 1.10.
Note2: The following example will configure vnstat on eth0; You may want to change this if you are on a OpenVZ VPS to venet0.

wget http://humdi.net/vnstat/vnstat-1.10.tar.gz
tar -xzf vnstat-1.10.tar.gz
cd vnstat-1.10
make
make install
vnstat --testkernel
/bin/cp examples/init.d/centos/vnstat /etc/init.d/vnstat
ln -s /etc/init.d/vnstat /etc/rc3.d/S40vnstat
vnstat -u -i eth0
/etc/init.d/vnstat start

Compiling PHP with LiteSpeed (with lsapi)

Compiling PHP with litespeed using LiteSpeed 4.10 SAPI.

You must download the latest PHP package and the litespeed sapi package to the /root directory, then run the following commands.
You may wish to change the config settings as needed.

Note: Litespeed was installed in /opt/lsws. You will want to change the prefix accordingly.

cd /root
tar -xjf php-5.3.2.tar.bz2
cd php-5.3.2
cd sapi
tar -xzf /root/php-litespeed-4.10.tgz
cd ..
touch ac*
./buildconf --force

./configure --prefix=/opt/lsws/lsphp5 --with-litespeed --with-config-file-path=/etc/ --with-gd --enable-shmop --enable-track-vars --enable-ftp --enable-sockets --enable-exif --enable-zip --enable-sysvsem --with-zlib --enable-sysvshm --enable-magic-quotes --with-jpeg-dir --with-png-dir --enable-mbstring --enable-embedded-mysqli=shared --with-curl --with-mysql=/opt/mysql --with-mysqli=/opt/mysql/bin/mysql_config --with-mcrypt
make
make install

/etc/init.d/lsws stop
sleep 5
/bin/cp sapi/litespeed/php /opt/lsws/fcgi-bin/lsphp
/etc/init.d/lsws start

Note: The ‘sleep 5’ statement is not necessary if you do these steps manually. It is added so the copy operation immediately after is successful. Otherwise, litespeed might still be running which will cause the copy operation to fail.

Compiling MySQL with Sphinx

The following commands were used to compile MySQL 5.1.43 with Sphinx 0.9.9. This will install it in /opt.  You may want to change the prefix accordingly.

Download the proper packages and following the following commands.

Note: For some reason, MySQL > 5.1.43 gives a “LT_INIT: command not found” error when compiling. Although it seems like it has something to do with autoconf < 2.2, this was ‘resolved’ by using an older release (5.1.43 instead of 5.1.44) at the time of this writing.

When configuring MySQL, if configure complains about something about no Sphinx, delete the entire MySQL source directory and try again from scratch.

Note: You should already have the following packages installed: libtermcap-devel libgcc-c++ libtool gcc make autoconf g++ gcc-c++

cd /root
tar -xzf mysql-5.1.43.tar.gz
tar -xzf sphinx-0.9.9.tar.gz

You may want to ignore this step if you do not want to compile sphinx with mysql.

cd mysql-5.1.43
cp -R ../sphinx-0.9.9/mysqlse/ storage/sphinx
sh BUILD/autorun.sh

Configure MySQL and compile as usual

./configure --prefix=/opt/mysql --with-unix-socket-path=/opt/mysql/mysql.sock --without-man --enable-shared  --without-debug --enable-assembler --with-ssl --with-plugins=sphinx CFLAGS=-O3 'CXXFLAGS=-O3 -fno-exceptions -felide-constructors -fno-rtti' CXX=gcc
make
make install

Setting up MySQL configuration and the initial database.

/bin/cp /root/my.cnf /etc/my.cnf
/bin/cp support-files/mysql.server /etc/init.d/mysql
chmod 755 /etc/init.d/mysql
ln -s /etc/init.d/mysql /etc/rc3.d/S40mysql
/bin/cp support-files/my-medium.cnf /etc/my.cnf
/usr/sbin/useradd mysql
cd /opt/mysql
chown -R mysql .
chgrp -R mysql .
bin/mysql_install_db --user=mysql
chown -R root .
chown -R mysql var
bin/mysqld_safe --user=mysql &
chown mysql /opt/mysql

Set the lib paths of MySQL so the libmysqlclient.so or whatever else libraries can be found. This is required when attempting to compile anything that requires MySQL (including sphinx).

echo "/opt/mysql/lib/mysql" > /etc/ld.so.conf.d/mysql.conf
ldconfig

Now that MySQL is done, we will compile Sphinx.

cd /root
cd sphinx-0.9.9
./configure --prefix=/opt/sphinx --with-mysql
make
make install

Post install steps:

/bin/cp /root/sphinx.conf /opt/sphinx/etc/sphinx.conf
cp contrib/scripts/searchd /etc/init.d/
chmod 777 /etc/init.d/searchd
ln -s /etc/init.d/searchd /etc/init.d/S55searchd

Setting up BIND on CentOS

The following steps were used to setup BIND using yum on CentOS 5.4. Assume the hostname is titan.steamr.com.
At the time of this writing, the yum repo had BIND 9.3

Step 1: Install the necessary packages:

yum -y install bind bind-libs bind-utils

Step 2: Create a new file /etc/named.conf with the following contents. Change titan.steamr.com for the hostname.
vi /etc/named.conf

options
{
     directory "/var/named"; // the default
};

zone "localhost" {
     type master;
     file "localhost.zone";
};

zone "titan.steamr.com" {
     type master;
     file "titan.steamr.com.zone";
};

Step 3: Create a new file /etc/named/localhost.zone with the following contents:

$TTL    86400
@               IN SOA  @       root (
                                        42              ; serial (d. adams)
                                        3H              ; refresh
                                        15M             ; retry
                                        1W              ; expiry
                                        1D )            ; minimum

                IN NS           @
                IN A            127.0.0.1
                IN AAAA         ::1

Step 4: Create a new file /etc/named/titan.steamr.com.zone with the following contents: (Change titan.steamr.com with your hostname)

$TTL    86400
titan.steamr.com.       14400   IN SOA  tns1.steamr.com root (
                                        20110000        ; serial (d. adams)
                                        3H              ; refresh
                                        15M             ; retry
                                        1W              ; expiry
                                        1D )            ; minimum

titan.steamr.com.       14400   IN NS           tns1.steamr.com
titan.steamr.com.       14400   IN NS           tns2.steamr.com
titan.steamr.com.       14400   IN A            67.215.230.73
localhost               14400   IN A            127.0.0.1
www                     14400   IN CNAME        titan.steamr.com
ftp                     14400   IN CNAME        titan.steamr.com

Step 5: Start BIND via /etc/init.d/named start

Step 6: Make BIND start on startup mv /etc/rc3.d/K87named S87named

Step 8: To add other DNS entries, append

zone "new.host.com" {
     type master;
     file "new.host.com.zone";
};

and create a new zone file /var/named/new.host.com.zone with something like the contents in step 4.

You will want to reload BIND once you add a new entry by running /etc/init.d/named reload