How to better isolate accounts on a cPanel server without CloudLinux
On a cPanel server, every website runs on the same operating system. If one account is hacked, for example through an outdated WordPress plugin, the attacker can try to use it to read or infect the other accounts on the server. CloudLinux prevents this with CageFS, which gives every account its own private view of the server, and LVE, which limits how much CPU, memory and disk I/O each account can use.
If your cPanel server doesn't run CloudLinux, you can still get much of the same protection with settings that are already built into cPanel. This article explains what to change, and what these settings can and can't do.
These steps are for cPanel servers you manage yourself (cloud servers, virtual servers and dedicated servers) and need root access to WHM or SSH. Make the changes during a quiet time, and test a few websites after each step.
What CloudLinux does that these settings don't
The settings below make it much harder for one hacked account to reach the others, but they are not a full replacement for CloudLinux:
- Accounts can still see that other accounts exist (for example, the list of users).
- There are no per-account limits on CPU, memory or disk I/O, so one busy or hacked site can still slow down the whole server.
- There is no MySQL Governor to stop one account's database queries from overloading MySQL.
If you need full isolation and resource limits, CloudLinux can be added to most cPanel servers. Please open a support ticket if you'd like to add it.
Step 1: Run every website with PHP-FPM
Most website hacks start through PHP. With PHP-FPM, each account's PHP runs as that account's own Linux user, in its own pool, so a hacked site can only change its own files.
- In WHM, go to Software > MultiPHP Manager.
- On the User Domain Settings tab, select all domains and turn PHP-FPM on.
- Check a few websites to confirm they still load.
So that new accounts also use PHP-FPM, turn on the option to use PHP-FPM by default for new accounts in the same MultiPHP Manager screen.
Limit what PHP can read with open_basedir
open_basedir stops PHP from opening files outside the account's own folders, which blocks one of the most common ways attackers read other accounts' configuration files (and their database passwords).
For PHP-FPM, you can set a default for all pools in /var/cpanel/ApachePHPFPM/system_pool_defaults.yaml, for example:
php_admin_value_open_basedir: { name: 'php_admin_value[open_basedir]', value: "[% homedir %]:/tmp:/var/tmp:/usr/share/pear:/usr/local/lib/php" }
Then rebuild the PHP-FPM configuration:
/scripts/php_fpm_config --rebuild
Some applications need extra folders added to the list. If a site shows an "open_basedir restriction in effect" error after this change, add the folder named in the error.
For sites that don't use PHP-FPM, WHM has a separate setting at Security Center > PHP open_basedir Tweak.
Step 2: Stop accounts from reading each other's files
cPanel's file protection sets each account's home folder and public_html so that only the account itself and the web server can read them, instead of every user on the server.
/scripts/enablefileprotect
Step 3: Turn on symlink protection
A common attack uses a symbolic link (a shortcut file) in a hacked account that points to another account's files, such as its wp-config.php, and then reads it through the web server.
- In WHM, go to Service Configuration > Apache Configuration > Global Configuration.
- Set Symlink Protection to On and save.
Also make sure the kernel's own symlink protection is on (it is by default on current AlmaLinux, Rocky Linux and CloudLinux releases):
sysctl fs.protected_symlinks
It should show fs.protected_symlinks = 1.
Step 4: Jail shell access and cron jobs
If your customers have SSH or cron access, give them jailshell instead of a normal shell. jailshell runs the user inside a restricted copy of the system, so they can't browse the rest of the server.
- In WHM, go to Account Functions > Manage Shell Access and set accounts to Jailed Shell (or Disabled if they don't need SSH).
- In Server Configuration > Tweak Settings, turn on the option to use jailshell as the default shell for new and modified accounts.
Cron jobs run with the account's shell, so jailed accounts' cron jobs are jailed too.
Step 5: Hide other users' processes
By default, any user can list every process running on the server, including other accounts' processes and the commands they were started with. Mounting /proc with hidepid=2 means each user only sees their own processes.
Add this line to /etc/fstab:
proc /proc proc defaults,hidepid=2 0 0
Then apply it without a reboot:
mount -o remount,hidepid=2 /proc
Some monitoring tools need to see all processes. If one stops working, give its group access with the gid= option (for example hidepid=2,gid=monitor).
Step 6: Secure /tmp and restrict compilers
Attackers often download their tools into /tmp and run them from there.
- Run
/scripts/securetmpto mount/tmpso programs can't be run from it. - In WHM, go to Security Center > Compiler Access and disable compilers for unprivileged users.
- In Security Center > Shell Fork Bomb Protection, turn protection on.
Step 7: Limit each account's PHP resources
Without CloudLinux there are no full per-account limits, but you can stop one site from using all of PHP's workers:
- In WHM, go to Software > MultiPHP Manager and open the System PHP-FPM Settings. Set a sensible Max Children (the most PHP processes one domain can run at once) and Max Requests.
- In Software > MultiPHP INI Editor, keep memory_limit and max_execution_time at reasonable values.
Step 8: Scan for malware and keep a web application firewall on
Isolation limits the damage from a hacked account; scanning and a firewall help find and stop it.
- If your server has Imunify360 (or ImunifyAV+), set the default action for detected malware to clean or quarantine, not only to notify. Otherwise infected files stay active after they're found.
- Keep ModSecurity turned on for all domains (WHM > Security Center > ModSecurity Configuration, and cPanel > ModSecurity for each account).
- Keep WordPress, its themes and plugins up to date, and remove ones that aren't used.
Summary
| Setting | Protects against |
|---|---|
| PHP-FPM for all domains | A hacked site changing other accounts' files |
| open_basedir | PHP reading other accounts' files and passwords |
| File protection | Users browsing each other's folders |
| Symlink protection | Reading other accounts' files through links |
| Jailshell | SSH and cron users browsing the server |
| hidepid=2 | Users seeing other accounts' processes |
| Secure /tmp, no compilers | Attackers running their own tools |
| PHP-FPM limits | One site using all PHP workers |
| Malware scanning and ModSecurity | Finding and blocking infections |
For complete isolation of every account, including CPU, memory and I/O limits, consider adding CloudLinux to your server. Please open a support ticket from your client area if you have any questions.