How to Deploy a Laravel App to cPanel Shared Hosting (2026)
A step-by-step guide to deploying Laravel on cPanel shared hosting the right way — fixing the public folder, setting up the database and .env, running migrations, and automating it with GitHub Actions.
Deploying Laravel to shared hosting has a reputation for being painful — mostly because Laravel expects the public folder to be the web root, and cPanel serves everything from public_html. Get that one thing right and the rest is straightforward. This guide walks through the whole process, from uploading your code to running migrations, plus how to automate future deploys so you never repeat these steps by hand.
Everything here works on standard cPanel shared hosting. You do not need a VPS — though you do need a plan that runs a modern PHP version and, ideally, gives you SSH or Terminal access.
Choosing a host for your Laravel project? BabalCloud plans ship with PHP version control, SSH/Terminal access, and an automated GitHub-to-cPanel pipeline — the exact things that make Laravel deployment painless. See pricing or how deployment works.
The core problem: Laravel's public folder vs cPanel's public_html
In a Laravel project, only the public directory should ever be reachable from the web. Everything else — your .env file, routes, config, database credentials — must stay private. But on cPanel, the folder that's served to visitors is public_html. So the whole job of "deploying Laravel to cPanel" comes down to bridging those two facts without exposing your application files.
There are two clean ways to do it. Pick the one that matches your access level.
What you'll need before deploying
- A Laravel project that runs locally without errors.
- A cPanel hosting account with PHP 8.2 or higher (check under MultiPHP Manager or Select PHP Version).
- Your app's Composer dependencies installable on the server (or uploaded).
- Access to phpMyAdmin (for the database) and ideally Terminal/SSH (for artisan commands).
Confirm your PHP version first — Laravel 11 and 12 need PHP 8.2+, and deploying onto an old PHP build is the most common cause of a white screen.
Method 1: Keep the app outside public_html (recommended)
This is the correct, secure approach. Your Laravel app lives in a private folder, and only its public contents are exposed.
Step 1 — Upload your project
Zip your Laravel project locally (exclude node_modules and vendor to keep it small), then in cPanel File Manager, upload and extract it to a folder above the web root — for example /home/username/laravelapp/, not inside public_html.
Step 2 — Install dependencies on the server
If you have Terminal/SSH access, run inside the project folder:
composer install --optimize-autoloader --no-devNo SSH? Then include the vendor folder in your upload instead — build it locally with the same command first, then upload it with the rest of the project.
Step 3 — Move the public folder's contents into public_html
Copy everything inside your project's public folder into public_html. Then open public_html/index.php and update the two paths that point back to your app:
// Point these at your app folder, one level up from public_html
require __DIR__.'/../laravelapp/vendor/autoload.php';
$app = require_once __DIR__.'/../laravelapp/bootstrap/app.php';Now visitors hit public_html/index.php, which boots the app that safely lives in laravelapp/ — exactly the separation Laravel wants.
Step 4 — Create the database
In cPanel, open MySQL Databases and create a database and a user, then add the user to the database with All Privileges. Note the database name, username, and password — they're prefixed with your cPanel account name (e.g. cpuser_appdb).
Step 5 — Configure your .env
Edit .env in your laravelapp/ folder with production values:
APP_ENV=production
APP_DEBUG=false
APP_URL=https://yourdomain.com
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_DATABASE=cpuser_appdb
DB_USERNAME=cpuser_appuser
DB_PASSWORD=your-strong-passwordSet APP_DEBUG=false in production — leaving it on exposes stack traces and config to the public. If your app key is empty, generate one with php artisan key:generate.
Step 6 — Run migrations and cache config
Over SSH/Terminal, from the app folder:
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan storage:link--force is required because production migrations otherwise ask for confirmation. No SSH access? You can import your schema through phpMyAdmin, but running artisan is far cleaner — it's worth choosing a host that gives you Terminal access.
Method 2: Symlink public_html to the public folder
If your host lets you delete and recreate public_html as a symlink, you can skip editing index.php entirely. Over SSH:
rm -rf ~/public_html
ln -s ~/laravelapp/public ~/public_htmlNow public_html is Laravel's public folder. This is the tidiest setup, but some shared hosts disable symlink creation — if the command fails, use Method 1.
Automate it: deploy on every git push
Doing all of the above once is fine. Doing it on every change is not. Wire up GitHub Actions so that pushing to main deploys automatically. Here's a minimal SSH-based workflow that syncs files and runs post-deploy commands:
name: Deploy Laravel to cPanel
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy over SSH
uses: appleboy/[email protected]
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd ~/laravelapp
git pull origin main
composer install --optimize-autoloader --no-dev
php artisan migrate --force
php artisan config:cache
php artisan route:cacheStore SSH_HOST, SSH_USER, and SSH_PRIVATE_KEY as repository secrets (GitHub → Settings → Secrets and variables → Actions). For the full walkthrough of setting up these keys and secrets, see our guide on auto-deploying from GitHub to cPanel.
Troubleshooting
White screen / HTTP 500. Almost always a PHP version mismatch or a missing vendor folder. Set PHP to 8.2+ in cPanel and confirm dependencies are installed. Temporarily set APP_DEBUG=true to read the real error, then turn it back off.
"No application encryption key has been specified." Run php artisan key:generate, or set a valid APP_KEY in .env.
403 Forbidden or directory listing instead of the app. Your web root isn't pointing at the public folder. Recheck Step 3 or the symlink in Method 2.
Storage/permission errors. Laravel needs to write to storage/ and bootstrap/cache/. Set those folders to 755 and ensure they're owned by your cPanel user.
Images/uploads return 404. Run php artisan storage:link so public/storage points to storage/app/public.
Frequently asked questions
Can Laravel really run on shared hosting, or do I need a VPS?
For most small-to-medium apps, shared cPanel hosting is perfectly capable of running Laravel. You'll want a VPS only when you need queue workers, custom services, or heavy background processing that shared plans limit.
What PHP version does Laravel need?
Laravel 11 and 12 require PHP 8.2 or newer. Always check and set the PHP version in cPanel before deploying — it's the number-one cause of deployment failures.
How do I run queue workers on shared hosting?
Use a cron job in cPanel to run php artisan schedule:run every minute, and process queues with queue:work --stop-when-empty triggered on a schedule, since shared hosts don't allow always-on daemons.
Do I need SSH access?
Not strictly, but it makes everything easier — running migrations, clearing caches, and installing Composer packages. If you can, choose a plan that includes Terminal or SSH access.
How do I deploy Laravel updates without downtime?
Automate deployment with GitHub Actions (above) and run php artisan config:cache and route:cache after each deploy. Because your code is in Git, rolling back a broken release is just a git revert and push.
Summary
Deploying Laravel to cPanel is really just three ideas: keep the app private, expose only the public folder, and run your migrations and caches after each deploy. Do it once by hand to understand it, then automate it with GitHub Actions so future releases are one git push.
If you want a host where PHP versions, SSH access, and automated GitHub deployment are built in rather than bolted on, take a look at BabalCloud's hosting plans — they're designed for exactly this developer workflow.