Compiling a LAMP stack for CentOS - Tutorial

 •  Filed under compiling, compile, LAMP, stack, CentOS

Getting the latest version of Apache, MySQL and PHP up and running on enterprise Linux operating systems can be a tough job. There are easy and quick ways to get around this, number 1 being the use of third-party repositories: but do you really want to use open-source software from third parties that might have been fiddled around with? I know, I can be a little bit paranoid about this. But, there is a second option: compiling the LAMP stack from source. This allows you to get control over:

  • The software versions used in the stack
  • The code that you compile (being able to review the code)
  • Enable and disable functionality that you (don't) need

Compiling the LAMP stack on CentOS from source is not that hard anymore, because I have written a script that automates the build process for you.

My script fetches all the source code that is needed to compile the LAMP stack and then compiles every dependency and/or program one by one. Afterwards, all the software gets installed in the /opt folder (you can always change this if you want).

So - without further ado - here's the script:

#!/bin/bash

TIMEFORMAT='It took %R seconds to complete this process.'  
time {  
    # Defining variables
    threads=$[$(nproc)+1]

    # Build local yum cache and install development tools
    echo "[1/16] Installing the 'Developer Tools' yum group.."
    yum -y makecache >/dev/null 2>&1 && yum -y groupinstall "Development Tools" >/dev/null 2>&1

    # Install other necessary binaries
    echo "[2/16] Installing necessary binaries.."
    yum -y install curl cmake >/dev/null 2>&1

    # Download source tarballs
    echo "[3/16] Downloading source tarballs.."
    curl ftp://xmlsoft.org/libxml2/LATEST_LIBXML2 -o libxml2.tar.gz >/dev/null 2>&1
    curl https://www.openssl.org/source/openssl-1.0.2l.tar.gz -o openssl.tar.gz >/dev/null 2>&1
    curl https://www.zlib.net/zlib-1.2.11.tar.gz -o zlib.tar.gz >/dev/null 2>&1
    curl http://apache.40b.nl/httpd/httpd-2.4.25.tar.gz -o httpd.tar.gz >/dev/null 2>&1
    curl https://ftp.pcre.org/pub/pcre/pcre-8.40.tar.gz -o pcre.tar.gz >/dev/null 2>&1
    curl http://apache.mirror.triple-it.nl/apr/apr-1.5.2.tar.gz -o apr.tar.gz >/dev/null 2>&1
    curl http://apache.mirror.triple-it.nl/apr/apr-util-1.5.4.tar.gz -o apr-util.tar.gz >/dev/null 2>&1
    curl https://ftp.gnu.org/gnu/ncurses/ncurses-6.0.tar.gz -o ncurses.tar.gz >/dev/null 2>&1
    curl https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-boost-5.7.18.tar.gz -o mysql.tar.gz -L >/dev/null 2>&1

    # Make source directories
    echo "[4/16] Creating source+build directories.."
    mkdir libxml2
    mkdir openssl
    mkdir zlib
    mkdir httpd
    mkdir pcre
    tar -xvzf httpd.tar.gz -C httpd --strip 1 >/dev/null 2>&1 && rm httpd.tar.gz
    mkdir httpd/srclib/apr
    mkdir httpd/srclib/apr-util
    mkdir ncurses
    mkdir mysql

    # Clone PHP sources
    echo "[5/16] Cloning PHP 7.1.5 from Github.."
    git clone -b php-7.1.5 https://github.com/php/php-src.git php7 >/dev/null 2>&1

    # Extract source packages
    echo "[6/16] Extracting source tarballs.."
    tar -xvzf libxml2.tar.gz -C libxml2 --strip 1 >/dev/null 2>&1 && rm libxml2.tar.gz
    tar -xvzf openssl.tar.gz -C openssl --strip 1 >/dev/null 2>&1 && rm openssl.tar.gz
    tar -xvzf zlib.tar.gz -C zlib --strip 1 >/dev/null 2>&1 && rm zlib.tar.gz
    tar -xvzf pcre.tar.gz -C pcre --strip 1 >/dev/null 2>&1 && rm pcre.tar.gz
    tar -xvzf apr.tar.gz -C httpd/srclib/apr --strip 1 >/dev/null 2>&1 && rm apr.tar.gz
    tar -xvzf apr-util.tar.gz -C httpd/srclib/apr-util --strip 1 >/dev/null 2>&1 && rm apr-util.tar.gz
    tar -xvzf ncurses.tar.gz -C ncurses --strip 1 >/dev/null 2>&1 && rm ncurses.tar.gz
    tar -xvzf mysql.tar.gz -C mysql --strip 1 >/dev/null 2>&1 && rm mysql.tar.gz

    # Pre-compile ncurses
    echo "[7/16] Compiling ncurses.."
    mkdir /opt/ncurses
    cd ncurses
    ./configure --prefix=/opt/ncurses --with-shared >/dev/null 2>&1 
    make -j$threads >/dev/null 2>&1 && make install >/dev/null 2>&1
    cd ..

    # Pre-compile mysql
    echo "[8/16] Compiling MySQL.."
    mkdir /opt/mysql
    cd mysql
    cmake -DWITH_BOOST=boost/ -DCMAKE_INSTALL_PREFIX:PATH=/opt/mysql -DCURSES_LIBRARY=/opt/ncurses/lib/libncurses.so -DCURSES_INCLUDE_PATH=/opt/ncurses/include . >/dev/null 2>&1
    make -j$threads >/dev/null 2>&1 && make install >/dev/null 2>&1
    cd ..

    # Pre-compile openssl
    echo "[9/16] Compiling OpenSSL.."
    mkdir /opt/openssl
    cd openssl
    ./config --prefix=/opt/openssl -fPIC >/dev/null 2>&1
    make -j$threads >/dev/null 2>&1 && make install >/dev/null 2>&1
    cd ..

    # Pre-compile libxml2
    echo "[10/16] Compiling LibXML2.."
    mkdir /opt/libxml2
    cd libxml2
    ./configure --without-python --prefix=/opt/libxml2 >/dev/null 2>&1
    make -j$threads >/dev/null 2>&1 && make install >/dev/null 2>&1
    cd ..

    # Pre-compile pcre
    echo "[11/16] Compiling PCRE.."
    mkdir /opt/pcre
    cd pcre
    ./configure --prefix=/opt/pcre >/dev/null 2>&1
    make -j$threads >/dev/null 2>&1 && make install >/dev/null 2>&1
    cd ..

    # Pre-compile zlib
    echo "[12/16] Compiling zlib.."
    mkdir /opt/zlib
    cd zlib
    ./configure --prefix=/opt/zlib >/dev/null 2>&1
    make -j$threads >/dev/null 2>&1 && make install >/dev/null 2>&1
    cd ..

    # Compile httpd
    echo "[13/16] Compiling httpd.."
    mkdir /opt/httpd
    cd httpd
    ./configure --with-pcre=/opt/pcre --with-z=/opt/zlib --with-libxml2=/opt/libxml2 --with-ssl=/opt/openssl --with-included-apr --enable-ssl --prefix=/opt/httpd >/dev/null 2>&1
    make -j$threads >/dev/null 2>&1 && make install >/dev/null 2>&1
    cd ..

    # Compile PHP7
    echo "[14/16] Compiling PHP7.."
    mkdir /opt/php7
    cd php7
    ./buildconf --force >/dev/null 2>&1 && ./configure --with-apxs2=/opt/httpd/bin/apxs --prefix=/opt/php7 --with-libxml-dir=/opt/libxml2 >/dev/null 2>&1
    make -j$threads >/dev/null 2>&1 && make install >/dev/null 2>&1
    cd .

    # Cleanup time!
    echo "[15/16] Cleaning up.."
    rm -rf php7 && rm -rf httpd && rm -rf zlib && rm -rf pcre && rm -rf libxml2 && rm -rf openssl && rm -rf mysql && rm -rf ncurses

    echo "[16/16] Finishing configuration for httpd, PHP7 and MySQL.."

    useradd -s /sbin/nologin mysql
    mkdir /opt/mysql/data
    chown -R mysql:mysql /opt/mysql/data
    mkdir /opt/mysql/data

    echo ""
    echo "Initializing MySQL:"
    echo ""

    /opt/mysql/bin/mysqld --initialize --datadir=/opt/mysql/data --user=mysql

    echo ""
    echo "You can start the MySQL daemon with:"
    echo "/opt/mysql/bin/mysqld --user=mysql --datadir=/opt/mysql/data --socket=/opt/mysql/data/mysql.sock"
    echo ""

    useradd -s /sbin/nologin www-data
    chown -R www-data:www-data /opt/httpd/htdocs
    sed -i 's/User daemon/User www-data/g' /opt/httpd/conf/httpd.conf
    sed -i 's/Group daemon/Group www-data/g' /opt/httpd/conf/httpd.conf

    mkdir /opt/certificates
    openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /opt/certificates/selfsigned.key -out /opt/certificates/selfsigned.crt -subj "/C=NL/ST=Zuid-Holland/L=Dordrecht/O=bartsimons.me/OU=IT Department/CN=bartsimons.me" >/dev/null 2>&1
    currentdate=$(date)
    echo "" >> /opt/httpd/conf/httpd.conf
    echo "# Appended at: ${currentdate}" >> /opt/httpd/conf/httpd.conf
    echo "LoadModule ssl_module modules/mod_ssl.so" >> /opt/httpd/conf/httpd.conf
    echo "<FilesMatch \.php$>" >> /opt/httpd/conf/httpd.conf
    echo "  SetHandler application/x-httpd-php" >> /opt/httpd/conf/httpd.conf
    echo "</FilesMatch>" >> /opt/httpd/conf/httpd.conf
    echo "Listen 443" >> /opt/httpd/conf/httpd.conf
    echo "<VirtualHost *:443>" >> /opt/httpd/conf/httpd.conf
    echo "  SSLEngine on" >> /opt/httpd/conf/httpd.conf
    echo "  SSLCertificateFile /opt/certificates/selfsigned.crt" >> /opt/httpd/conf/httpd.conf
    echo "  SSLCertificateKeyFile /opt/certificates/selfsigned.key" >> /opt/httpd/conf/httpd.conf
    echo "</VirtualHost>" >> /opt/httpd/conf/httpd.conf

    echo "You can start the HTTPD daemon with:"
    echo "/opt/httpd/bin/httpd"
    echo ""
    echo "Done!"
    echo ""
    echo ""
}

This has been tested on CentOS 7 x64.

You can start MySQL with this command:

/opt/mysql/bin/mysqld --user=mysql --datadir=/opt/mysql/data --socket=/opt/mysql/data/mysql.sock

And you can start httpd with this command:

/opt/httpd/bin/httpd

Should you run into an issue: feel free to leave a comment!