OpenLiteSpeed Namespaces vs PHP Sessions on CyberPanel: A Painful Lesson Learned

OLS namespace isolation

TL;DR

If you are running OpenLiteSpeed (OLS) on CyberPanel with namespace isolation enabled, PHP sessions will break if you leave session.save_path at its default value under /var/lib/lsphp/. The default OLS namespace template mounts /var/lib as read-only, which makes PHP’s default session storage path unusable. The fix is to move PHP sessions to a writable path inside the site’s home directory, such as /home/<SITE>/tmp/sessions.


Environment Overview

This issue surfaced on the following setup:

  • OS: AlmaLinux 9.7 (Moss Jungle Cat)
  • Control Panel: CyberPanel 2.4.4 (last upgraded 8 January 2026)
  • Web Server: OpenLiteSpeed 1.8.3 (managed by CyberPanel)
  • PHP: lsphp74 (but applies to all lsphp versions)
  • Hosting Model: Single VPS, configured as shared hosting
  • Affected Applications: All PHP sites (Adminer triggered the investigation)

The specific application that exposed the issue was Adminer:

I had previously used Adminer 5.3.0 on other servers without any issues, which made this failure particularly confusing.


The Symptoms: Classic PHP Session Failure

The most obvious symptom was that Adminer simply would not let me log in.

  • Standard login resulted in an infinite login loop
  • Enabling “persistent login” partially worked, but then resulted in CSRF token errors
  • This strongly suggested broken PHP session handling

The smoking gun appeared in the OpenLiteSpeed error log:

[STDERR] PHP Warning: session_start(): open(/var/lib/lsphp/session/lsphp74/sess_3vdd78k9s5nr9hhdcqckimhubk, O_RDWR) failed: Read-only file system (30) in /home/<SITE>/public_html/adminer-5.3.0-en.php on line 60

Important details:

  • The filesystem was not actually read-only
  • The disk was not full
  • File permissions were correct

At first, this looked like a misleading or outright wrong error message.


False Leads and Red Herrings

My initial assumptions were predictable:

  • File ownership or permissions issue
  • PHP 7.4 incompatibility
  • CyberPanel virtual host misconfiguration

None of these were true.

CyberPanel’s configuration looked correct, permissions were sane, and the same Adminer version worked elsewhere. Something more fundamental was going on.


The Real Culprit: OpenLiteSpeed Namespaces

After a lot of testing, I noticed something unusual: the output of mount showed a large number of mounts, typically two per site, many managed via systemd.

This led me to investigate:

  • /var/lsns/<SITE>/…
  • /usr/local/lsws/lsns/

That, in turn, led me to the OpenLiteSpeed documentation on namespace isolation:

What OLS Namespaces Actually Do

OpenLiteSpeed uses Linux namespaces to isolate sites from one another. This is good security practice, especially on shared hosting systems.

However, the default namespace template has a critical detail:

/var/lib is mounted read-only inside the namespace.

This is where everything breaks down.


Why PHP Sessions Break Under Namespaces

By default, all lsphp versions are configured with:

session.save_path = /var/lib/lsphp/session/lsphpXX/

That path:

  • Exists on the host
  • Has correct permissions
  • Works fine without namespaces

But inside the OLS namespace:

  • /var/lib is read-only
  • PHP still tries to write session files there
  • Result: Read-only file system (30)

This is not a PHP bug. This is not an Adminer bug. This is a mismatch between OLS namespace defaults and PHP defaults.


Confirming the Hypothesis

To confirm this, I needed a way to override PHP configuration per site.

That led to another discovery: .user.ini support is not enabled by default in OpenLiteSpeed.

Using the following documentation:

I enabled:

LSPHP_ENABLE_USER_INI=on

This allowed per-site overrides of session.save_path.

Once I pointed PHP sessions to a writeable directory inside the namespace, the problem immediately disappeared.


The Fix: Move PHP Sessions Inside the Site

Final Session Path

/home/<SITE>/tmp/sessions

Ownership & Permissions

These values match CyberPanel’s own session setup logic, as seen in:

/usr/local/CyberCP/CPScripts/setup_php_sessions.sh
  • Owner: site user
  • Group: nobody
  • Permissions:
    chmod 1733

Configuration Method

Per-site .user.ini:

session.save_path = "/home/<SITE>/tmp/sessions"

Restart Required

To ensure all workers picked up the new configuration:

systemctl restart lsws
killall -9 lsphp

After this, Adminer worked flawlessly — no login loops, no CSRF errors.


Why I Didn’t Disable Namespaces

Could I have disabled namespaces entirely?

Yes — it’s only a few clicks in the OLS Admin GUI.

But I didn’t, because:

  • Namespace isolation is a valuable security feature
  • This is a configuration compatibility issue, not a design flaw
  • I wanted a solution compatible with CyberPanel’s default OLS setup

I also avoided modifying namespace templates directly to preserve upgrade compatibility.


Impact and Takeaways

  • This issue likely affects all PHP applications running under OLS namespaces
  • It is especially relevant for shared hosting environments
  • The error messages are misleading unless you understand namespace isolation
  • PHP defaults are not namespace-aware

Recommendations

  • Always move PHP sessions to a site-local writeable path
  • Enable .user.ini support explicitly
  • Be aware that /var/lib may be read-only inside namespaces
  • Don’t assume a “read-only filesystem” error means the host filesystem is broken

References & Further Reading

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top