On this page
Fixing 'Permission denied' errors when running Magento CLI commands
Learn how to resolve 'Permission denied' errors when running Magento CLI commands over SSH on Kualo shared hosting.
If you see a 'Permission denied' error when running bin/magento commands over SSH, the cause is almost always one of three things: how the command is being invoked, the execute permission on the script, or file ownership left wrong by a migration or restore. This article walks you through each fix in order.
Why this happens on shared hosting
Our servers run CloudLinux, which isolates every cPanel account under its own system user. This is good for security, but it means file ownership and permissions matter more than they might on a single-user server. For bin/magento to run, the files must be owned by your cPanel account user, and the way you invoke the command determines which permissions actually apply.
No server-level changes are needed from your side. If you work through the steps below and the problem persists, contact our support team.
Check how you are invoking the command
There are two ways to run Magento's CLI, and they fail differently:
php bin/magento cache:flush
./bin/magento cache:flush
The first form passes the script to PHP directly and does not require bin/magento to be executable at all. The second form runs the script itself, which requires the execute permission to be set - and if it is missing, you get exactly the error this article is about: Permission denied.
So the quickest fix is simply to use the php bin/magento form, which is what all our Magento guides use. If you prefer the ./bin/magento form, restore the execute bit:
- Navigate to your Magento root directory, for example:
cd ~/public_html
- Check the current permissions:
ls -l bin/magento
If the output shows -rw-r--r-- rather than -rwxr-xr-x, the execute bit is missing.
- Add it and confirm:
chmod +x bin/magento
ls -l bin/magento
If your Magento files were restored from a backup, uploaded via File Manager, or transferred from another host, the execute bit is often stripped in the process. Always check it after a restore or migration.
If php bin/magento also returns 'Permission denied', the problem is not the execute bit - continue to the ownership section below.
Make sure the CLI uses the same PHP version as your website
On our CloudLinux servers, the php command in your SSH session uses whichever PHP version you have selected in cPanel's Select PHP Version tool. Check it with:
php -v
The catch is that your website does not necessarily run the same version. The PHP version for web requests can be set separately - most commonly by an AddHandler line in your site's .htaccess file, often left behind by a migration or added by a developer to pin a specific version. When that happens, your SSH php command and your website are running different PHP versions, and Magento commands run over SSH will behave inconsistently with the live site.
This matters more for Magento than most applications. Commands such as setup:upgrade, setup:di:compile, and setup:static-content:deploy generate code and configuration that your web requests then execute, so they must run under the same PHP version as the site itself. A mismatch can cause anything from Composer refusing to run to subtle errors that only appear in the browser.
To check whether your site's version is pinned, look for an AddHandler line in your Magento root:
grep -i addhandler ~/public_html/.htaccess
If nothing is returned, your site follows your cPanel PHP Selector version and the plain php command is correct - use it for all Magento commands.
If an AddHandler line is present, the version it names is what your website actually runs. You have two options:
- Align the versions (recommended) - remove the AddHandler line and set the version you want in the PHP Selector instead, so the site and CLI always agree. Check with your developer first if you are unsure why the line is there.
- Match the binary manually - run Magento commands using the versioned binary that corresponds to the handler. For example, if the handler names PHP 8.2:
/opt/alt/php82/usr/bin/php bin/magento cache:flush
If you are unsure which binary path matches the handler in your .htaccess, or php -v does not match your PHP Selector setting even with no AddHandler present, contact our support team and we will confirm the right setup for your account.
Check file ownership
Every file in your Magento installation should be owned by your cPanel account user. Ownership problems typically appear after a migration from another server, a restore, or - on dedicated servers - commands previously run as root. Files owned by another user cannot be read, written, or fixed from within your account, because shared hosting accounts cannot use chown to claim files.
To confirm which user you are:
whoami
And to spot files owned by someone else in the key directories:
ls -ld var/ generated/ pub/static/ pub/media/
All should show your cPanel username as the owner. If any show a different owner, such as root, contact our support team and we will correct ownership at the server level.
If you have an unmanaged dedicated server or have a developer who deploys with root access, never run bin/magento commands as root. Any files written during the command - compiled classes, static assets, cache files - become owned by root, and the site then fails in the browser even though commands appear to work. Always run Magento commands as the account user that owns the files.
Silent failures in setup:upgrade and static-content:deploy
Some bin/magento commands appear to complete without errors but changes do not take effect. This usually means the command could not fully write to var/, generated/, or pub/static/ because of wrong permissions within those directories - often after a restore, a File Manager operation, or a previous command run as the wrong user.
If the directories are owned by your account user but have restrictive or inconsistent permissions, correct them:
find var/ generated/ pub/static/ -type d -exec chmod 755 {} \;
find var/ generated/ pub/static/ -type f -exec chmod 644 {} \;
Never set permissions to 777 - it is not required on our servers, and it allows any compromise of any script to modify your files. 755 for directories and 644 for files is correct and sufficient.
Magento also writes uploaded images to pub/media/. If product images go missing after a restore, check that directory's ownership and permissions in the same way.
Once permissions are correct, run the standard regeneration sequence:
php bin/magento setup:upgrade
php bin/magento setup:di:compile
php bin/magento setup:static-content:deploy -f
php bin/magento cache:flush
For guidance on reading any errors that appear during these commands, see our article on debugging Magento 2 errors and log locations, and for the wider command reference, see essential Magento 2 commands to run over SSH.
When to contact us
If you have worked through the steps above and still see permission errors, the issue is likely something only we can fix:
- Files in your account owned by root or another user.
- A PHP version mismatch between your website and the CLI that you cannot resolve.
- CloudLinux account configuration preventing processes from running.
Please raise a support ticket and include the exact error message, the command you ran, and we will investigate and resolve it for you.