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:
curl -O https://repo.cloudlinux.com/cloudlinux_sources/cldeploy
sh cldeploy -k YOUR_ACTIVATION_KEY
rebootAfter reboot, verify:
cat /etc/os-release # should show CloudLinux
uname -r # kernel will be lve kernelIf you already run CloudLinux, simply update to the latest release:
yum update -y
rebootStep 2 — Install CageFS#
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:
/usr/sbin/cagefsctl --enable-allTo verify a specific user is caged:
/usr/sbin/cagefsctl --list-enabled | grep johndoeStep 3 — Install PHP Selector#
PHP Selector requires the alt-php packages from CloudLinux. Install the full set:
yum install ea-php* alt-php* -y # ea-php for cPanel; alt-php for CageFS
/usr/sbin/cagefsctl --setup-cl-selectorThen update the CageFS skeleton so every caged user can see the PHP binaries:
/usr/sbin/cagefsctl --force-updateLet 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:
selectorctl --set-current 8.2 --user johndoeAs the admin, set a server-wide default (e.g. 8.2) and let users override only within the versions you permit:
selectorctl --set-default 8.2You can disable old, insecure versions entirely:
selectorctl --disable 5.6 --user johndoe
selectorctl --disable 7.0 --user johndoeStep 4 — Harden the CageFS skeleton#
The default skeleton is safe, but you should audit it:
- Remove binaries you do not need. Edit
/etc/cagefs/cagefs.mpand comment out lines for tools likegcc,gdb, orstracethat normal users should never access. Then rebuild:
/usr/sbin/cagefsctl --remount- Blacklist sensitive files. Add paths to
/etc/cagefs/conf.d/blacklist.cfg:
/etc/my.cnf
/var/lib/mysql
/root- Whitelist only what users need. If a customer needs a custom binary (e.g.
node), add it to/etc/cagefs/conf.d/custom.cfg:
[node]
comment = Node.js
paths = /usr/local/bin/nodeThen run:
/usr/sbin/cagefsctl --updateStep 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:
yum install lve-utils -ySet CPU, memory, and process limits per package (e.g. a "Basic" plan gets 1 CPU core, 1 GB RAM, 100 processes):
lvetool --set-reseller-limits --reseller reseller1 --speed=100% --pmem=1024M --nproc=100Or per user:
lvectl set johndoe --speed=50% --pmem=512M --nproc=75 --iops=1024Check current usage in real time:
lveinfo --period=1hThis 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:
/usr/sbin/cagefsctl --validateThis reports missing mounts, stale skeletons, or permission issues.
Ongoing maintenance checklist#
- Update the skeleton after every
yum updatethat changes system binaries:
/usr/sbin/cagefsctl --force-update- Audit LVE limits monthly. Use
lveinfoto find accounts consistently hitting ceilings — either upgrade them or investigate abuse.
- Remove dead users. When an account is terminated, ensure CageFS data is cleaned:
/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:
yum update alt-php* -yThe 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.
0 comments
Loading comments…