Skip to content

UNIX user namespacing

What is UNIX user namespacing, and why is it the default?

This article explains what namespacing is, the two effects it has, and the one case in which you may want to opt out.


The short version

Leave namespacing on. It's the default, and almost no project needs to change it.

It does two things:

  1. Per-user PHP and Node.js versions: the version you set for the UNIX user is always the one that runs.
  2. Protection against Local Privilege Escalation: SUID binaries such as sudo don't work, which blocks most of these exploits.

There's one reason to opt out, being a legacy application that needs sudo. See When to opt out.

What it is

Cyberfusion runs each UNIX user, and the processes that run a site's PHP code, inside its own Linux namespace. A namespace is an isolated execution environment: processes inside it see a restricted view of the system.

Per-user PHP and Node.js versions

Inside a namespaced UNIX user, php or node always runs the version set as the default for that UNIX user.

To change it:

How it works

On Linux there is normally one system-wide default version of binaries such as php and node, shared by all users. Cyberfusion mounts the UNIX user's selected version over those default binaries.

So the user's chosen default is what gets invoked, no matter how many other versions are installed on the cluster.

Why a daemon's PHP version can look wrong

php -v shows the version you chose. But some programs don't run php — they read the path of the currently running PHP interpreter (which PHP exposes as PHP_BINARY) and use that exact path to start more PHP processes. Laravel Horizon works this way.

So you may see php8.3 in the command line while your default is PHP 8.5. PHP 8.5 is still the version actually running.

Why: to make your version the one that runs, the cluster mounts it over the shared php path. The path keeps the name of the cluster's system-wide default version (php8.3 here), but the program at that path is your selected version (8.5). The version number in the path is misleading; the program behind it is correct.

A plain php command is unaffected. To confirm which version is really running, don't read the path — check what the worker processes report, for example in phpinfo() or the application's own version output.

Protection against Local Privilege Escalation

Inside a namespace, SUID binaries such as sudo do not function. Using sudo simply fails.

Local Privilege Escalation (LPE) is the class of bug that lets a regular user become root. Most LPE exploits need a SUID binary to do the escalation. With SUID binaries disabled, the exploit cannot run even when the underlying bug is present.

Publicly known LPE exploits such as Copy Fail, Dirty Frag and Fragnesia do not work against namespaced UNIX users on Cyberfusion, regardless of patch state.

When to opt out

One reason: you need SUID binaries to work, usually because a legacy application depends on sudo.

With namespacing off, you lose both effects:

Per-user versions. Cyberfusion sets up shell aliases for php and node pointing at the user's selected version. The aliases don't cover every case — not in non-interactive shells, not in scripts that invoke the binary indirectly, and not when the caller uses a full path. Where the alias doesn't apply, the cluster's system-wide default version runs instead, which may not be what you expected.

To guarantee a specific version, call it by its full path:

/usr/bin/php7.4 /usr/bin/composer

LPE protection. SUID binaries work normally, so LPE exploits against unpatched bugs become possible.

Separating services across nodes — what an attacker reaches once they do become root on a node, and when it's worth moving the database or mail to a node of their own.