TheHolbi
Priority Members
-
Joined
-
Last visited
Solutions
-
TheHolbi's post in How to Add Custom PHP-FPM 8.4 / 8.5 Support to CWP on AlmaLinux 9.x was marked as the answerFull tutorial with GUI integration, fixed OpenSSL support, external modules, and a working custom PHP builder.
This guide explains how to properly add PHP 8.4 and PHP 8.5 to Control Web Panel (CWP) on EL9-based systems.
Unlike older CWP releases, CWP does not provide official PHP 8.4/8.5 packages yet — but with the steps below you can fully integrate them into and you can also fix the PHP 8.3 OpenSSL problem based on this:
✔ the CWP PHP Selector GUI
✔ Apache / Nginx vhosts
✔ external PECL modules
✔ system services
✔ CSF/Monit integration
This article provides everything: file paths, scripts, corrections, and the build steps.
⚙️ Step 1 — Extend the CWP GUI to Support PHP 8.4 and 8.5
CWP reads available PHP versions from:
/usr/local/cwpsrv/htdocs/resources/conf/el9/php-fpm_selector/versions.iniAdd the new PHP versions like:
[8.3] version[]=8.3.28 version[]=8.3.27 version[]=8.3.25 version[]=8.3.21 version[]=8.3.20 version[]=8.3.19 version[]=8.3.17 version[]=8.3.16 version[]=8.3.15 version[]=8.3.14 version[]=8.3.13 version[]=8.3.12 version[]=8.3.11 version[]=8.3.10 version[]=8.3.9 version[]=8.3.8 version[]=8.3.7 version[]=8.3.6 version[]=8.3.4 version[]=8.3.3 version[]=8.3.2 version[]=8.3.1 version[]=8.3.0 [8.4] version[]=8.4.15 version[]=8.4.14 version[]=8.4.13 version[]=8.4.12 version[]=8.4.11 version[]=8.4.10 version[]=8.4.9 version[]=8.4.8 version[]=8.4.7 version[]=8.4.6 version[]=8.4.4 version[]=8.4.3 version[]=8.4.2 version[]=8.4.1 version[]=8.4.0 [8.5] version[]=8.5.0 This makes the versions selectable in the GUI.
If you don't want to make previous PHP 8.4 versions optional under 8.4.14, you can leave them out of the list.
⚙️ Step 2 — Create 8.4.ini and 8.5.ini GUI Templates
Location:
/usr/local/cwpsrv/htdocs/resources/conf/el9/php-fpm_selector/Create these files based on the sample and content of 8.3.ini:
8.4.ini 8.5.ini Both must contain a corrected OpenSSL section:
[openssl] default=1 option="--with-openssl=/usr" info-file=openssl.txt (Older CWP templates use deprecated OpenSSL paths that break EL9 builds. The corrected version above is mandatory. And similarly, the OpenSSL section in the 8.3.ini file must be corrected.)
These files provide the GUI-driven configure flags that our builder script will later use.
⚙️ Step 3 — Create External and Pre Run Modules for PHP 8.4 and 8.5
Create these directories and update the content of 8.3 folder with the linked ZIP file:
/usr/local/cwpsrv/htdocs/resources/conf/el9/php-fpm_selector/external_modules/8.3 /usr/local/cwpsrv/htdocs/resources/conf/el9/php-fpm_selector/external_modules/8.4 /usr/local/cwpsrv/htdocs/resources/conf/el9/php-fpm_selector/external_modules/8.5Populate each directory with the updated scripts:
apcu.sh
imagick.sh
memcache.sh
memcached.sh
mailparse.sh
mongodb.sh
redis.sh
ssh2.sh
uploadprogress.sh
xdebug.sh
yaz.sh
sodium.sh
sourceguardian.sh
sqlsrv.sh
ioncube.sh
(With proper loader URL handling: stable for 8.4, beta for 8.5.)
👉 Here is the ZIP file with all corrected module scripts to this post for download:
External_Modules
Create these directories and update the content of 8.3 folder with the linked ZIP file:
/usr/local/cwpsrv/htdocs/resources/conf/el9/php-fpm_selector/pre_run/8.3 /usr/local/cwpsrv/htdocs/resources/conf/el9/php-fpm_selector/pre_run/8.4 /usr/local/cwpsrv/htdocs/resources/conf/el9/php-fpm_selector/pre_run/8.5Pre Run Modules
⚙️ Step 4 — Install the Custom Builder Script
Place the builder script in:
/root/build-php-fpm84-el9.sh This script:
✔ reads the GUI-generated configure template
✔ enforces OpenSSL 3.x for EL9
✔ builds PHP cleanly under /opt/alt/php-fpm84/usr/
✔ installs FPM service, ini files, sockets
✔ compiles all external modules
✔ integrates CSF and Monit
✔ logs every step
You can rewrite this script to install PHP 8.3.28 or PHP 8.5.0 by changing just a few variables.
Here is the corrected PHP compiler script located in /root/build-php-fpm84-el9.sh file:
#!/bin/bash set -euo pipefail set -x # --- Basic variables --- PHPMAJOR="84" # php-fpm84 PHPVER="8.4.15" # PHP version FPMDIR="/opt/alt/php-fpm${PHPMAJOR}" CONFBASE="/usr/local/cwp/.conf/php-fpm_conf" arch=$(uname -m) if [[ "$arch" == "x86_64" ]]; then platform="x86-64" libdir="/usr/lib64" else platform="x86" libdir="/usr/lib" fi # --- Packages for Build (EL9) --- dnf -y install \ krb5-devel glibc-common gnutls-devel \ libargon2 libargon2-devel libbsd-devel \ perl libzip libzip-devel pcre2 pcre2-devel \ libavif libavif-devel \ uw-imap-devel \ openssl-devel # If there is any old CWP OpenSSL hack left, don't use it.: if [ -d /usr/local/opensslso ]; then echo "WARN: /usr/local/opensslso exists, but we DO NOT USE for compiling PHP (OpenSSL 1.1 hack)." fi # --- Force OpenSSL 3.x --- export PKG_CONFIG_PATH=/usr/lib64/pkgconfig export OPENSSL_CFLAGS="-I/usr/include" export OPENSSL_LIBS="-L/usr/lib64" export LDFLAGS="-lssl -lcrypto" # --- CWP pre-conf, if exists (e.g.: pcre2, & other libs) --- if [ -e "${CONFBASE}/php${PHPMAJOR}_pre.conf" ]; then bash "${CONFBASE}/php${PHPMAJOR}_pre.conf" fi # --- PHP SOURCE DOWNLOAD CHECK: CWP CDN → OFFICIAL php.net → GitHub fallback --- CWP_URL="http://static.cdn-cwp.com/files/php/php-${PHPVER}.tar.gz" PHPNET_URL="https://www.php.net/distributions/php-${PHPVER}.tar.gz" GITHUB_URL="https://codeload.github.com/php/php-src/tar.gz/refs/tags/php-${PHPVER}" # Function: check HTTP 200 + verify tar.gz content check_and_verify() { local url="$1" local testfile="/tmp/php-test-${PHPVER}.tar.gz" echo "Checking: $url" # First check HTTP status code if ! curl -I -L -s "$url" | grep -q "200"; then echo " → HTTP check failed" return 1 fi # Download temporary test file if ! wget -q "$url" -O "$testfile"; then echo " → Download failed" return 1 fi # Validate MIME type of tar.gz if file "$testfile" | grep -qiE "gzip compressed data|tar archive"; then rm -f "$testfile" echo " → Valid TAR.GZ" return 0 fi echo " → Invalid TAR.GZ (HTML or wrong file)" rm -f "$testfile" return 1 } # Check sources in order (CWP → php.net → GitHub) if check_and_verify "$CWP_URL"; then PHPSOURCE="$CWP_URL" elif check_and_verify "$PHPNET_URL"; then PHPSOURCE="$PHPNET_URL" elif check_and_verify "$GITHUB_URL"; then PHPSOURCE="$GITHUB_URL" else echo "ERROR: Could not download a valid PHP source for version ${PHPVER}" exit 1 fi echo "Using source: $PHPSOURCE" # --- Build directory --- rm -rf /usr/local/src/php-build mkdir -p /usr/local/src/php-build cd /usr/local/src/php-build wget -q "${PHPSOURCE}" -O "php-${PHPVER}.tar.gz" tar -xvf "php-${PHPVER}.tar.gz" cd "php-${PHPVER}" # --- Configure: CWP's own php84.conf, but already wired to OpenSSL 3.x from env --- if [ ! -x "${CONFBASE}/php${PHPMAJOR}.conf" ]; then chmod +x "${CONFBASE}/php${PHPMAJOR}.conf" 2>/dev/null || true fi # IMPORTANT: LDFLAGS + PKG_CONFIG_PATH already exported bash "${CONFBASE}/php${PHPMAJOR}.conf" # --- Compiling --- if command -v nproc >/dev/null 2>&1; then make -j"$(nproc)" else make fi make install # --- PHP.ini + FPM scaffolding --- mkdir -p "${FPMDIR}/usr/php/php.d" mkdir -p "${FPMDIR}/usr/var/sockets" mkdir -p "${FPMDIR}/usr/etc/php-fpm.d" mkdir -p "${FPMDIR}/usr/etc/php-fpm.d/users" rsync php.ini-production "${FPMDIR}/usr/php/php.ini" sed -i 's/^short_open_tag.*/short_open_tag = On/' "${FPMDIR}/usr/php/php.ini" sed -i 's/^;cgi.fix_pathinfo=.*/cgi.fix_pathinfo=1/' "${FPMDIR}/usr/php/php.ini" sed -i 's/.*mail.add_x_header.*/mail.add_x_header = On/' "${FPMDIR}/usr/php/php.ini" sed -i 's@.*mail.log.*@mail.log = /usr/local/apache/logs/phpmail.log@' "${FPMDIR}/usr/php/php.ini" echo "include=${FPMDIR}/usr/etc/php-fpm.d/users/*.conf" > "${FPMDIR}/usr/etc/php-fpm.d/users.conf" echo "include=${FPMDIR}/usr/etc/php-fpm.d/*.conf" > "${FPMDIR}/usr/etc/php-fpm.conf" cat > "${FPMDIR}/usr/etc/php-fpm.d/cwpsvc.conf" <<EOF [cwpsvc] listen = ${FPMDIR}/usr/var/sockets/cwpsvc.sock listen.owner = cwpsvc listen.group = cwpsvc listen.mode = 0640 user = cwpsvc group = cwpsvc pm = ondemand pm.max_children = 25 pm.process_idle_timeout = 15s request_terminate_timeout = 0 EOF # --- Systemd service --- cp sapi/fpm/php-fpm.service "/usr/lib/systemd/system/php-fpm${PHPMAJOR}.service" sed -i "s|\${exec_prefix}|${FPMDIR}/usr|g" "/usr/lib/systemd/system/php-fpm${PHPMAJOR}.service" sed -i "s|\${prefix}|${FPMDIR}/usr|g" "/usr/lib/systemd/system/php-fpm${PHPMAJOR}.service" systemctl daemon-reload systemctl enable "php-fpm${PHPMAJOR}" # --- Loading Apache FPM module if not already present --- if [ ! -e "/usr/local/apache/conf.d/php-fpm.conf" ]; then cat > /usr/local/apache/conf.d/php-fpm.conf <<EOF <IfModule !proxy_fcgi_module> LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so </IfModule> EOF fi # --- External modules (imagick, redis, imap, etc.) --- if [ -e "${CONFBASE}/php${PHPMAJOR}_external.conf" ]; then bash "${CONFBASE}/php${PHPMAJOR}_external.conf" || true fi # --- Monitor integration --- if [ -d "/etc/monit.d" ]; then if [ ! -e "/etc/monit.d/php-fpm${PHPMAJOR}" ]; then if [ -e "/usr/local/cwpsrv/htdocs/resources/conf/monit.d/php-fpm${PHPMAJOR}" ]; then cp "/usr/local/cwpsrv/htdocs/resources/conf/monit.d/php-fpm${PHPMAJOR}" /etc/monit.d/ 2>/dev/null || true monit reload || true fi fi fi systemctl restart "php-fpm${PHPMAJOR}" # --- CSF pignore --- if [ -e "/etc/csf/csf.pignore" ]; then # PHP-FPM + PHP binary if ! grep -q "${FPMDIR}/usr/sbin/php-fpm" /etc/csf/csf.pignore; then echo "exe:${FPMDIR}/usr/sbin/php-fpm" >> /etc/csf/csf.pignore fi if ! grep -q "${FPMDIR}/usr/bin/php" /etc/csf/csf.pignore; then echo "exe:${FPMDIR}/usr/bin/php" >> /etc/csf/csf.pignore fi # memcached daemon if command -v memcached >/dev/null 2>&1; then if ! grep -q "exe:/usr/bin/memcached" /etc/csf/csf.pignore; then echo "exe:/usr/bin/memcached" >> /etc/csf/csf.pignore fi fi # redis-server daemon if command -v redis-server >/dev/null 2>&1; then if ! grep -q "exe:/usr/bin/redis-server" /etc/csf/csf.pignore; then echo "exe:/usr/bin/redis-server" >> /etc/csf/csf.pignore fi fi # Restart CSF/LFD to apply changes csf -r fi rm -rf /usr/local/src/php-build rm -rf /usr/local/src/build-dir echo "PHP ${PHPVER} (php-fpm${PHPMAJOR}) build finished successfully." It is for sample, you can modify it by your needs.
⚙️ Step 5 — Trigger the GUI Build Once
From the CWP Admin Panel:
PHP-FPM Selector → PHP 8.4 → Choose desired version of PHP → Build CWP will:
generate the build configuration files
stop early because no packages exist (expected!)
but now the config files are ready
The GUI selector
(Image on the shared link)
This step must be done once so the GUI produces:
/usr/local/cwp/.conf/php-fpm_conf/php84.conf /usr/local/cwp/.conf/php-fpm_conf/php84_pre.conf /usr/local/cwp/.conf/php-fpm_conf/php84_external.conf Our builder script depends on them.
⚙️ Step 6 — Build PHP 8.4 With Logging
Run the custom builder script manually:
bash /root/build-php-fpm84-el9.sh 2>&1 | tee /root/php84-build.log This:
logs all output
compiles PHP 8.4.14
installs extensions - e.g. IonCube loader if it was selected
reloads FPM
integrates CSF pignore entries
exe:/usr/bin/redis-server
exe:/usr/bin/memcached
After the build:
Test PHP:
/opt/alt/php-fpm84/usr/bin/php -v /opt/alt/php-fpm84/usr/sbin/php-fpm -t Verify IonCube:
grep -Ri ioncube /opt/alt/php-fpm84/usr/php/php.d/ Verify Imagick:
/opt/alt/php-fpm84/usr/bin/php -r "print_r(Imagick::getVersion());"⚙️ Repeat the Process for PHP 8.5
The steps are identical, except:
PHP version is different
ionCube loader uses the beta build
ioncube_loaders_lin_x86-64_beta.tar.gz
Here is the IonCube documentation. The PHP 8.4 is fully supported, PHP 8.5 is Beta in the moment.
🎉 Result
After completing these steps you will have:
✔ Fully working PHP 8.4 or 8.5
✔ 100% GUI-compatible (PHP Selector, vhost handler, extension manager)
✔ Proper OpenSSL 3.x integration
✔ All external PECL modules working
✔ Systemd FPM services
✔ Clean, isolated alt-PHP folders under /opt/alt
✔ No conflict with AlmaLinux REMI PHP packages
And most importantly:
You can now run PHP 8.4 / 8.5 safely in production on CWP EL9.
I also fixed the PHP - OpenSSL compilation issue in AlmaLinux 9.x with PHP 8.3.28 version of the script. PHP now uses OpenSSL 3.x.
Checking the compiled PHP versions (e.g. 8.4.14 and 8.3.28):
[root@vps ~]# /opt/alt/php-fpm84/usr/bin/php -v PHP 8.4.14 (cli) (built: Dec 1 2025 22:53:34) (NTS) Copyright (c) The PHP Group Zend Engine v4.4.14, Copyright (c) Zend Technologies with the ionCube PHP Loader v15.0.0, Copyright (c) 2002-2025, by ionCube Ltd. with Zend OPcache v8.4.14, Copyright (c), by Zend Technologies [root@vps ~]# /opt/alt/php-fpm83/usr/bin/php -v PHP 8.3.28 (cli) (built: Dec 1 2025 16:39:53) (NTS) Copyright (c) The PHP Group Zend Engine v4.3.28, Copyright (c) Zend Technologies with Zend OPcache v8.3.28, Copyright (c), by Zend Technologies [root@vps ~]# Checking OpenSSL:
[root@vps ~]# /opt/alt/php-fpm84/usr/bin/php -i | grep -i "openssl" Configure Command => './configure' '--prefix=/opt/alt/php-fpm84/usr' '--with-config-file-path=/opt/alt/php-fpm84/usr/php' '--with-config-file-scan-dir=/opt/alt/php-fpm84/usr/php/php.d' '--with-zlib=/usr' '--enable-mbstring' '--with-zip' '--enable-bcmath' '--enable-pcntl' '--enable-ftp' '--enable-exif' '--enable-calendar' '--enable-sysvmsg' '--enable-sysvsem' '--enable-sysvshm' '--with-tidy' '--with-curl' '--with-iconv' '--with-gmp' '--with-pspell' '--enable-gd' '--with-jpeg' '--with-freetype' '--enable-gd-jis-conv' '--with-webp' '--with-avif' '--with-zlib-dir=/usr' '--with-xpm' '--with-openssl=/usr' '--with-pdo-mysql=mysqlnd' '--with-gettext=/usr' '--with-bz2=/usr' '--with-mysqli' '--enable-soap' '--enable-phar' '--with-xsl' '--with-kerberos' '--enable-posix' '--enable-sockets' '--with-external-pcre' '--with-libdir=lib64' '--with-mysql-sock=/var/lib/mysql/mysql.sock' '--enable-intl' '--with-imap' '--with-imap-ssl' '--enable-fpm' '--enable-opcache' '--with-password-argon2' 'PKG_CONFIG_PATH=/usr/lib64/pkgconfig' 'OPENSSL_CFLAGS=-I/usr/include' 'OPENSSL_LIBS=-L/usr/lib64' SSL Version => OpenSSL/3.5.1 libSSH Version => libssh/0.10.4/openssl/zlib openssl OpenSSL support => enabled OpenSSL Library Version => OpenSSL 3.5.1 1 Jul 2025 OpenSSL Header Version => OpenSSL 3.5.1 1 Jul 2025 Openssl default config => /etc/pki/tls/openssl.cnf openssl.cafile => no value => no value openssl.capath => no value => no value OpenSSL support => enabled [root@vps ~]# If you have any suggestions, please feel free to write to me.
-
TheHolbi's post in CSF replacements needs was marked as the answerCSF replacement tested in old Centos 7, AlmaLinux 8.10 and AlmaLinux 9.6
The CSF project is continuing as Open Source project, the website is here: https://docs.configserver.dev/
Github: https://github.com/Aetherinox/csf-firewall
And as it was suggested in article https://www.jaspreet.net/2025/09/06/3180/how-to-fix-csf-firewall-error-oops-unable-to-download-no-host-option-provided/ you have to update the content of
/etc/csf/downloadserver
Comment out (or delete) the old content of the file and set the new line of download server: download.configserver.dev
Restart CSF and from the GUI of CWP update Firewall.
The result will be appear in the screen, and the CFS/LFD will update to the current version: Status: csf: v15.01 (CentOS Web Panel)
Or, you can use the solution suggested by @Starburst above.
-
TheHolbi's post in DKIM signature and OpenSSL 3.0.7 was marked as the answerThe DKIM signature issue was resolved as follow:
There were missing lines from the /etc/postfix/main.cf :
#DKIM milter_default_action = accept milter_protocol = 6 smtpd_milters = inet:localhost:8891 non_smtpd_milters = inet:localhost:8891 and the correct /etc/opendkim.conf was :
AutoRestart Yes AutoRestartRate 10/1h LogWhy Yes Syslog Yes SyslogSuccess Yes Mode sv Canonicalization relaxed/simple ExternalIgnoreList refile:/etc/opendkim/TrustedHosts InternalHosts refile:/etc/opendkim/TrustedHosts KeyTable refile:/etc/opendkim/KeyTable SigningTable refile:/etc/opendkim/SigningTable SignatureAlgorithm rsa-sha256 Socket inet:8891@localhost PidFile /var/run/opendkim/opendkim.pid UMask 022 UserID opendkim:opendkim TemporaryDirectory /var/tmp After completed /etc/postfix/main.cf and restarted services, the DKIM signature was properly inserted to the outgoing emails.