Composer Install Failing in cPanel: Memory & Timeout Fixes
You SSH in, run composer install, and instead of a clean vendor folder you get a wall of red - memory exhausted, a timeout, or a flat "command not found." Composer problems on hosting accounts are almost never about your code; they're about what the hosting environment restricts. Here's how to work through them in order.
Symptom: What You're Actually Seeing
A few variations show up depending on whether you're on shared cPanel hosting or a VPS:
Fatal error: Allowed memory size of 134217728 bytes exhaustedpartway throughcomposer installorcomposer update.proc_open(): Failed to open stream: Permission denied, or Composer just hangs with no output.- The command runs for a minute or two, then the SSH session drops with no error at all.
composer: command not found, even though the host's docs say Composer is preinstalled.- Installs work fine for small packages but choke on anything Laravel- or Symfony-sized.
Each of these traces back to a different limit the hosting environment is enforcing. Work through them in this order rather than guessing.
Cause 1: PHP's Memory Limit Is Too Low for Composer's Dependency Resolver
Composer's solver has to hold the entire dependency graph in memory while it figures out which package versions are compatible. On shared hosting, CLI PHP often still runs with a conservative default - 128M or 256M - which is fine for serving pages but too tight for resolving a Laravel project with 60+ packages.
Check what CLI PHP is actually using (it's frequently a different php.ini than the web-facing one):
php -i | grep memory_limit
The fastest fix is to tell Composer to ignore the limit entirely for this run:
COMPOSER_MEMORY_LIMIT=-1 composer install
If that's not available (some restricted shells block setting env vars inline), raise the limit for the CLI SAPI specifically. In cPanel, go to Select PHP Version → Options and bump memory_limit to 512M or 1024M - note this is separate from the memory_limit your website uses under PHP-FPM/LiteSpeed. On a VPS, edit the CLI-specific ini:
sudo nano /etc/php/8.3/cli/php.ini
# memory_limit = 512M
php -m | grep -i memory_limit # confirm CLI SAPI, not fpm
Cause 2: proc_open or exec Is Disabled
Composer shells out to git and unzip behind the scenes, which means it needs proc_open. Security-hardened shared hosting - and some managed VPS images - disable it by default in disable_functions alongside exec, shell_exec, and passthru. Composer will still start, but it dies the moment it tries to clone a VCS package or run a post-install script.
Check what's blocked:
php -r "echo ini_get('disable_functions');"
On a VPS you control, remove proc_open and proc_close from that list in php.ini and restart PHP. On shared cPanel hosting, you usually can't edit this yourself - it's set at the account or server level for good reason (it's a real attack-surface reduction). Open a support ticket asking specifically whether proc_open can be allowlisted for CLI PHP only, not the web SAPI; most hosts will do this without disabling it site-wide once you explain it's for Composer, not a script left running on the front end.
Cause 3: No SSH Access, or Composer Isn't on the PATH
Plenty of entry-level shared hosting plans don't ship SSH access at all, and even where cPanel's built-in Terminal app is enabled, it runs as your account user with a restricted PATH that may not include Composer's install location.
If Terminal is available but Composer isn't found, download it into your home directory instead of relying on a system-wide install:
cd ~
curl -sS https://getcomposer.org/installer | php
php composer.phar install --no-dev --optimize-autoloader
--no-dev skips dev-only packages (PHPUnit, debug bars) and --optimize-autoloader builds a flat classmap instead of Composer resolving PSR-4 paths at runtime - both cut memory use meaningfully on a constrained account.
If there's genuinely no shell access at all, the practical workaround is to run composer install on your local machine or in a CI job, then upload the resulting vendor/ folder via SFTP or the cPanel Git feature. It's not elegant, but it sidesteps every hosting-side restriction at once. For anything beyond a one-off, that's usually a sign the plan is undersized for what you're deploying - Getwebup's VPS plans include full SSH and an unrestricted Composer setup out of the box.
Cause 4: Execution Timeout or GitHub API Rate Limiting
Large installs that take longer than max_execution_time get killed mid-download, which looks identical to a silent SSH drop. Check and raise it alongside memory_limit in the same CLI php.ini. Separately, Composer pulls package metadata from the Packagist/GitHub API, which has a low unauthenticated rate limit (60 requests/hour) - shared IPs on hosting servers burn through that fast because other tenants are hitting it too. You'll see this as API rate limit exceeded partway through resolution.
Fix it by giving Composer a personal access token so it authenticates instead of sharing the anonymous quota:
composer config -g github-oauth.github.com YOUR_TOKEN_HERE
A token needs no special scopes for public repos - just generate a basic one from GitHub's Developer Settings.
Quick Reference
| Error you see | Likely cause | Fix |
|---|---|---|
| Allowed memory size exhausted | CLI memory_limit too low | COMPOSER_MEMORY_LIMIT=-1 or raise CLI memory_limit |
| proc_open() Permission denied / silent hang | proc_open disabled | Ask host to allowlist for CLI PHP, or move to a VPS |
| command not found | No SSH / Composer not on PATH | Install composer.phar locally in home dir |
| API rate limit exceeded | Shared-IP GitHub API throttling | Add a GitHub OAuth token via composer config |
| Session drops with no error | max_execution_time hit | Raise CLI timeout in php.ini |
Prevention
Once it's working, keep it working: commit composer.lock so every deploy resolves the exact same versions instead of re-solving the graph from scratch (that alone avoids most memory spikes). Run composer install, not composer update, in deployment scripts - update re-resolves everything and is far heavier. And if you're regularly deploying PHP frameworks rather than just running WordPress, a VPS with full SSH and CLI control saves you from fighting shared-hosting restrictions every time you add a package.
Frequently asked questions
Why does Composer work locally but fail on my hosting account?
Your local machine almost certainly has a higher CLI memory_limit and no disable_functions restrictions. Hosting environments - especially shared cPanel accounts - deliberately cap both for security and resource-sharing reasons, so the same composer.json can behave very differently on the server.
Is it safe to set COMPOSER_MEMORY_LIMIT=-1 permanently?
It's fine to use per-command when you're actively installing or updating packages, since it only affects that one process. Don't set it globally in a shell profile on a shared account - if something runs Composer unattended (like a deploy hook) with no ceiling, a bad dependency graph could consume more memory than your account is allotted.
My host says they won't enable proc_open. What are my options?
Run composer install on your local machine or in a CI pipeline, then deploy the vendor/ folder alongside your code via Git or SFTP - Composer itself never needs to run on the server. For frequent deploys, moving to a VPS where you control the PHP configuration is usually less friction long-term.
Does upgrading to a bigger hosting plan actually fix this?
It fixes the memory and timeout causes, since those scale with plan resources. It won't fix proc_open being disabled by policy - that's a security setting, not a resource limit, so check with your host before assuming a plan upgrade solves it.
Can I avoid running Composer on the server entirely?
Yes - many teams build the vendor/ directory as part of their CI pipeline and deploy the finished artifact, which is arguably better practice anyway since it keeps package resolution out of production. Just make sure vendor/ isn't excluded by your .gitignore if you're deploying via Git.