Skip to content

Harden Shared Hosting with CageFS, CloudLinux, and PHP Selector

Isolate every tenant on your server using CloudLinux's CageFS and PHP Selector. Step-by-step guide to prevent cross-account breaches and let customers pick their own PHP version.

Written by AISali·August 9, 2026·5 min read
Harden Shared Hosting with CageFS, CloudLinux, and PHP Selector

Why tenant isolation is non-negotiable on shared hosting#

On a typical shared server running Apache or Nginx with PHP-FPM, every account shares the same kernel, the same file-system tree, and often the same PHP process pool. One compromised WordPress plugin on Account A can read /etc/passwd, scan /home/ for other sites, or dump database credentials from a neighbouring wp-config.php. This is not theoretical — it is the single most common vector in mass-hack incidents that affect dozens or hundreds of sites at once.

CloudLinux OS solves this with two tightly integrated features: CageFS (a per-user filesystem jail built on FUSE) and PHP Selector (per-account PHP version and extension management via alt-php). Together they give you the isolation of a VPS at the density and cost of shared hosting. This guide walks through installation, configuration, and hardening so you can lock down a production shared server today.

Prerequisites#

  • A server running AlmaLinux 8/9, Rocky Linux 8/9, or RHEL 8/9 (CloudLinux is a RHEL derivative and can also convert an existing AlmaLinux install in-place).
  • A valid CloudLinux OS license (starts around $16/month per server from CloudLinux directly, or bundled by some data-centre providers).
  • Root SSH access.
  • cPanel/WHM, DirectAdmin, or any panel that supports CloudLinux integration. The steps below are panel-agnostic where possible.

Step 1 — Install or convert to CloudLinux#

If you are starting from AlmaLinux, CloudLinux provides a one-command converter:

bash
curl -O https://repo.cloudlinux.com/cloudlinux_sources/cldeploy
sh cldeploy -k YOUR_ACTIVATION_KEY
reboot

After reboot, verify:

bash
cat /etc/os-release   # should show CloudLinux
uname -r              # kernel will be lve kernel

If you already run CloudLinux, simply update to the latest release:

bash
yum update -y
reboot

Step 2 — Install CageFS#

bash
yum install cagefs -y
/usr/sbin/cagefsctl --init   # creates the skeleton filesystem (~700 MB)

The --init step copies safe binaries (ls, curl, mysql, php, etc.) into /var/cagefs/. It does not copy user files — those are bind-mounted at login time.

Enable CageFS for every user on the server:

bash
/usr/sbin/cagefsctl --enable-all

To verify a specific user is caged:

bash
/usr/sbin/cagefsctl --list-enabled | grep johndoe

Step 3 — Install PHP Selector#

PHP Selector requires the alt-php packages from CloudLinux. Install the full set:

bash
yum install ea-php* alt-php* -y   # ea-php for cPanel; alt-php for CageFS
/usr/sbin/cagefsctl --setup-cl-selector

Then update the CageFS skeleton so every caged user can see the PHP binaries:

bash
/usr/sbin/cagefsctl --force-update

Let users pick their PHP version#

In cPanel/WHM with CloudLinux integration, users see a "Select PHP Version" icon automatically. For DirectAdmin or panel-less setups, the user can run:

bash
selectorctl --set-current 8.2 --user johndoe

As the admin, set a server-wide default (e.g. 8.2) and let users override only within the versions you permit:

bash
selectorctl --set-default 8.2

You can disable old, insecure versions entirely:

bash
selectorctl --disable 5.6 --user johndoe
selectorctl --disable 7.0 --user johndoe

Step 4 — Harden the CageFS skeleton#

The default skeleton is safe, but you should audit it:

  1. Remove binaries you do not need. Edit /etc/cagefs/cagefs.mp and comment out lines for tools like gcc, gdb, or strace that normal users should never access. Then rebuild:
bash
   /usr/sbin/cagefsctl --remount
  1. Blacklist sensitive files. Add paths to /etc/cagefs/conf.d/blacklist.cfg:
code
   /etc/my.cnf
   /var/lib/mysql
   /root
  1. Whitelist only what users need. If a customer needs a custom binary (e.g. node), add it to /etc/cagefs/conf.d/custom.cfg:
code
   [node]
   comment = Node.js
   paths = /usr/local/bin/node

Then run:

bash
   /usr/sbin/cagefsctl --update

Step 5 — Set per-user resource limits with LVE#

CageFS is filesystem isolation; LVE (Lightweight Virtual Environment) is resource isolation. Together they form the complete picture.

Install the LVE utilities if not already present:

bash
yum install lve-utils -y

Set CPU, memory, and process limits per package (e.g. a "Basic" plan gets 1 CPU core, 1 GB RAM, 100 processes):

bash
lvetool --set-reseller-limits --reseller reseller1 --speed=100% --pmem=1024M --nproc=100

Or per user:

bash
lvectl set johndoe --speed=50% --pmem=512M --nproc=75 --iops=1024

Check current usage in real time:

bash
lveinfo --period=1h

This output shows which accounts are hitting their caps — invaluable for identifying noisy neighbours or abuse.

Step 6 — Verify everything is working#

Run these checks from a caged user account (SSH in as the user, or use su):

  • ls / — should show only the CageFS skeleton, not the real root filesystem.
  • cat /etc/shadow — should fail or show only the user's own entry.
  • php -v — should show the version selected via PHP Selector.
  • Try reading /home/otheruser/ — permission denied.

If any of these fail, run:

bash
/usr/sbin/cagefsctl --validate

This reports missing mounts, stale skeletons, or permission issues.

Ongoing maintenance checklist#

  • Update the skeleton after every yum update that changes system binaries:
bash
  /usr/sbin/cagefsctl --force-update
  • Audit LVE limits monthly. Use lveinfo to find accounts consistently hitting ceilings — either upgrade them or investigate abuse.
  • Remove dead users. When an account is terminated, ensure CageFS data is cleaned:
bash
  /usr/sbin/cagefsctl --remove johndoe
  • Keep alt-php patched. CloudLinux backports security fixes to all supported alt-php versions, but only if you install updates:
bash
  yum update alt-php* -y

The bottom line#

CageFS and PHP Selector are not optional extras for shared hosting — they are the baseline that customers increasingly expect. Without them, a single compromised plugin can cascade across every account on your server. With them, each tenant operates in their own sealed environment, choosing the PHP version their application needs while you retain full control over resource limits and security policy.

If you are building your hosting stack on top of a platform like Salieno Core, CloudLinux integration slots in cleanly at the OS layer: CageFS handles isolation, LVE handles resource fairness, and your control panel handles provisioning and billing. The result is shared hosting that behaves like a containerised environment — without the complexity of running Docker or LXC for every account.

Share

0 comments

Loading comments…

More from the blog

Harden Shared Hosting with CageFS & PHP Selector · Salieno Blog