Panellicense

Set up a jailed SSH shell (jailshell) on cPanel & WHM

Give shared-hosting clients SSH without exposing the box — enable cPanel's jailed shell, understand VirtFS, and learn why CageFS should replace it on CloudLinux.

6 min readUpdated 2026-07-17cpanel · jailshell · ssh · virtfs
schema: HowToschema: FAQPage

Handing a shared-hosting client a normal shell lets them cd /home, list every other account, and read anything world-readable across the server. Jailed shell — jailshell — chroots each user into their own home directory so ls / shows a skeleton filesystem, not your other customers' sites.

This covers enabling jailshell per-account and by default, how the VirtFS backing store works and why /home/virtfs quietly eats mount points, how to clean up stale mounts, and the one interaction that catches every host running CloudLinux: installing CageFS silently reverts jailshell users to plain bash.

Enable jailed shell for one account

Go to WHM → Account Functions → Manage Shell Access. Each account gets three options:

  • Normal Shell — full /bin/bash, can traverse the whole filesystem. Only give this to accounts you operate yourself.
  • Jailed Shell — chrooted jailshell. SFTP and SSH both work, but the user is confined to their home.
  • Disabled Shell — no interactive login at all. SFTP still works via the internal SFTP subsystem, so pick this if the client only moves files.

Selecting Jailed Shell sets the account's login shell to /usr/local/cpanel/bin/jailshell in /etc/passwd. Confirm from the command line:

grep bob /etc/passwd
# bob:x:1024:1030::/home/bob:/usr/local/cpanel/bin/jailshell

You can flip it non-interactively with the API, which is handy inside provisioning hooks:

whmapi1 modifyacct user=bob shell=/usr/local/cpanel/bin/jailshell

Make jailshell the default for new accounts

Setting shells one account at a time drifts the moment someone creates a package outside your runbook. Set the server-wide default in WHM → Server Configuration → Tweak Settings → search for jail → enable Use cPanel® jailshell by default. Every new or modified account with shell access then lands in jailshell instead of /bin/bash.

This is one of the Tweak Settings worth changing on a shared box. It does not retroactively re-jail existing normal-shell accounts — audit those separately:

grep -vE 'jailshell|/nologin|/false' /etc/passwd | grep '/home/'

Anything that prints is an account with an unrestricted shell.

How VirtFS works and why /home/virtfs grows

jailshell doesn't use a static chroot. cPanel builds each jail on demand with VirtFS: the first time a jailed user opens an SSH or SFTP session, cPanel creates /home/virtfs/<user>/ and BIND-mounts the system binaries, libraries, and config files the user needs — /bin, /lib64, /etc, and so on — into that per-user tree. The user sees a working Linux environment; you keep isolation.

The cost is mount-table bloat. Each active jailed user can add dozens of bind mounts, and a busy server accumulates thousands:

grep virtfs /proc/mounts | wc -l

On servers with hundreds of shell users this inflates mount output, slows df, and occasionally leaves stale mounts behind after an account is removed or a session dies uncleanly.

Clean up stale VirtFS mounts

To tear down one user's jail safely, use cPanel's script — it unmounts every bind mount for that user before touching the directory:

/usr/local/cpanel/scripts/clean_user_virtfs bob

If mounts are wedged (a process still has a handle open), find and unmount them manually, then re-run the script:

grep '/home/virtfs/bob' /proc/mounts | awk '{print $2}' | sort -r | xargs -r umount

Sorting in reverse unmounts the deepest paths first. Do this during a maintenance window — the user's session dies with the mounts.

The CloudLinux CageFS exception

This is the part hosts trip over. If you run CloudLinux with CageFS, do not use jailshell. When you install or update the CageFS package, it rewrites every jailshell user in /etc/passwd back to /bin/bash:

grep bob /etc/passwd
# bob:x:1024:1030::/home/bob:/bin/bash

That looks like a security regression, but it isn't. CageFS already virtualises the entire filesystem per user at a lower level than VirtFS — a CageFS user in a normal bash shell still can't see other accounts, /etc/passwd is filtered, and only whitelisted binaries are reachable. Running jailshell inside CageFS would double-mount the same isolation and conflict with the CageFS skeleton, so CloudLinux deliberately disables it.

The practical rule:

  • CloudLinux box → enable CageFS, leave shells as bash, add any missing tools to the CageFS skeleton. CageFS is the isolation layer.
  • Stock cPanel, no CloudLinux → use jailshell + VirtFS as above.

Don't stack both. If you're weighing the upgrade, CageFS also brings per-user PHP versions and symlink-attack protection that jailshell doesn't — see SecureLinks symlink protection. Pricing and tiers are on the CloudLinux license page.

Jail Apache is a separate setting

The Security Advisor's "Jail Apache Virtual Hosts using mod_ruid2" recommendation is unrelated to shell access — it confines the web server's PHP processes, not SSH logins. It's worth enabling on most shared boxes, but on servers with more than ~500 accounts the extra per-vhost mounts can bite performance the same way VirtFS does. Test before rolling it fleet-wide, and pair either approach with account-level suspension hygiene so compromised accounts lose shell access fast.

Where is the jailshell binary in cPanel?+
At /usr/local/cpanel/bin/jailshell. Enabling Jailed Shell in Manage Shell Access sets a user's login shell to that path in /etc/passwd.
Why did my jailshell users switch to bash after installing CloudLinux?+
CageFS rewrites jailshell users to /bin/bash on install because CageFS provides stronger per-user filesystem isolation on its own. This is expected — don't switch them back.
Can I delete the /home/virtfs directory to reclaim space?+
No. It contains live bind mounts, and a recursive delete can destroy system binaries or user data. Use /usr/local/cpanel/scripts/clean_user_virtfs to tear a user's jail down safely.
Does jailed shell block SFTP?+
No. SFTP works under both Jailed Shell and Disabled Shell. If a client only transfers files, Disabled Shell gives them SFTP with no interactive shell at all.
How do I make jailshell the default for all new accounts?+
Enable 'Use cPanel jailshell by default' in WHM → Tweak Settings. It applies to new and modified accounts but does not re-jail existing normal-shell accounts.

Next steps

Switch in an afternoon

Switch from your current reseller — free.

We migrate active cPanel, Plesk, LiteSpeed and CloudLinux licenses from any reseller. We prorate the first month so you never pay twice, and your customers see zero downtime during the swap.