How to deploy a Laravel application
Point the document root at Laravel's public folder, set up .env, run migrations, and cache the config — what a Laravel deploy needs.
Laravel expects a specific folder layout: one folder, public, is meant to be reachable by a browser, and everything else — application code, configuration, the .env file, the vendor folder — is meant to sit outside it. Getting that one arrangement right is most of what makes a Laravel deployment different from dropping plain PHP files into a folder.
Document root: the part that trips people up
If your hosting lets you set a custom document root per domain, point it at the project's public folder rather than the project root:
/home/youraccount/laravel-app/ <- project root, NOT public
/home/youraccount/laravel-app/public/ <- point the document root here
Some shared hosting only lets you serve from a fixed folder such as public_html. In that case, upload the Laravel project one level above public_html, then move only the contents of the project's public folder into public_html, and edit public_html/index.php to point its require paths at the actual location of vendor/autoload.php and bootstrap/app.php one directory up. This keeps application code and .env outside the web-reachable folder even when the hosting itself does not offer a configurable document root.
Getting the application onto the server
Two common routes, both covered in more detail elsewhere in this section:
- Deploy from a Git repository, pulling the latest commit onto the server and running the remaining steps below afterwards.
- Sync files with rsync, excluding
.env,vendorandnode_modulesfrom the transfer so they are managed separately per environment rather than overwritten from your local copy.
Installing dependencies
Over SSH, in the project root — not public — run Composer with production flags:
composer install --no-dev --optimize-autoloader
--no-dev skips packages only needed for local development and testing, and --optimize-autoloader builds a faster class map for production. See using Composer on shared hosting if you have not installed Composer into the account yet.
The .env file
Laravel reads its configuration from a .env file in the project root, and this file should never be committed to version control or copied unchanged between environments — it holds database credentials and the application encryption key, and production needs its own values, not the ones from local development.
APP_ENV=production
APP_DEBUG=false
APP_KEY=base64:generate-this-with-artisan
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_DATABASE=yourdatabase
DB_USERNAME=yourdbuser
DB_PASSWORD=yourdbpassword
Generate a fresh application key rather than reusing one from another environment:
php artisan key:generate
With debug mode on, an unhandled exception shows a full stack trace, file paths and configuration values directly to visitors. Confirm APP_DEBUG=false before the site goes live — this is one of the most common accidental information leaks on a freshly deployed Laravel site.
See setting environment variables for more on how .env works and alternatives where your control panel offers its own environment variable screen instead.
Database and cache setup
- Run the migrations
php artisan migrate --forceapplies the schema. The--forceflag is required to run migrations whenAPP_ENVis set to production, as a deliberate guard against running them by accident. - Cache the configuration
php artisan config:cachecombines every config file into one cached file, which is faster to load on every request than reading and merging them individually. - Cache routes and views
php artisan route:cacheandphp artisan view:cachedo the same for the route table and compiled Blade templates.
If you change a config value, a route or an environment variable after caching, the cached version keeps being served until you clear it: php artisan config:clear (and the matching route:clear, view:clear) followed by re-running the cache commands above. A change that appears to have no effect after a deploy is very often this.
File permissions
Laravel needs to write to two folders — storage and bootstrap/cache — for logs, compiled views and cached files. If either is not writable by the PHP process, the application throws permission errors on almost every page. On shared hosting this is usually a matter of confirming ownership matches your account rather than opening permissions further than necessary.
Scheduled tasks and queues
If the application uses Laravel's scheduler, a single cron entry runs everything it defines — see scheduling a PHP script for the cron syntax involved:
* * * * * php /home/youraccount/laravel-app/artisan schedule:run >> /dev/null 2>&1
Queues that rely on a persistent worker process are generally a poor fit for shared hosting, since there is no long-running process to keep a worker alive between requests — that is a good reason to consider a VPS for an application that depends heavily on queued jobs.
Related reading
Composer runs fine on shared hosting over SSH — here is how to install it, run it, and keep dependencies out of the public folder.
How to set environment variables on your hostingWithout root access, environment variables come from a control panel screen where one exists, or from a .env file your app loads itself.
How to deploy your website from GitAdding SSH keys, connecting a remote and choosing pull-based or push-to-deploy — what a Git deployment setup needs on hosting.
How to set up SSH keys for your hostingGenerate a key pair, add the public half to your hosting account, and connect over SSH without a password from then on.