Deploy Laravel to cPanel and VPS: A Step-by-Step Guide

How do you deploy Laravel to cPanel?
To deploy Laravel to cPanel means moving the project files to your hosting account, installing dependencies with Composer, filling in a production .env file, and pointing the domain's document root at the project's public folder. After that, you run the migrations, fix permissions, and add one cron line for scheduled tasks.
We are a digital marketing and web team, not a hosting company. So we based every command and setting name in this guide on the official Laravel, Composer, and cPanel documentation. Our guide does not describe running servers of our own.
Who is this guide for? If you own a website or an online store, it helps you understand what your developer and your hosting provider are doing. If you are a developer who manages your own VPS or cPanel account, you can follow the commands step by step. We do not pin version numbers or default values here, because they change with your Laravel version.
The last sections also cover common errors and the moments when you should hand the job to your host. Part of a good decision is knowing which command to type. Another part is knowing when not to type it. If this is your first deployment, check the result after every step.
What should you check before you start the deployment?
The official Laravel deployment documentation lists the minimum PHP version and the required extensions. The current version of that page asks for PHP 8.3 or higher. However, the number changes between Laravel releases. So check the php line in your project's composer.json and the documentation page for your own version.
The name of the PHP selector in cPanel depends on your host. Many providers show a screen called MultiPHP Manager or Select PHP Version. After you pick the version, confirm that the extensions are on. The documentation lists these extensions:
- Ctype, cURL, DOM, and Fileinfo.
- Filter, Hash, Mbstring, and OpenSSL.
- PCRE, PDO, Session, Tokenizer, and XML.
You also need the PDO driver for your database. For example, if you use MySQL, pdo_mysql must be on. Finally, check whether you have terminal access. Composer and php artisan need a terminal, because they are command line tools. Some shared hosting plans keep it off.
Should you deploy Laravel to cPanel, a VPS, or a managed platform?
The answer depends on how much control you want and how much responsibility you can carry. Shared hosting with cPanel is cheap and simple. However, it is limited for long-running processes such as queue workers. A VPS gives you full control, but security and updates become your job.
Laravel's own documentation mentions two managed options. Laravel Cloud is a fully managed deployment platform. Forge is a VPS management tool for people who want their own servers without installing every service by hand. The table below gives a general frame.
| Criterion | Shared hosting with cPanel | VPS | Managed platform |
|---|---|---|---|
| Control | Limited by provider rules | Full control | As much as the platform offers |
| Terminal access | Depends on the provider | Always available | Platform interface and tools |
| Queue worker | Usually an indirect cron workaround | Persistent process with Supervisor | The platform handles it |
| Security duty | Mostly with the provider | With you | Mostly with the platform |
| Best for | Small and mid-size sites | Apps with special needs | Growing products |
We covered the marketing and performance side of this choice in our guide on how to choose web hosting. Here we only explain what is specific to Laravel. For a small company site or an early-stage store, a Laravel cPanel setup is often enough. As traffic grows, the talk turns to a VPS or a managed platform.
How do you get the project files onto the server?
There are three common ways: pull with Git, upload a zip file in File Manager, or send the files over SFTP. Git is the tidiest, because you always know which version runs in production. If Git is new to you, our Git and GitHub guide explains the basic commands.
Whichever way you choose, these rules apply:
- Do not copy your local .env file to the server. You will prepare a separate one for production.
- Do not upload node_modules. If you will not build the front end on the server, build it locally and upload the output files.
- Create the vendor folder on the server with Composer if you can. Without a terminal, you have to build it locally and upload it.
- Keep the application outside the public folder of your domain. We explain why in the public folder section.
In short, the safest layout keeps the application folder private and exposes only the public contents to the web.
Tagging the release before you upload also helps. If something breaks, you know which version to return to. Also schedule the upload for a quiet hour. On a store, a deployment during peak traffic can cost you orders.
How do you install dependencies with Composer on the server?
You enter the project folder and run Composer's install command with production flags. According to the official Composer command documentation, install uses the exact versions in composer.lock when that file exists. So the package versions you tested locally are the ones that reach production.
cd /path-to-your-project
composer install --no-dev --optimize-autoloader
The no-dev flag skips packages listed under require-dev. That keeps testing and debugging tools out of production. The optimize-autoloader flag also builds a classmap for faster class loading, and the documentation recommends it for production.
Do not run composer update on the live server, because it changes your lock file. Then an update can pull versions you never tested. If Composer fails on shared hosting because of memory or time limits, build the vendor folder locally with the same command and upload it as a stopgap.
Also match your local PHP version to the server's. If they differ, Composer may refuse packages on the server that worked locally. The error message usually names the package and the version it wants. Reading it and aligning the versions is much safer than forcing the install.
How do you set up the .env file and APP_KEY?
A fresh Laravel install contains a .env.example file, and the installer copies it to .env. On the server you follow the same logic. You copy the example file, fill it with production values, and then generate the application key.
cp .env.example .env
php artisan key:generate
The values below are examples. Replace them with your own:
APP_ENV=production
APP_DEBUG=false
APP_URL=https://example.com
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_DATABASE=account_laravel
DB_USERNAME=account_app
DB_PASSWORD=write-a-strong-password
The Laravel configuration documentation is clear: in production, APP_DEBUG must always be false. If it stays true, error pages can show sensitive configuration values to your visitors. Also keep the .env file out of source control, because anyone who reaches the repository would get your secrets.
Laravel uses APP_KEY for encryption. If you change it later in production, data protected with the old key may become unreadable. So store the key in a password manager.
How do you create the database and run migrations?
In cPanel, you create a new database and a user in MySQL Databases or in the MySQL Database Wizard. Do not forget to add the user to the database with all privileges. cPanel adds your account name as a prefix. So the DB_DATABASE and DB_USERNAME values in .env need the prefixed names.
After you enter the connection details in .env, you create the tables with migrations:
php artisan migrate --force
In production, Laravel asks for confirmation before it runs migrations. The force flag skips that prompt, and you need it in automated deployments. However, migrations can change table structure. If you already have live data, take a backup first. Our website backup strategy guide covers a sensible routine.
If you want to understand queries and database design better, our SQL query scenarios article is a good companion.
How do you set permissions for storage and bootstrap/cache?
According to the Laravel documentation, the application must be able to write to the bootstrap/cache and storage directories. In other words, the owner of the web server process needs write permission there. On most cPanel setups, PHP runs as your account user. However, this can differ between providers.
chmod -R ug+rwx storage bootstrap/cache
This command gives the owner and the group read, write, and execute permission. Do not give these folders full public access (777). Other accounts on the same server, or a security hole, could abuse that permission.
To serve uploaded files from the public disk, you run the storage:link command:
php artisan storage:link
Some shared hosts turn off symbolic links. In that case your images return 404. Ask your provider instead, or change how you serve the files.
User uploads are a separate topic. Validate the type and size of every uploaded file, because unchecked uploads are a serious security risk. Do not keep uploaded documents in folders that can run code. So you write the validation rules in application code, and a server setting does not replace them.
How do you point the domain at the public folder?
Laravel's deployment documentation asks the web server to send all requests to the application's public/index.php file. The warning is explicit: never move index.php to the project root. If you serve the application from the root, many sensitive configuration files become reachable from the internet.
In cPanel, you do this on the Domains screen. According to the cPanel documentation, you click Manage next to an existing domain to change its document root. Then you enter the path of your project's public folder in the document root field. For example, the path is your account folder, then the application folder, then public.
Subdomains and addon domains usually work without trouble. On the main domain, some providers keep the document root fixed. In that case, read the options in the next section.
How do you deploy Laravel to cPanel if the main domain root is fixed?
First, ask your provider. Often a single support ticket changes the document root. If that fails, then you either install the project on a subdomain or switch to a layout that moves the public contents into the public web folder.
| Method | How you do it | Watch out for |
|---|---|---|
| Change the document root | Use Manage on the Domains screen and enter the public path | The cleanest option, but the provider must allow it |
| Move the app out of the web folder | Keep the application outside the public web folder and copy the public contents into it | You must update the paths in index.php |
| Symbolic link | Link the public web folder to the public folder | The provider must allow symbolic links |
With the second method, you update the autoload, bootstrap, and maintenance paths in index.php for the new folder layout. You also have to recheck that file after Laravel updates, because the file may change. So this method adds maintenance work.
Whichever you choose, make sure the .env file is not in the public web folder, because that exposes your secrets. Finally, open your domain followed by /.env in a browser. If you can read the file, the setup is unsafe and you must fix it at once.
Which optimization commands should you run in production?
The Laravel documentation recommends caching configuration, events, routes, and views in production. A single optimize command does all of it, and the documentation says it should be part of your deployment process. The table lists the details.
| Command | What it does |
|---|---|
| php artisan optimize | Builds the configuration, event, route, and view caches together |
| php artisan config:cache | Combines all configuration files into one file |
| php artisan route:cache | Reduces route registrations to one cached file |
| php artisan view:cache | Precompiles Blade views |
| php artisan event:cache | Caches event and listener mappings |
| php artisan optimize:clear | Removes these caches and the keys in the default cache driver |
There is one important trap here. After you cache the configuration, Laravel does not read the .env file, and the env function returns null. So call env only inside the files in the config folder. In your application code, read values with the config function.
For a wider view of caching, read our article on how caching works with Redis and Memcached.
How do you set up the scheduler cron job on cPanel?
Laravel's scheduler needs only one cron line on the server. That line runs the schedule:run command every minute, and the command decides which tasks are due. You define the tasks in routes/console.php. So the schedule stays in source control together with your code.
The line from the Laravel documentation looks like this. Replace the path with your own project:
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
In cPanel, open the Cron Jobs screen, choose every minute, or enter five asterisks by hand. Then write the absolute file path in the command box. The path to php also differs between providers. So check the PHP information in your hosting panel, or try the which php command in a terminal. A cron job with the wrong PHP version can fail silently even when the website opens fine.
The cPanel cron documentation gives two warnings. First, leave enough time between cron jobs for the previous one to finish. Second, if you do not add /dev/null to the end, you receive an email for each run. After setup, run php artisan schedule:list to confirm your tasks appear. For example, if you defined a daily report, you will see its next run time. Do not use schedule:work in production, because the documentation shows it for local development.
How do you run queue workers on cPanel and on a VPS?
The queue:work command is a long-running process. According to the documentation, workers keep your application code in memory. In other words, if you do not restart them after a release, they keep running the old code. So you run php artisan queue:restart in every deployment.
On a VPS, you keep the workers alive with a process manager such as Supervisor. A short version of the documentation's example looks like this:
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /path/to/artisan queue:work
autostart=true
autorestart=true
numprocs=2
redirect_stderr=true
stdout_logfile=/path/to/worker.log
stopwaitsecs=3600
Shared hosting usually has no process manager. A common workaround is to drain the queue from cron at short intervals. The stop-when-empty and max-time options of queue:work suit this. However, this method does not process jobs instantly.
For example, if an order confirmation email or a stock sync is late, the customer notices. Instead of a cron workaround, give jobs like these a real worker. If your queue is critical, consider a VPS or a managed platform. Also add the worker restart to your deployment checklist.
Which Nginx settings do you need on a VPS?
On a VPS, you write the web server configuration yourself. The Laravel documentation gives a full Nginx example. So take it as a starting point and adapt it to your server. In particular, the root line must point to the project's public folder.
server {
listen 80;
server_name example.com;
root /srv/example.com/public;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
}
This short example only shows the idea. The full example also includes security headers, the PHP-FPM connection, and a rule that blocks dotfiles. The PHP-FPM socket path changes with the installed PHP version. So do not copy the path from the documentation as it is.
You also need a certificate for HTTPS. On most cPanel hosts, the provider issues it automatically. On a VPS, however, you install it yourself. We explain the topic in our guide on SSL certificates and HTTPS security.
What does the .htaccess file do when you deploy Laravel to cPanel?
In Laravel's default skeleton, the public folder includes a ready .htaccess file for Apache. It sends requests for addresses that do not exist as files to index.php. So clean URLs such as /products work, and you do not need a separate file for each route.
Most cPanel hosts run Apache or a compatible server. So it should work without extra setup. However, if you point the document root at the wrong folder, the .htaccess file never applies, and only the home page opens. Therefore, if your routes return 404, check the document root first.
Take a backup before you edit your own .htaccess. A small typo can turn the whole site into a 500 error. If you are unsure, ask your provider's support instead of touching the file.
How do you configure email and logs?
If your application sends notification, order, or password reset emails, you need to fill in the values that start with MAIL in your .env file. In cPanel, you can create an email account and use the SMTP details your provider gives you. Keep the passwords only in .env, because that file stays private.
Logs matter as much as email. Because you turned off the debug screen in production, the storage/logs folder is your only source of information. Remember that this folder can also grow over time. If the disk quota fills up, the application throws write errors.
So check the log files regularly. Also send one test email from production to an address of your own. Do not send test messages to real customers. If you use queues, confirm that the emails land in the queue and that a worker processes them.
How do local development and production differ?
A Laravel project that works locally may behave differently in production. The two environments differ in error display, caching, and background processes. The table summarizes the main differences from the documentation.
| Topic | Local environment | Production |
|---|---|---|
| APP_DEBUG | May be true | Always false |
| Configuration cache | Off, changes show at once | On with config:cache |
| Scheduler | schedule:work | One cron line every minute |
| Queue worker | You start it by hand | Process manager or cron |
| Packages | Dev packages included | Only what you need, with no-dev |
In practice, it is a good habit to try your APP_ENV and cache settings once locally as if they were production. That way you catch surprises with the env function early.
Why does it matter for SEO when you deploy Laravel to cPanel?
The technical setup directly affects search visibility. If a misconfigured site returns a 500 error, Google's crawler cannot reach your pages. If HTTPS is missing, users see a browser warning. A slow server then weakens both rankings and conversions.
So when your Laravel cPanel deployment is done, check these points: do all addresses open over HTTPS, is the robots.txt file reachable, and do pages create redirect chains? You can build the robots file with our robots.txt generator.
The link between speed and sales is even stronger on online stores. We covered it in our article on whether ecommerce page speed affects sales. So on a store built with Laravel, your cache and hosting choices also change how far your marketing budget goes.
How do you test the deployment afterward?
First open the home page, and then open a route other than the home page. If the home page opens but other routes return 404, the document root or the rewrite rules are wrong. After that, run these checks:
- Open the /up address. Laravel's health route returns 200 when the application boots without exceptions, and 500 otherwise.
- Type /.env after your domain. If you cannot see the file contents, it works as it should.
- Confirm that a log file appears in storage/logs and that it is writable.
- Check that your tasks appear in the php artisan schedule:list output.
- Verify the certificate and the DNS records with tools.
For the certificate and DNS, use our SSL checker and our DNS lookup tool. After launch, measuring speed is also a good step, and a Lighthouse performance test does that. For the link between speed and rankings, read how site speed affects SEO.
Which errors do you meet most often when you deploy Laravel to cPanel?
Most errors come from a few causes: a wrong document root, a missing key, permissions, and a stale cache. Always read the log in storage/logs first, because you see no details on screen while APP_DEBUG is off. The table below summarizes the likely causes.
| Symptom | Likely cause | What you do |
|---|---|---|
| Blank page or 500 error | Permissions, missing .env, or wrong PHP version | Read the log and check permissions and version |
| No application encryption key warning | APP_KEY is empty | Run php artisan key:generate |
| Only the home page opens | Document root or rewrite problem | Point the document root at the public folder |
| .env change has no effect | Configuration is cached | Run php artisan config:clear, then cache again |
| Uploaded images return 404 | No symbolic link | Run php artisan storage:link |
| Class not found error | A service provider uses a dev package | Move the package to require or remove the registration |
Pasting the error message into a search engine is often the fastest route. Copy the whole message, because the file name and line number matter. That way you find the source of the problem sooner. However, compare any command you find with the Laravel documentation before you run it.
When should you leave the deployment to your hosting provider?
You do not have to do everything yourself. In some cases, handing the work to your provider or an experienced system administrator is safer. Since we are not a hosting company, we state this limit up front.
- You have real customer or order data in production and no backup.
- You lack the experience to manage SSH, firewalls, and operating system updates.
- Your hosting account has no terminal, and you need persistent processes such as queues.
- You need zero-downtime deployment and high availability.
- You are launching an application that handles payments or personal data for the first time.
In these cases, let your provider do the setup, and only verify the result. On the security side, our OWASP Top 10 guide shows which weaknesses to watch. So you can use those topics as a checklist when you talk with your technical team.
You can ask a provider for automatic backups, PHP version management, an SSL certificate, and fast support when something breaks. On a host that offers these, the risky parts of a Laravel setup move to the provider. Then you can focus on the marketing and product side of your work.
Which checklist should you follow in every deployment?
Once you have deployed by hand one time, running the same steps in the same order every time reduces mistakes. The sequence below combines the official commands we covered in this guide. Adapt it to your own project.
php artisan down
git pull
composer install --no-dev --optimize-autoloader
php artisan migrate --force
php artisan optimize
php artisan queue:restart
php artisan up
The documentation says the down command causes a short outage. If you want zero-downtime deployment, consider a managed platform. Also, if you defined sub-minute tasks, add the schedule:interrupt command at the end of the deployment.
Finally, check the health route and the home page after every deployment, because users should not find problems first. That way you catch problems before your users do. Most failures in a Laravel cPanel deployment come from skipping one step, so keep the list in writing. When your team grows, it makes sense to turn these steps into a script or an automated pipeline.



