Skip to content

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.

  • 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.

The loader is not a single server-wide component. Each PHP version has:

  • its own php.ini in /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 .so file.

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 _ts suffix. A thread-safe PHP build needs the _ts file.
  • 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.so for PHP 8.2.

The loader runs files produced by older encoders as well, so updating it does not require re-encoding the application.

Start with the ini files, because they record exactly which installation and which file path are in use:

Terminal window
grep -rl ioncube /etc/php/*/*/conf.d/ 2>/dev/null

Then read each match:

Terminal window
for f in $(grep -rl ioncube /etc/php/*/*/conf.d/ 2>/dev/null); do
echo "--- $f"
cat "$f"
done

A 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:

Terminal window
ls -d /etc/php/*/cli /etc/php/*/cgi /etc/php/*/fpm /etc/php/*/apache2 2>/dev/null

Create a dated directory and copy the binaries and configuration into it. The checksums let you prove afterwards exactly which file is installed:

Terminal window
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/"
done
for so in $(grep -rho '/[^ ]*ioncube[^ ]*\.so' /etc/php/*/*/conf.d/ 2>/dev/null | sort -u); do
cp -a "$so" "$BK/"
sha256sum "$so"
done

Also record the version each SAPI reports now, using the SAPI itself rather than the CLI proxy:

Terminal window
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 none
done

Adjust 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:

Terminal window
cd /root
curl -fsSLO https://downloads.ioncube.com/loader_downloads/ioncube_loaders_lin_x86-64.tar.gz
ls -l ioncube_loaders_lin_x86-64.tar.gz
sha256sum ioncube_loaders_lin_x86-64.tar.gz

Confirm the architecture before you continue, because the wrong package loads into nothing:

Terminal window
uname -m
ldd --version | head -1

x86_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:

Terminal window
tar -tzf ioncube_loaders_lin_x86-64.tar.gz | grep '\.so$' | sed 's#.*/##' | sort
tar -xzf ioncube_loaders_lin_x86-64.tar.gz

The archive extracts to a directory named ioncube/.

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:

Terminal window
DST=/usr/local/ioncube
install -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:

Terminal window
printf 'zend_extension = /usr/local/ioncube/ioncube_loader_lin_8.4.so\n' \
> /etc/php/8.4/fpm/conf.d/00-ioncube.ini

Repeat for cli, cgi and fpm wherever those directories exist. The 00- prefix is what keeps the loader ahead of OPcache.

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:

Terminal window
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.

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:

Terminal window
systemctl reload php8.1-fpm php8.2-fpm php8.3-fpm

A reload lets existing requests finish. A restart is not needed, and on a busy server it briefly interrupts every request.

The CLI result alone proves nothing about the website. Check all three layers that are present.

Command line and CGI:

Terminal window
/usr/bin/php8.2 -r 'echo phpversion("ionCube Loader"), PHP_EOL;'
/usr/bin/php-cgi8.2 -v | grep ionCube

The FastCGI process manager:

Terminal window
/usr/sbin/php-fpm8.2 -i | grep -iE 'Loaded Configuration|ionCube'

The running workers, which shows the file each worker actually mapped at startup:

Terminal window
for p in $(pgrep -f 'php-fpm: pool'); do
grep ioncube /proc/$p/maps 2>/dev/null | awk '{print $6}' | sort -u
done | sort -u

Every 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:

Terminal window
grep -i 'ioncube\|encoded file' /var/log/apache2/error.log /var/log/php*-fpm.log 2>/dev/null | tail

No output is the expected result.

Restore the saved files and reload:

Terminal window
BK=/root/ioncube-before-20261022
install -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-fpm

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