ProdCraft
Subscribe
Hosting Panels

Multi-Tenant Hosting Isolation: Linux Users, PHP Pools and Resource Quotas

Design safer shared hosting with per-site Linux users, PHP-FPM pools, filesystem boundaries, resource quotas and auditable account operations.

ProdCraft6 min read
Person standing inside a server room representing hosting control panel administration and server access troubleshooting

A hosting control panel may manage hundreds of customer websites on a small fleet of servers. If every site runs under the same Unix identity, a compromised plugin or application can expose files belonging to other customers. Multi-tenant isolation must be enforced by the operating system and service configuration, not only by the panel UI.

Use a separate identity per account

Create a dedicated Linux user and group for each hosting account. Ensure files, sockets, temporary directories and deployment jobs are owned by the correct identity. Avoid shared writable directories between customers. Apply restrictive permissions and keep administrative services separate from customer processes.

Configure PHP-FPM pools per site

Run PHP workers under the account’s user and group. Use a separate pool configuration with controlled process limits and a Unix socket whose permissions permit access only to the intended web server. Tune pm.max_children from measured memory per worker and the account’s resource budget.

Limit resource consumption

Use cgroups or systemd scopes to control CPU, memory and task counts. Monitor disk usage, inodes, bandwidth and process counts. A quota should produce a clear operational signal when exceeded; avoid silently terminating workloads without recording the event and notifying the account owner.

Protect secrets and control-plane access

Keep database credentials, backup keys and panel tokens out of web roots. Restrict access to SSH keys and provide account-scoped credentials. Administrative APIs should enforce role-based access and record changes to domains, DNS, backups and account lifecycle.

Plan backups and migrations around identity

Backups must preserve ownership and permissions, but restore workflows should validate them before exposing files to a live account. When migrating between servers, create the destination identity and resource policy before restoring data. Avoid running customer-provided scripts as root.

Isolation checklist

  • Separate Unix user and PHP-FPM pool per account.
  • Restrict socket and filesystem permissions.
  • Apply CPU, memory, disk and process quotas.
  • Separate control-plane credentials from site credentials.
  • Test backup restore and account termination safely.

Isolation is a core hosting-platform feature, not an optional hardening extra. Related reading: PHP-FPM pool configuration and Linux server hardening.

Architecture and prerequisites

Begin with a threat model for each hosting account. Identify which files, processes, sockets, databases and network destinations belong to one customer, and list the ways a compromised PHP application could attempt to cross that boundary. A separate Unix user is only effective when ownership and permissions are consistent across web roots, temporary directories, deployment scripts and scheduled jobs. Review every shared writable directory and remove write access unless it is required. Keep control-panel services under a separate administrative identity.

Configuration and implementation

PHP-FPM pools should run with the account’s user and group and expose a Unix socket with narrowly scoped permissions. Set process manager limits based on measured worker memory and the account’s expected concurrency. A low max_children value can create request queues, while an excessive value can exhaust host memory. Monitor per-pool active processes, listen queue, slow requests and memory use. Ensure that pool configuration is generated safely by the panel and validated before reload so a malformed customer setting cannot break every PHP site on the server.

Security and compatibility

Use cgroups or systemd scopes to apply CPU, memory, task and I/O limits where supported. Disk quotas and inode limits should be enforced separately because a customer can exhaust inodes while using relatively little storage. Bandwidth controls may exist at the network layer or provider edge. Define what happens when a quota is exceeded: block new writes, throttle requests or suspend an account according to a documented policy. Record the event and notify the account owner instead of silently terminating processes.

Testing and validation

Protect control-plane credentials from customer processes. Store database passwords, backup credentials and panel API tokens outside document roots with restrictive permissions. SSH access should be account-scoped, audited and disabled by default where it is not required. A customer should not be able to read another account’s environment files, backup archives, logs or PHP session data. Test isolation using two separate test accounts and attempt file, process and socket access across the boundary.

Monitoring and troubleshooting

Backups and migrations must preserve ownership without trusting archive metadata blindly. Validate file paths, symlinks, permissions and ownership during restore so a crafted archive cannot write outside the target account. Create the destination user and quotas before restoring data. When migrating between servers, verify PHP version, extensions, database grants, cron entries and domain mappings. Keep a rollback copy until DNS and application health checks confirm the destination is serving correctly.

Production operations

Account lifecycle operations are security-sensitive. Suspend should stop new requests and scheduled jobs without deleting data; unsuspend should restore only the intended services. Termination should require explicit authorization, a clear retention policy and a final backup or export option where promised. Record who created, transferred, suspended or deleted an account. A hosting panel should reconcile its database state with the actual Linux users, pools, vhosts and DNS records to detect partial failures.

Operational readiness and lifecycle

Before rollout, define an owner for the configuration, supported versions, dependencies and escalation path. Put configuration under version control and require review for production changes. Verify the implementation with a representative workload and record a baseline so future changes can be compared. Test a failure scenario, a restart and a rollback rather than relying only on a successful happy-path test. Monitoring should expose both the component’s internal health and the user-visible outcome, with alert thresholds that have a documented response. Keep a concise runbook containing diagnostic commands, expected signals, safe retry guidance and recovery steps. Review the design after the first production cycle and whenever an upstream dependency changes. Remove temporary exceptions, rotate credentials where applicable and update compatibility notes. This ongoing ownership is what turns a working configuration into a maintainable production service.

Scenario-based verification

For hosting isolation, include a two-account penetration test: attempt to read another account’s files, inspect its processes, connect to its PHP-FPM socket and access its backup path. Repeat the test after panel upgrades and account transfers. Verify that suspend and unsuspend operations change the real service state as well as the panel database.

Performance and capacity validation

Define a measurable service-level baseline before enabling the change. Record normal and peak throughput, error rate, latency distribution, resource consumption and recovery time. A single successful test does not show how the system behaves under concurrency or after a dependency becomes unavailable. Run load tests that resemble real request patterns and include burst traffic, slow clients and large payloads. Compare results with the baseline and investigate regressions rather than accepting them because the deployment completed. Keep test data representative but non-sensitive, and repeat the test after significant runtime or dependency upgrades.

Logging and alert design

Operational logs should make failures diagnosable without exposing credentials or customer data. Include a correlation identifier, component version, action outcome and safe resource reference. Avoid logging bearer tokens, private keys, full database records or unrestricted request bodies. Define retention and access permissions for diagnostic data. Alert on repeated failures, queue growth, resource saturation and missed scheduled work, but ensure every alert has an owner and an action. Review alert noise after rollout and remove rules that do not lead to useful investigation.

Recovery documentation

Document the recovery path as carefully as the setup path. Include prerequisites, permissions, exact verification commands, expected outputs, rollback steps and conditions that require escalation. Test the procedure with someone who did not build the original system; this exposes assumptions that are obvious only to the author. Keep the runbook next to the configuration or source repository and update it when versions or workflows change. Schedule a periodic review so temporary exceptions, obsolete settings and unsupported dependencies do not become permanent parts of production.

Apply these checks to Multi-Tenant Hosting Isolation: Linux Users, PHP Pools and Resource Quotas: retain the test evidence, identify the owner who accepts the production risk and define the conditions that trigger rollback. Re-run the checks after major upgrades or changes in traffic patterns.

Share this article

Written by

ProdCraft

ProdCraft publishes practical engineering guides on DevOps, Kubernetes, Docker, Linux, databases, cloud and LLMs — written for engineers who ship.

227 articles View profile

The weekly ops & AI brief

One email a week with the best new guides, tools and incident write-ups. No spam, unsubscribe anytime.

Leave a Reply

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