Documentation menuAccount isolation

Account isolation

bipanel creates every hosting account as a separate Linux user; file permissions, a per-account PHP-FPM pool and open_basedir apply on every installation. On a server installation it adds a jailed shell, cgroup resource limits and, in the Pro edition, account isolation built on systemd namespaces.

Last updated:

On this page
  1. Layers at a glance
  2. Separate system user and file permissions
  3. PHP-FPM pools and open_basedir
  4. Jailed shell
  5. Resource limits
  6. Account isolation (Pro)
    1. Compatibility test and rollback
  7. SELinux and AppArmor
  8. Docker and Railway installations

#Layers at a glance

Isolation is not a single switch but a set of overlapping layers. Where each one applies:

LayerServer installationDocker / RailwayEdition
Separate Linux user and file permissionsYesYesCommunity
Per-account PHP-FPM pool, open_basedirYesYes (shared master)Community
Per-account PHP-FPM master processYes (systemd + cgroup v2)NoCommunity
Jailed shell (SSH, SFTP, web terminal, cron)YesNoCommunity
CPU, memory and process limits (cgroup v2)YesProcess count onlyCommunity
Disk I/O limitsYesNoPro
Account isolation (systemd namespaces)Yes (systemd 245+)NoPro

The Community edition manages up to 3 hosting accounts; see Pricing for edition differences.

#Separate system user and file permissions

Each account gets its own user and group ID. The home directory is mode 0711, so other users cannot list its contents. The document root is owned by the account, grouped to the web server group (www-data or apache) with mode 0750: the web server can read it, other accounts cannot. The tmp, backups, .ssh and .bipanel directories are created as 0700, logs as 0750.

To stop symlinks from reaching another account's files, Apache virtual hosts use SymLinksIfOwnerMatch and the options .htaccess may change are restricted. File operations the panel performs as root (file manager, restoring from backup) open paths component by component without following links, so a link pointing outside the account's home is never followed.

#PHP-FPM pools and open_basedir

Each account's PHP runs in its own FPM pool under the account's user ID. Only the web server can connect to the pool socket. Each pool pins:

  • open_basedir: the account's home, /tmp, /var/tmp, the distribution's shared PHP library directories and /dev/urandom.
  • Uploads, temporary files and sessions go to the account's ~/tmp; PHP errors are logged to ~/logs/php-error.log.
  • The server-wide disable_functions list is applied to the pool as well.

On a server installation with systemd and cgroup v2, each account's pool runs in its own PHP-FPM master process inside the account's cgroup slice, so CPU, memory and process limits cover PHP too. This is on by default for new installations. On a server that already has accounts, an update does not switch it on, because every account needs an extra master process and sites are briefly interrupted during the switch; turn it on under Server Admin → Resource Limits. On Docker and Railway the pools run in a shared master process.

#Jailed shell

Shell access is set per account or per package to one of three modes: off, jailed or full. When a package enables shell access without choosing a type, the jailed mode is used. The settings live under Server Admin → Shell Isolation, available to administrators and resellers.

The jailed shell is built on bubblewrap and applies equally to SSH, SFTP/scp, git, the web terminal and cron jobs:

  • Only the account's home is writable; /usr and the required system files are read-only.
  • Other accounts' directories, panel data and system configuration are not visible; /etc/passwd lists only root, nobody and the account itself.
  • A separate PID namespace: other users' processes are not visible.
  • A private /tmp (512 MB by default) and a cleaned environment.

Administrators can bind extra read-only paths into the jail; account homes, /etc, /proc, panel data and similar paths are refused. The component is installed by default on a server installation. If it is missing, accounts in jailed mode cannot log in; the administrator can choose to give them an unrestricted full shell instead. An optional compiler restriction limits tools such as gcc and make to the accounts that are allowed to use them.

#Resource limits

On a server installation the package's CPU percentage, memory and maximum process count are enforced with systemd slices (cgroup v2): PHP-FPM and Node.js/Python apps run in the account's slice, SSH sessions and cron jobs in the account's user slice. The process limit also guards against fork bombs. Disk read/write throughput limits are a Pro feature (Server Admin → Disk I/O & File Limits). If the server runs in cgroup v1 mode, the screen shows the kernel parameter needed to switch. On Docker and Railway the platform limits resources; the panel applies only a process count limit to apps and commands. Details: Monitoring, limits and statistics.

#Account isolation (Pro)

Server Admin → Account Isolation (Pro) confines everything an account runs with systemd namespaces: the per-account PHP-FPM master, Node.js/Python app units, build and deploy commands, and git. An isolated unit:

  • sees the filesystem read-only and can write only to its own home;
  • cannot see other accounts' homes, panel data, mailboxes, system logs, certificate private keys or /etc/shadow;
  • gets a private /tmp and /dev and cannot see other users' processes (systemd 247 and later);
  • cannot gain new privileges, create setuid files or reach kernel tunables and modules; risky system call groups are blocked.

Database sockets, PHP extensions, CA certificates and PHP mail() keep working. The setting is available at server, package and account level and is off by default. Administrators can add extra writable paths and extra hidden paths.

#Compatibility test and rollback

Isolation is tested before it is applied to an account: PHP pools, PHP sites and running apps are measured first without isolation, then in a temporary isolated copy, and the results are compared. If anything differs, isolation is not applied; if something stops working after the switch, it is rolled back automatically and the administrator is notified. The screen shows each unit's systemd exposure score (0 fully protected, 10 unrestricted) before and after isolation. With per-account PHP-FPM turned off, PHP cannot be isolated; only apps and commands are. If the licence becomes invalid, applied isolation is not removed; only new isolation cannot be started.

Requirement: systemd 245 or later (Ubuntu 22.04+, Debian 12+, AlmaLinux/Rocky/RHEL 9+).

#SELinux and AppArmor

On AlmaLinux, Rocky Linux and RHEL the panel never disables SELinux; it grants what it needs through the policy tools. Web roots and the directories PHP writes to are labelled with the right contexts, and the required booleans and ports are set. For account isolation a small local policy module grants only the few permissions it needs. The SELinux mode and recent SELinux errors are shown in the SELinux section of Server Admin → Firewall.

On Ubuntu, when AppArmor restricts unprivileged user namespaces, the jailed shell component adds an AppArmor profile for bubblewrap; if another bwrap profile is already defined, it is left alone.

#Docker and Railway installations

In a container installation all accounts run in one container and are separated by Linux users. File permissions, PHP pools and open_basedir apply, but without systemd the per-account PHP-FPM master, cgroup limits, the jailed shell and Pro account isolation are not available. Accounts with shell access get a normal shell. Host customers who do not trust each other on a server installation. Details: Docker and Railway; security overview: Security.

Something missing or wrong on this page? Let us know.