Install PHP5.2, PHP5.6 and PHP7.0 as Apache + FCGI on AlmaLinux8 / Centos8
This might sound very strange in 2023, but here are HOW-TO instructions on how to install Apache with FCGI and various number of old PHP versions, starting with PHP5.2 and up to PHP8.0.
In our company reason for such setup was an internal (and very important) CRM system, that we wrote ourselves and still keep maintaining, but never had time and resources to make it compatible with at least PHP7. Up to recent time everything was running on Centos6 server, but the need to migrate to different data center put us (read – me) into situation, where I had to migrate that old system to newer OS.
Over the years my personal preference has shifted to Debian, but after failing to compile old code on the latest Debian – I gave up and gave AlmaLinux8 a try.
Drop me a message, if you find this article interested and helpful!
P.S: this article is not intended for newbies, but for system administrators, who actually understand it. Of course, if you need, I can help, just drop me a line.
Update 6.August: turns out, PHP5.2 can be compiled with openSSL 1.0.2 and with that version it will support much broader range of ciphers and features.
Update 7.August: added –with-freetype-dir=/usr to PHP5.2 compilation to support GD TTF related functions for adding smooth texts to images.
Update 8.September: added instructions for PHP7.4 compilation and added –with-external-gd option to PHP8.0
Let’s assume we are on a clean AlmaLinux8 setup.
First of all – disable selinux, it will make things easier. After all – you should be careful this setup, but you don’t want extra problems. The best security for such setup is to limit PHP using open_basedir.
– disable selinux in /etc/sysconfig/selinux
# install large group of all kind of useful things yum groupinstall "Development Tools" # I suppose you will want MySQL / MariaDB server # AlmaLinux8 comes with nice MariaDB 10.3 yum install mariadb-common mariadb-server mariadb mariadb-devel mariadb-server-utils # Also let's not forget about install Apache and mod_fcgi yum install httpd httpd-devel httpd-tools mod_fcgid spawn-fcgi fcgi fcgi-devel # this is place, where we will be compiling things mkdir /root/install # First we will install old libGD # Old PHP do not like latest GD... # install PNG, JPG, FreeType, XML and ZIP packages yum install wget libpng-devel libjpeg-turbo-devel freetype-devel fontconfig-devel libxml2-devel sqlite sqlite-devel sqlite-libs libsqlite3x libsqlite3x-devel libzip libzip-devel # now head to install GD 2.0.33 - lovely old version cd /root/install wget https://src.fedoraproject.org/lookaside/extras/gd/gd-2.0.33.tar.gz/be0a6d326cd8567e736fbc75df0a5c45/gd-2.0.33.tar.gz tar -zxf gd-2.0.33.tar.gz cd gd-2.0.33 ./configure --prefix=/opt/libgd --with-jpeg --with-png --with-freetype make && make install cd /opt/libgd ln -s lib lib64 # Also we need library and includes for MySQL. # Unfortunately old PHP don't recognize MariaDB's development package # We download MySQL source and just use it for compilation cd /root/install wget https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.42-linux-glibc2.12-x86_64.tar.gz tar -zxf mysql-5.7.42-linux-glibc2.12-x86_64.tar.gz cd mysql-5.7.42-linux-glibc2.12-x86_64 mkdir -p /opt/mysql-5.7 mv bin /opt/mysql-5.7/ mv include /opt/mysql-5.7/ mv lib /opt/mysql-5.7/ mv share /opt/mysql-5.7/ cd /opt/mysql-5.7 ln -s lib lib64 # main issue with old PHP are incompatibility with newest OpenSSL and Curl # that's why we are going to install old versions ### ### PHP 5.2 ### # update 6.AUGUST.2023 - PHP5.2 can be installed with openSSL 1.0.2 # follow steps for openSSL + curl for 1.0.2 described below cd /root/install wget https://www.openssl.org/source/old/1.0.2/openssl-1.0.2u.tar.gz tar -zxf openssl-1.0.2u.tar.gz cd openssl-1.0.2u ./config --prefix=/opt/openssl-1.0.2 shared zlib make -j 8 make install cd /opt/openssl-1.0.2 ln -s lib lib64 # and compile another version of LibCurl, that uses openSSL 1.0.2 cd /root/install rm -rf curl-8.2.1* # download source from https://curl.se/download.html wget https://curl.se/download/curl-8.2.1.tar.gz tar -zxf curl-8.2.1.tar.gz cd curl-8.2.1 ./configure --prefix=/opt/libcurl-ssl-1.0.2 --enable-http --enable-ftp --disable-ldap --disable-dict --disable-telnet --disable-tftp --enable-thread --enable-crypto-auth --enable-cookies --with-zlib --with-openssl=/opt/openssl-1.0.2 make && make install cd /opt/libcurl-ssl-1.0.2 ln -s lib lib64 # Now let's build PHP 5.2 # There was some requirement to patch original version, I could not find original # post about it, but had patched version laying around. cd /root/install wget aleksandrov.eu/php-5.2.17.patched.tar.gz tar -zxf php-5.2.17.patched.tar.gz cd php-5.2.17 make clean rm -f config.log rm -f config.cache ./configure --prefix=/opt/php-5.2 --enable-fastcgi --enable-force-cgi-redirect --with-zlib --with-curl=/opt/libcurl-ssl-1.0.2 --enable-exif --with-gd=/opt/libgd --with-gettext --enable-mbstring --with-mysql=/opt/mysql-5.7 --enable-zip --with-pear --with-openssl=/opt/openssl-1.0.2 --with-libxml-dir=/usr --with-pdo-mysql --libdir=lib64 --enable-embedded-mysqli --with-mysql-sock=/var/lib/mysql/mysql.sock --enable-sockets --with-freetype-dir=/usr make && make install # don't forget to copy php.ini file to /opt/php-5.2/lib/php.ini and configure it # configuration examples for Apache and FCGI will be shown later. # Head to compiling PHP5.6 # PHP5.6 also requires OpenSSL 1.0.2 # compiling PHP5.6 cd /root/install wget https://www.php.net/distributions/php-5.6.40.tar.gz tar -zxf php-5.6.40.tar.gz cd php-5.6.40 make clean rm -f config.log rm -f config.cache ./configure --prefix=/opt/php-5.6 --disable-fileinfo --disable-posix --enable-bcmath --enable-calendar --enable-exif --enable-ftp --enable-gd-native-ttf --enable-libxml --enable-mbstring --enable-pdo --enable-soap --enable-sockets --enable-zip --with-curl=/opt/libcurl-ssl-1.0.2 --with-freetype-dir=/usr --with-gd --with-pear --with-gettext --with-mysql=/opt/mysql-5.7 --with-openssl=/opt/openssl-1.0.2 --with-pdo-mysql --with-zlib --enable-embedded-mysqli --enable-opcache make && make install # do not forget to copy php.ini to /opt/php-5.6/lib/php.ini # compiling PHP7.0 # Now we don't need any special openSSL, therefore we use system OS packages cd /root/install wget https://www.php.net/distributions/php-7.0.33.tar.gz tar -zxf php-7.0.33.tar.gz cd php-7.0.33 make clean rm -f config.log rm -f config.cache ./configure --prefix=/opt/php-7.0 --enable-mysqlnd --disable-fileinfo --disable-posix --enable-bcmath --enable-calendar --enable-exif --enable-ftp --enable-gd-native-ttf --enable-libxml --enable-mbstring --enable-pdo --enable-sockets --enable-zip --with-curl --with-freetype-dir=/usr --with-gd --with-pear --with-gettext --with-openssl --with-pdo-mysql=mysqlnd --with-zlib --with-openssl make && make install # do not forget to copy php.ini to /opt/php-7.0/lib/php.ini # compiling PHP7.2 cd /root/install wget https://www.php.net/distributions/php-7.2.34.tar.gz tar -zxf php-7.2.34.tar.gz cd php-7.2.34 make clean rm -f config.log rm -f config.cache ./configure --prefix=/opt/php-7.2 --enable-mysqlnd --disable-fileinfo --disable-posix --enable-bcmath --enable-calendar --enable-exif --enable-ftp --enable-libxml --enable-mbstring --enable-pdo --enable-sockets --enable-zip --with-curl --with-gd --with-pear --with-gettext --with-openssl --with-pdo-mysql=mysqlnd --with-zlib --with-openssl --with-mysqli make && make install # do not forget to copy php.ini to /opt/php-7.2/lib/php.ini # compiling PHP 7.4 # PHP7.4+ requires oniguruma. # Precompiled oniguruma package for unknown reason is not being recognized # therefore we are installing it manually. cd /root/install git clone https://github.com/kkos/oniguruma.git cd oniguruma ./autogen.sh ./configure --prefix=/usr --libdir=/usr/lib64 make && make install # install PHP7.4 cd /root/install wget https://www.php.net/distributions/php-7.4.33.tar.gz tar -zxf php-7.4.33.tar.gz cd php-7.4.33 make clean rm -f config.log rm -f config.cache './configure' '--prefix=/opt/php-7.4' '--enable-mysqlnd' '--disable-fileinfo' '--disable-posix' '--enable-bcmath' '--enable-calendar' '--enable-exif' '--enable-ftp' '--enable-mbstring' '--enable-pdo' '--enable-sockets' '--with-zip' '--with-curl' '--enable-gd' '--with-pear' '--with-gettext' '--with-openssl' '--with-pdo-mysql=mysqlnd' '--with-zlib' '--with-openssl' '--with-mysqli' '--with-external-gd' make -j 8 && make install # compiling PHP8.0 cd /root/install wget https://www.php.net/distributions/php-8.0.28.tar.gz tar -zxf php-8.0.28.tar.gz cd php-8.0.28 make clean rm -f config.log rm -f config.cache ./configure --prefix=/opt/php-8.0 --enable-mysqlnd --disable-fileinfo --disable-posix --enable-bcmath --enable-calendar --enable-exif --enable-ftp --enable-mbstring --enable-pdo --enable-sockets --with-curl --with-pear --with-gettext --with-openssl --enable-mysqlnd --with-pdo-mysql --with-zlib --with-openssl --with-mysqli --with-zip --enable-gd --with-external-gd make && make install # do not forget to copy php.ini to /opt/php-8.0/lib/php.ini
PHP settings, that I always check and change
open_basedir = /home:/opt:/tmp
expose_php = Off
max_execution_time = 180
max_input_vars = 4000
memory_limit = 512M
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT & ~E_NOTICE & ~E_WARNING
post_max_size = 100M
; default_charset = "UTF-8"
cgi.force_redirect = 1
upload_max_filesize = 100M
mysqli.default_socket = /var/lib/mysql/mysql.sock
pdo_mysql.default_socket=/var/lib/mysql/mysql.sock
mysqlnd.collect_statistics = Off
date.timezone = Europe/Oslo
Apache settings to check and set
in file /etc/httpd/conf.modules.d/10-fcgid.conf add
AddHandler fcgid-script .php
FcgidMinProcessesPerClass 1
FcgidIdleScanInterval 60
FcgidIdleTimeout 300
FcgidMaxProcessesPerClass 30
FcgidMaxProcesses 200
FcgidMaxRequestsPerProcess 300
FcgidIOTimeout 3600
FcgidProcessLifeTime 900
FcgidMaxRequestLen 1073741824
FcgidIOTimeout 300
FcgidBusyTimeout 3600
FcgidFixPathinfo 1
in file /etc/httpd/conf.modules.d/00-mpm.conf
– disable mod_mpm_event
– enable mod_mpm_worker
in file /etc/httpd/conf.modules.d/00-base.conf
– make sure, that suexec module is enabled
FCGI script example
Very important note: all FCGI scripts must reside under /var/www folder due to precompiled permission / setting in the mod_suexec module. I have spent several days trying to figure this out. I usually put website files in appropriate user’s home folder, for example: /home/user1/public_html – but FCGI starter scripts must still be under /var/www. I put them in /var/www/php-wrappers/user1/ folder – basically you must have separate folder for each user’s FCGI scripts. Also for configuration flexibility I always put php.ini
Example of FCGI script for PHP5
Assume we have user “randweb“.
– make folder for his FCGI scripts – /var/www/php-wrappers/randweb
– copy php.ini from PHP5.2 installation to this folder, call it “php-5.2.ini”, just in case you might need to have several different versions running for the same user (yes, this is possible!)
– create file /var/www/php-wrappers/randweb/php52
– put the following content into that file:
#!/bin/sh PHPRC="/opt/php-5.2/lib" export PHPRC PHP_FCGI_MAX_REQUESTS=500 export PHP_FCGI_MAX_REQUESTS exec /opt/php-5.2/bin/php-cgi -c /var/www/php-wrappers/randweb/php-5.2.ini
Important: Now remember to change owner of the FCGI folder and all the files inside. Also you must make FCGI script executable.
chmod +x /var/www/php-wrappers/randweb/php52
chown randweb:randweb /var/www/php-wrappers/randweb -R
Example of VirtualHost
Please note paths to FCGI script and user folders. As I mentioned, I put all user webfiles in /home/username/public_html. Apache’s configuration is usually laying in /etc/httpd/virtual-hosts (right, you need to make and include that folder!)
<VirtualHost *:80> ServerName randweb.hosting.guru DocumentRoot /home/randweb/public_html ServerAdmin [email protected] UseCanonicalName Off <Directory /var/www/php-wrappers/> SetHandler fcgid-script Options +ExecCGI # Customize the next two directives for your requirements. Order allow,deny Allow from all </Directory> <Directory /home/randweb/public_html> FCGIWrapper /var/www/php-wrappers/randweb/php52 .php Require all granted AllowOverride All Options All -Indexes Options +ExecCGI Order allow,deny Allow from all </Directory> SuexecUserGroup randweb randweb </VirtualHost>
For other PHP versions steps are very similar. You just need to set path to correct PHP version in the FCGI script. And if you want to have different PHP version for a subfolder – you can have it by adding <Directory> block and creating FCGI script with different PHP version.
Where to check for errors
PHP / Apache errors are in:
/var/log/httpd/error_log
SuEXEC errors are in:
/var/log/secure
I think that is so far, what I can share with you. If you have questions of find some mistakes – please drop me a line. Happy 2023!