CageFS: What It Does and How to Enable It on CloudLinux

Why every CloudLinux server should run CageFS, what it hides from users, how to initialise and enable it, and how to fix the usual breakages.

Published
Reading time
4 min

LVE stops one account from using another account's resources. CageFS stops one account from seeing another account's files. It is the second half of what makes a CloudLinux server safe to share, and it is required by PHP Selector, so nearly every CloudLinux server runs it. This guide explains the attack it prevents, how to set it up, what changes for your users, and what to do when something they rely on stops working.

The threat it stops

On a plain shared server, every user can read /etc/passwd and learn every other account's username, look through /proc and see other users' running commands with their arguments, and walk /home looking for world-readable files. That last one is the real problem. A WordPress install with a misconfigured wp-config.php permission, or a symlink placed by a compromised site pointing at another user's config, hands over database credentials. Automated malware does exactly this: land on one account, harvest the credentials of every other account on the box.

CageFS removes the target. Inside the cage, /home contains only the user's own directory, /proc shows only their own processes, /etc/passwd lists only them, and the paths and binaries they can reach are a curated subset of the real server. There is nothing to enumerate and nowhere to point a symlink.

How it works

CageFS builds a skeleton filesystem under /usr/share/cagefs-skeleton: copies of the binaries, libraries and configuration files a hosting user legitimately needs (PHP, Perl, Python, the shell, curl, git, mysql, and so on). When a caged user's process starts, whether it is a PHP request, a cron job or an SSH login, the kernel mounts a private view for it: the skeleton, plus the user's real home directory, plus a private /tmp. Everything the user does happens inside that view. Their files are still exactly where they always were; only their view of the server has changed.

The skeleton is shared and read-only, so the disk cost is paid once, around 7 GB, however many users you have.

Initialise and enable it

Install the package, build the skeleton, and turn it on for everyone:

bash
yum install cagefs
cagefsctl --init
cagefsctl --enable-all

--init copies the skeleton and takes several minutes. --enable-all sets the mode so that every current and future user is caged unless individually excluded. The opposite mode, cagefsctl --toggle-mode disable-all, cages nobody unless individually enabled; use it only while you are testing on a live server with one or two accounts:

bash
cagefsctl --toggle-mode disable-all
cagefsctl --enable bob
cagefsctl --list-enabled

cagefsctl --disable bob takes a user out of the cage in either mode. In DirectAdmin, Admin Level → Extra Features → CloudLinux Manager → Users shows each account's CageFS status with a toggle.

If you are setting up a new server, the order is in installing CloudLinux on a DirectAdmin server: convert, switch CustomBuild to lsphp, then CageFS, then alt-php.

Keep the skeleton up to date

The skeleton is a copy, so anything you install or update on the server afterwards is not in it until you say so. After every yum update, every CustomBuild PHP rebuild and every new alt-php version:

bash
cagefsctl --update

--update only copies what has changed. cagefsctl --force-update rebuilds the whole skeleton and is the fix when something is inexplicably missing. cagefsctl --remount-all re-mounts every user's cage without rebuilding, needed after changing mount points. cagefsctl --update-etc refreshes the filtered copies of /etc files, such as after adding users outside the panel.

To add a binary of your own, say a deploy tool under /usr/local/bin, create a file in /etc/cagefs/conf.d/ listing the paths to copy, then run --update. Directories that must be visible inside every cage rather than copied go in /etc/cagefs/cagefs.mp, followed by --remount-all.

What changes for users

Mostly nothing, which is the goal: a WordPress site does not know it is caged. The differences a user can notice:

/tmp is private. Each user's temporary files land in ~/.cagefs/tmp, and a full one affects only them. Anything that expects to share /tmp with another user breaks, which is rare.

Only the skeleton's binaries exist. which composer may return nothing even though composer is installed on the server, until you add it to the skeleton.

Cron jobs and SSH sessions run inside the cage. A cron command that worked as root while you were testing may fail as the user because the binary or the path is not in the skeleton.

PHP Selector works. Because alt-php lives inside the skeleton, users can switch versions and extensions in Select PHP Version, and PHP Selector refuses to serve a user who is not caged.

Common breakages and fixes

A site broke the moment CageFS was enabled. Usually a missing binary or library the site calls through exec(), such as convert or wkhtmltopdf. Disable the user temporarily to confirm, add the binary via /etc/cagefs/conf.d/, run cagefsctl --update, and re-enable.

A cron job stopped running. Log in as the user and run the command from the crontab by hand; the error tells you what is missing. Check the PHP path is one that exists in the cage, such as /opt/alt/php83/usr/bin/php or the CustomBuild binary the user's domain uses.

A user can see other accounts' processes. They are not caged. cagefsctl --list-enabled will confirm; check whether the user was created while the mode was disable-all, or was added to /etc/cagefs/exclude/ at some point.

PHP Selector says the user is not enabled. Same cause; enable the user in CageFS.

Everything is odd after an update. cagefsctl --force-update, then cldiag --all, which names the failing check.

CageFS and LVE together are what let one server hold customers who have never met. On a VPSPioneer managed VPS we enable CageFS as part of a CloudLinux conversion.

#cloudlinux#cagefs#security#shared-hosting

Keep reading

More from CloudLinux

All guides

CloudLinux

LVE Explained: How CloudLinux Isolates Accounts on a Shared Server

What an LVE is, which processes run inside it, the seven limits CloudLinux enforces, what a user sees when each one is hit, and how to watch it live with lveps.

4 min read →

CloudLinux

What Is CloudLinux OS and Who Actually Needs It?

What CloudLinux OS does on a shared or reseller server, how the Shared, Shared Pro, Solo and Admin editions differ, and when plain AlmaLinux is enough.

4 min read →

CloudLinux

How to Set LVE Limits: SPEED, PMEM, IO, IOPS, NPROC and EP

What each CloudLinux LVE limit means, worked starting values for three package tiers, the lvectl commands, and when to raise a limit or move a customer up.

5 min read →