Bart Simons

Bart Simons

Thoughts, stories and ideas.

Bart Simons




Compiling a LAMP stack for CentOS - Tutorial

Bart SimonsBart Simons

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:


TIMEFORMAT='It took %R seconds to complete this process.'
time {
	# Defining variables

	# 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 -o libxml2.tar.gz >/dev/null 2>&1
	curl -o openssl.tar.gz >/dev/null 2>&1
	curl -o zlib.tar.gz >/dev/null 2>&1
	curl -o httpd.tar.gz >/dev/null 2>&1
	curl -o pcre.tar.gz >/dev/null 2>&1
	curl -o apr.tar.gz >/dev/null 2>&1
	curl -o apr-util.tar.gz >/dev/null 2>&1
	curl -o ncurses.tar.gz >/dev/null 2>&1
	curl -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 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/ -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/ Department/" >/dev/null 2>&1
	echo "" >> /opt/httpd/conf/httpd.conf
	echo "# Appended at: ${currentdate}" >> /opt/httpd/conf/httpd.conf
	echo "LoadModule ssl_module modules/" >> /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:


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

Bart Simons

Bart Simons