How to Check and Update the ionCube Loader on a Linux Server
A server can run several PHP versions at once, each with its own command line binary, CGI binary and FastCGI process manager. The ionCube Loader is a Zend extension, so every one of those installations needs its own copy of the loader, and each copy is loaded from its own php.ini scan directory. Updating only the one you tested leaves the website that matters still running the old loader, which is why a panel or application can keep reporting an outdated loader after an update that looked successful.
This guide shows you how to find every PHP installation that loads the loader, replace each binary from the official package, confirm the result in each SAPI, and put everything back if a site stops working. It is written for administrators with root access to a Debian or Ubuntu server, and the same method applies to any distribution that keeps PHP configuration under /etc/php.
Last reviewed: 22 October 2026, against ionCube Loader 15.5.1 (Linux x86-64 package released 18 September 2026, checked at https://www.ioncube.com/loaders.php). This guide is written for Noiz hosting and is kept current against ionCube. It complements, and does not replace, the official ionCube documentation linked below.
Official Documentation Reference
Section titled “Official Documentation Reference”- ionCube Loader downloads and release notes: the current package per platform, and what changed in each loader release.
- ionCube Loader Wizard: a PHP script that identifies the correct loader file for a machine.
- PHP configuration file: how
php.iniand the additional.iniscan directories are read. - PHP-FPM configuration: pools, sockets and graceful reloads.
Prerequisites
Section titled “Prerequisites”- Root access to the server, over SSH or a console.
- A copy of the current loader files and their configuration before you touch anything. The commands below create one.
- A note of which websites use encoded files, so you can test the right ones afterwards.
- A short maintenance window if encoded applications serve live traffic. A graceful reload does not drop requests, but a wrong loader does.
1. Understand What You Are Updating
Section titled “1. Understand What You Are Updating”The loader is not a single server-wide component. Each PHP version has:
- its own
php.iniin/etc/php/<version>/<sapi>/, - its own scan directory,
/etc/php/<version>/<sapi>/conf.d/, - and an ini file there, usually
00-ioncube.ini, that points at one.sofile.
The same .so path may be shared by the CLI, CGI and FPM SAPIs of one PHP version, or each SAPI may have its own path. Read the ini files rather than guessing the layout.
Two details matter when choosing the replacement file:
- Non-thread-safe or thread-safe. Linux builds of PHP are normally non-thread-safe, so you need the file without the
_tssuffix. A thread-safe PHP build needs the_tsfile. - The PHP branch. A loader built for one PHP branch does not load into another. The package ships one file per branch, for example
ioncube_loader_lin_8.2.sofor PHP 8.2.
The loader runs files produced by older encoders as well, so updating it does not require re-encoding the application.
2. Inventory Every PHP That Loads It
Section titled “2. Inventory Every PHP That Loads It”Start with the ini files, because they record exactly which installation and which file path are in use:
grep -rl ioncube /etc/php/*/*/conf.d/ 2>/dev/nullThen read each match:
for f in $(grep -rl ioncube /etc/php/*/*/conf.d/ 2>/dev/null); do echo "--- $f" cat "$f"doneA PHP version with no matching ini file never had the loader, so there is nothing to update there. Check which SAPIs that version actually has:
ls -d /etc/php/*/cli /etc/php/*/cgi /etc/php/*/fpm /etc/php/*/apache2 2>/dev/null3. Record the Before State
Section titled “3. Record the Before State”Create a dated directory and copy the binaries and configuration into it. The checksums let you prove afterwards exactly which file is installed:
BK=/root/ioncube-before-$(date +%Y%m%d)mkdir -p "$BK"for f in $(grep -rls ioncube /etc/php/*/*/conf.d/ 2>/dev/null); do cp -a "$f" "$BK/"donefor so in $(grep -rho '/[^ ]*ioncube[^ ]*\.so' /etc/php/*/*/conf.d/ 2>/dev/null | sort -u); do cp -a "$so" "$BK/" sha256sum "$so"doneAlso record the version each SAPI reports now, using the SAPI itself rather than the CLI proxy:
for v in 8.1 8.2 8.3; do printf '%s cli: ' "$v"; /usr/bin/php$v -r 'echo phpversion("ionCube Loader") ?: "none", PHP_EOL;' printf '%s cgi: ' "$v"; /usr/bin/php-cgi$v -v 2>/dev/null | grep -oE 'ionCube PHP Loader[^,]*v[0-9]+\.[0-9]+\.[0-9]+' || echo none printf '%s fpm: ' "$v"; /usr/sbin/php-fpm$v -i 2>/dev/null | grep -oE 'ionCube PHP Loader[^,]*v[0-9]+\.[0-9]+\.[0-9]+' || echo nonedoneAdjust the version list to the ones found in step 2.
4. Download and Check the Official Package
Section titled “4. Download and Check the Official Package”Download the package for the platform and architecture. This example is 64-bit Linux with glibc:
cd /rootcurl -fsSLO https://downloads.ioncube.com/loader_downloads/ioncube_loaders_lin_x86-64.tar.gzls -l ioncube_loaders_lin_x86-64.tar.gzsha256sum ioncube_loaders_lin_x86-64.tar.gzConfirm the architecture before you continue, because the wrong package loads into nothing:
uname -mldd --version | head -1x86_64 means the 64-bit Intel/AMD package. A musl system such as Alpine needs the lin-musl package instead, and ARM needs its own package.
List the loader files inside the archive and compare them with the versions you found in step 2:
tar -tzf ioncube_loaders_lin_x86-64.tar.gz | grep '\.so$' | sed 's#.*/##' | sorttar -xzf ioncube_loaders_lin_x86-64.tar.gzThe archive extracts to a directory named ioncube/.
5. Install One File per PHP Branch
Section titled “5. Install One File per PHP Branch”Keep every branch’s loader in one directory and point every ini file at it. The next update is then a file replacement, not a search through version-specific paths:
DST=/usr/local/ioncubeinstall -d -m 0755 "$DST"install -o root -g root -m 0755 /root/ioncube/ioncube_loader_lin_8.2.so "$DST/"One .so per PHP branch, and never rename one branch’s file for another.
If an existing ini names a different path, the file and the ini must still agree exactly: either leave that file where it is or edit the ini to the new path.
For a branch that has no loader yet, create the ini in each SAPI directory it has, using the Scan this dir value that SAPI reports:
printf 'zend_extension = /usr/local/ioncube/ioncube_loader_lin_8.4.so\n' \ > /etc/php/8.4/fpm/conf.d/00-ioncube.iniRepeat for cli, cgi and fpm wherever those directories exist. The 00- prefix is what keeps the loader ahead of OPcache.
6. Keep the Load Order
Section titled “6. Keep the Load Order”The loader is a zend_extension, and it must be loaded before OPcache. Debian-style packaging handles this with a filename prefix: 00-ioncube.ini sorts before 10-opcache.ini, because the scan directory is read in filename order.
If you ever rename or renumber the ionCube ini, check the result:
php -i | grep -iE 'Additional .ini files parsed|ionCube Loader|OpCache'A loader line that appears after the OPcache line is a configuration fault, even if it happens to work on the day.
7. Reload the SAPIs
Section titled “7. Reload the SAPIs”The command line picks up the new file on its next invocation. Long-running processes keep the old loader until they are replaced, so reload each FastCGI process manager gracefully:
systemctl reload php8.1-fpm php8.2-fpm php8.3-fpmA reload lets existing requests finish. A restart is not needed, and on a busy server it briefly interrupts every request.
8. Verify Each SAPI Separately
Section titled “8. Verify Each SAPI Separately”The CLI result alone proves nothing about the website. Check all three layers that are present.
Command line and CGI:
/usr/bin/php8.2 -r 'echo phpversion("ionCube Loader"), PHP_EOL;'/usr/bin/php-cgi8.2 -v | grep ionCubeThe FastCGI process manager:
/usr/sbin/php-fpm8.2 -i | grep -iE 'Loaded Configuration|ionCube'The running workers, which shows the file each worker actually mapped at startup:
for p in $(pgrep -f 'php-fpm: pool'); do grep ioncube /proc/$p/maps 2>/dev/null | awk '{print $6}' | sort -udone | sort -uEvery path printed must be a file that still exists and carries the new checksum.
The website itself: ask the application to report the version through the SAPIs it really uses. A temporary file in the site root is enough, and it must be deleted immediately afterwards:
<?php echo phpversion("ionCube Loader");Then check the server’s error log for new loader messages:
grep -i 'ioncube\|encoded file' /var/log/apache2/error.log /var/log/php*-fpm.log 2>/dev/null | tailNo output is the expected result.
9. Roll Back
Section titled “9. Roll Back”Restore the saved files and reload:
BK=/root/ioncube-before-20261022install -o root -g root -m 0755 "$BK"/ioncube_loader_lin_8.*.so /usr/local/ioncube/systemctl reload php8.1-fpm php8.2-fpm php8.3-fpmTroubleshooting
Section titled “Troubleshooting”The command line shows the new version but the website still shows the old one. The web SAPI has a different ini directory or the pool was not reloaded. Compare php-fpmX.Y -i with php -i and check the Additional .ini files parsed line.
A site shows “encoded file requires the ionCube Loader”. That SAPI loads nothing, or a loader too old for the encoded file. Confirm the ini file sits in the scan directory for the SAPI that serves the site, not only in the CLI directory.
A duplicate loader warning appears, or PHP fails to start. Two zend_extension lines point at ionCube binaries. Keep one per SAPI and remove the other.
There is no loader file for a PHP branch in the current package. Older branches are dropped from current releases. Leave that branch on its last supported loader and plan to move the application to a supported PHP version; do not copy a loader from another branch.
The website loads the loader but the application still refuses to start. Check the encoded file’s own error message for the minimum loader version it requires, and confirm the file was not copied with the wrong _ts suffix.
[noiz] | disrupt the signal