How to Deploy a Laravel Application on Shared Hosting: Complete Step-by-Step Guide

Deploying a normal HTML or PHP website to shared hosting is usually simple. You upload the files, connect the domain, and the website starts working.

Laravel needs a few additional steps.

A Laravel application has Composer dependencies, environment variables, database configuration, storage permissions, cache files, and a dedicated public directory. If any of these are configured incorrectly, you may see a 500 error, blank page, missing CSS, database error, or a website that only works through /public.

This guide explains how to deploy a Laravel application on shared hosting step by step.

What You Need Before Deploying Laravel

Before uploading your application, make sure you have:

  • A domain or subdomain

  • A compatible shared hosting account

  • PHP support

  • MySQL or MariaDB if your application uses a database

  • File Manager or FTP access

  • SSH or Terminal access if available

  • Composer support, or a locally generated vendor directory

  • Your Laravel project files

  • Your production .env configuration

The required PHP version depends on your Laravel version.

For example, Laravel 13 requires PHP 8.3 or later along with several standard PHP extensions. Always check the requirements for the Laravel version used by your project before changing the server PHP version.

Step 1: Prepare Your Laravel Application

Before uploading the project, test it locally.

Make sure:

  • The application starts correctly

  • Database migrations are complete

  • Routes work

  • Login works

  • File uploads work

  • There are no unresolved development errors

It is much easier to diagnose a problem locally before adding hosting configuration into the mix.

Your Laravel project will normally contain folders similar to:

app/
bootstrap/
config/
database/
public/
resources/
routes/
storage/
vendor/

and files such as:

.env
artisan
composer.json
composer.lock

Step 2: Create Your Domain or Subdomain

Create the domain you want to use for the application.

For example:

example.com

or:

app.example.com

If your hosting panel allows you to choose a document root, point it directly to Laravel's public directory.

For example:

/home/username/laravel-app/public

This is the preferred configuration.

Laravel's official deployment documentation says web requests should be directed to public/index.php and warns against serving the Laravel project root publicly because sensitive files may be exposed.

Step 3: Upload Your Laravel Project

Upload your Laravel application to the server.

For example:

/home/username/laravel-app/

The structure should look similar to:

laravel-app/
├── app/
├── bootstrap/
├── config/
├── database/
├── public/
├── resources/
├── routes/
├── storage/
├── vendor/
├── .env
├── artisan
├── composer.json
└── composer.lock

Do not upload only the contents of the public folder.

Laravel requires the rest of the framework files to run.

Step 4: Point the Domain to the Public Folder

The safest setup is:

Domain:
https://example.com

Document Root:
/home/username/laravel-app/public

Your users visit:

https://example.com

while the web server serves:

laravel-app/public/index.php

Visitors should not need to enter:

https://example.com/public

What If Shared Hosting Does Not Allow Changing the Document Root?

Some hosting environments force your domain to use:

public_html

If your Laravel project is directly inside public_html, you may temporarily use a root .htaccess rewrite.

Create:

public_html/.htaccess

and add:

<IfModule mod_rewrite.c>
    RewriteEngine On

    RewriteCond %{REQUEST_URI} !^/public/
    RewriteRule ^(.*)$ public/$1 [L]
</IfModule>

Laravel's normal .htaccess should remain inside:

public/.htaccess

Changing the actual document root to public is preferable whenever your hosting environment supports it.

Step 5: Install Composer Dependencies

Laravel needs Composer dependencies from the vendor directory.

If SSH or Terminal access is available, go to your Laravel project directory:

cd /home/username/laravel-app

Then run:

composer install --no-dev --optimize-autoloader

For a production application, --no-dev prevents development-only dependencies from being installed.

Do not normally run:

composer update

during deployment unless you specifically intend to change dependency versions.

Using composer install with an existing composer.lock installs the dependency versions defined for the application.

What If Composer Is Not Available on Shared Hosting?

You can install dependencies on your local computer:

composer install --no-dev --optimize-autoloader

Then upload the generated:

vendor/

directory together with the project.

Make sure your local PHP environment and server are compatible with the packages used by the application.

Step 6: Create the Production .env File

Laravel uses .env for environment-specific settings.

A basic production configuration may look like:

APP_NAME="My Application"
APP_ENV=production
APP_KEY=
APP_DEBUG=false
APP_URL=https://example.com

LOG_CHANNEL=stack

DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=database_name
DB_USERNAME=database_user
DB_PASSWORD=database_password

Do not copy your local database credentials directly to production.

Replace them with the database information from your hosting account.

Set APP_ENV to Production

For a production server, use:

APP_ENV=production

Avoid:

APP_ENV=local

on the live website.

Disable APP_DEBUG

Production applications should normally use:

APP_DEBUG=false

Laravel's deployment documentation recommends keeping debug mode disabled in production because debug responses can expose sensitive configuration information.

Do not leave:

APP_DEBUG=true

enabled on a public production website just because you are troubleshooting an error.

Turn it off again after troubleshooting.

Step 7: Generate the Laravel APP_KEY

Check your .env file.

You should have:

APP_KEY=base64:...

If this is a new deployment and no application key exists, run:

php artisan key:generate

Do not casually regenerate the APP_KEY on an existing production application.

Laravel uses this key for encryption, and changing it can affect encrypted data, cookies, and sessions.

Step 8: Create the MySQL Database

Open your hosting control panel and create:

  1. A MySQL database

  2. A database user

  3. A strong password

Then assign the user to the database with the required privileges.

Update .env:

DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=your_database
DB_USERNAME=your_username
DB_PASSWORD=your_password

Some hosting providers use a database hostname other than:

localhost

Use the hostname supplied by your hosting company.

Step 9: Import an Existing Database

If your Laravel application already has production-ready data, export the database from your existing environment.

You may have a file such as:

database.sql

Open phpMyAdmin or another database management tool and import it into the new database.

Then make sure the .env credentials point to that database.

Step 10: Run Laravel Migrations

If you are deploying a new application and the database should be created through Laravel migrations, run:

php artisan migrate --force

The --force option is commonly needed when running migrations in a production environment.

Before running migrations against an existing live database, make sure you understand what the migration will change.

Take a database backup before performing significant production database changes.

Step 11: Configure Storage Permissions

Laravel needs write access to:

storage/

and:

bootstrap/cache/

On many Linux hosting environments, permissions such as the following may work:

chmod -R 775 storage
chmod -R 775 bootstrap/cache

Permissions depend on your server configuration and file ownership.

Do not automatically set everything to:

777

because it grants much broader permissions than most applications require.

Laravel specifically requires the web server process to be able to write to storage and bootstrap/cache.

Step 12: Create the Storage Link

If your application stores public files using Laravel's public disk, run:

php artisan storage:link

Laravel stores public-disk files under:

storage/app/public

and uses a symbolic link at:

public/storage

to make those files available through the web.

After creating the link, a file may be accessible through:

https://example.com/storage/image.jpg

Storage Link Already Exists Error

You may see:

ERROR  The [public/storage] link already exists.

Check what currently exists:

ls -l public/storage

If it is already the correct symbolic link, you may not need to do anything.

If it is an incorrect directory, do not immediately delete it.

First check whether it contains uploaded files.

If you know it is safe to remove an incorrect empty directory:

rm -rf public/storage

Then recreate the link:

php artisan storage:link

Be careful with rm -rf. Verify the exact path before running it.

Step 13: Clear Laravel Development Caches

After changing .env or configuration, run:

php artisan optimize:clear

This clears generated optimization caches.

You may also clear individual caches when troubleshooting:

php artisan config:clear
php artisan route:clear
php artisan view:clear

Step 14: Optimize Laravel for Production

Once the application is configured and working, run:

php artisan optimize

Current Laravel documentation recommends optimization during production deployment. The command caches framework configuration used for faster application bootstrapping.

You can also run specific commands separately when needed, such as:

php artisan config:cache
php artisan route:cache
php artisan view:cache

Be aware that route caching can fail if your application contains unsupported route definitions.

Step 15: Enable SSL

Install an SSL certificate for your domain.

Your website should use:

https://example.com

Then update:

APP_URL=https://example.com

and run:

php artisan optimize:clear
php artisan optimize

Test that your application does not generate insecure HTTP links.

Step 16: Check Laravel Public Assets

Open the website and check whether:

  • CSS loads

  • JavaScript loads

  • Images load

  • Vite assets load

  • Uploaded files load

If the website loads without CSS, inspect the generated URLs.

Incorrect:

https://example.com/public/css/app.css

Preferred:

https://example.com/css/app.css

Do not hardcode /public into Laravel asset URLs just to make the local setup work.

Laravel Vite Assets Not Loading

Modern Laravel projects commonly use Vite.

Before deployment, build the frontend assets:

npm install
npm run build

This commonly generates production files under:

public/build/

Upload that build directory if you build assets locally.

If the server does not need to compile assets itself, you do not necessarily need Node.js running continuously just to serve the compiled Laravel frontend.

Step 17: Configure Laravel Email

If your application sends:

  • Password reset emails

  • OTP messages

  • Contact form notifications

  • Invoice emails

  • Account verification messages

configure mail settings in .env.

Example:

MAIL_MAILER=smtp
MAIL_HOST=mail.example.com
MAIL_PORT=587
[email protected]
MAIL_PASSWORD=your_password
MAIL_ENCRYPTION=tls
[email protected]
MAIL_FROM_NAME="${APP_NAME}"

The correct server, port, encryption method, and authentication details depend on your email provider.

After changing mail settings:

php artisan optimize:clear

Step 18: Configure Laravel Queue Workers

Some Laravel applications send emails, notifications, reports, or other tasks through queues.

If your application uses:

QUEUE_CONNECTION=database

or another asynchronous queue driver, queued jobs need a worker.

A typical worker command is:

php artisan queue:work

However, shared hosting may not allow a permanently running process.

Depending on your application and hosting provider, you may need:

  • Supervisor

  • A hosting-specific process manager

  • Cron-based queue processing

  • VPS hosting

If your application depends heavily on long-running queue workers, a VPS may be more suitable than basic shared hosting.

Step 19: Configure Laravel Scheduler

Laravel applications may use scheduled tasks for:

  • Sending reminders

  • Generating reports

  • Cleaning old records

  • Subscription renewals

  • Automated emails

  • Database maintenance

These tasks require the Laravel scheduler to be triggered by the server.

The exact cron configuration depends on your Laravel version and hosting environment.

Use your hosting control panel's Cron Jobs feature and configure it according to your application's scheduler requirements.

Step 20: Protect Your .env File

Never allow visitors to access:

https://example.com/.env

The file may contain:

  • Database passwords

  • SMTP credentials

  • API keys

  • Application secrets

A properly configured Laravel deployment exposes only the public directory, which prevents direct web access to the project's .env file.

This is another reason to point the domain document root directly to:

/path/to/project/public

rather than exposing the entire Laravel project.

Step 21: Check Laravel Logs

If the application returns a 500 error, check:

storage/logs/laravel.log

For example:

tail -f storage/logs/laravel.log

The log can reveal problems such as:

  • Database connection failures

  • Missing classes

  • Permission errors

  • Mail errors

  • Missing configuration

  • Application exceptions

Do not rely only on what the browser displays.

Common Laravel Shared Hosting Problems

500 Internal Server Error

Possible causes include:

  • Incorrect PHP version

  • Missing PHP extensions

  • Incorrect permissions

  • Invalid .htaccess

  • Missing vendor directory

  • Invalid .env

  • Missing APP_KEY

  • Cache permission problems

  • Application exceptions

Start by checking:

storage/logs/laravel.log

and the hosting server's error log.

Composer Command Not Found

If:

composer

returns:

command not found

your hosting provider may not have Composer available through the current shell.

You can:

  • Ask the hosting provider whether Composer is available

  • Use the path provided by the hosting company

  • Install dependencies locally and upload vendor

  • Use a VPS if your project needs more server-level control

PHP Version Error

You may see Composer errors saying your PHP version does not satisfy the application's requirements.

Check:

php -v

The PHP version used by your website and the PHP version used by SSH/CLI may sometimes be different on shared hosting.

Confirm both if Artisan works differently from the website.

Class Not Found Error

Run:

composer install

or regenerate Composer's autoloader:

composer dump-autoload

Then:

php artisan optimize:clear

No Application Encryption Key Error

If Laravel shows an error related to the application encryption key, check:

APP_KEY=

For a new deployment:

php artisan key:generate

Then clear cached configuration.

Database Connection Refused

Check:

DB_HOST=
DB_PORT=
DB_DATABASE=
DB_USERNAME=
DB_PASSWORD=

Do not assume DB_HOST=127.0.0.1 or localhost is correct for every hosting provider.

Use the database hostname supplied with your account.

Access Denied for MySQL User

This usually means:

  • Database username is wrong

  • Password is wrong

  • User was not assigned to the database

  • User does not have required privileges

Check your hosting database management panel.

Laravel Routes Return 404

If:

/

works but:

/login
/dashboard
/admin

returns 404, check:

  • public/.htaccess

  • Apache mod_rewrite

  • Domain document root

  • Rewrite permissions

Do not create physical folders for Laravel routes.

CSS and JavaScript Return 404

Check:

public/build/

if you use Vite.

Run locally:

npm run build

and upload the generated build files.

Also make sure your APP_URL is correct.

Uploaded Images Do Not Display

Check the storage link:

ls -l public/storage

Then create it if necessary:

php artisan storage:link

Make sure files actually exist under:

storage/app/public

Laravel's documented public-disk setup uses this storage directory together with the public/storage symbolic link.

Permission Denied Error

Check:

storage/
bootstrap/cache/

The web server needs write access to these directories.

You may use:

chmod -R 775 storage
chmod -R 775 bootstrap/cache

depending on your hosting environment.

If the problem continues, file ownership may be incorrect.

Laravel Works With /public but Not Without It

Your domain document root is most likely wrong.

Preferred:

/home/username/laravel-app/public

instead of:

/home/username/laravel-app

If you cannot change the document root, use a carefully configured .htaccess rewrite.

Laravel Shows Old .env Values

Laravel may still be using cached configuration.

Run:

php artisan optimize:clear

Then test again.

After everything works, you can run:

php artisan optimize

APP_URL Changed but Laravel Still Uses the Old Domain

Update:

APP_URL=https://newdomain.com

Then:

php artisan optimize:clear
php artisan optimize

Also check whether any URLs have been hardcoded in:

  • JavaScript

  • Blade files

  • Database records

  • Configuration files

A Good Laravel Production .env Example

A basic production setup could look like:

APP_NAME="My App"
APP_ENV=production
APP_KEY=base64:YOUR_APPLICATION_KEY
APP_DEBUG=false
APP_URL=https://example.com

LOG_CHANNEL=stack

DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=example_database
DB_USERNAME=example_user
DB_PASSWORD=strong_password

SESSION_DRIVER=database
CACHE_STORE=database
QUEUE_CONNECTION=database

This is only an example.

Use the configuration required by your application and Laravel version.

Laravel Deployment Command Checklist

A typical deployment may involve commands such as:

composer install --no-dev --optimize-autoloader

php artisan optimize:clear

php artisan migrate --force

php artisan storage:link

php artisan optimize

Not every command should be run blindly on every application.

For example, do not run production migrations unless you know what changes they will perform.

Laravel Deployment Security Checklist

Before launching the website, confirm:

  • APP_ENV=production

  • APP_DEBUG=false

  • .env is not publicly accessible

  • Domain points to public

  • Database uses a strong password

  • Correct PHP version is selected

  • File permissions are appropriate

  • SSL is enabled

  • Unused development files are not exposed

  • Backups are available

  • Sensitive credentials are not stored in public files

Laravel Deployment Performance Checklist

After the application works correctly:

composer install --no-dev --optimize-autoloader
php artisan optimize

Laravel recommends caching production configuration, routes, events, and views where appropriate to reduce framework bootstrap work.

Also consider:

  • PHP OPcache

  • Database indexing

  • Image optimisation

  • Browser caching

  • Queue processing

  • Redis where appropriate

  • CDN usage for larger projects

The correct performance setup depends on the application.

Shared Hosting vs VPS for Laravel

Shared hosting can be suitable for:

  • Small Laravel websites

  • Admin panels

  • Business applications

  • Low to moderate traffic projects

  • Basic CRUD applications

A VPS may be more suitable if you need:

  • Root access

  • Custom PHP extensions

  • Redis

  • Supervisor

  • Long-running queue workers

  • WebSockets

  • Custom Nginx configuration

  • Node.js services

  • Higher CPU or memory resources

  • Multiple backend services

Do not move to a VPS simply because the application is built with Laravel. Choose based on actual resource and server requirements.

Frequently Asked Questions

Can Laravel Run on Shared Hosting?

Yes, provided the hosting environment meets the requirements of the Laravel version used by your application and gives you the necessary PHP, database, storage, and file configuration.

Do I Need SSH Access?

Not always.

You can upload Laravel using File Manager or FTP, but SSH makes tasks such as Composer installation, Artisan commands, migrations, and troubleshooting much easier.

Should I Upload the Vendor Folder?

If you can run Composer on the server, it is normally better to install dependencies there.

If Composer is unavailable, you can generate vendor locally and upload it.

Should Laravel Be Installed Inside public_html?

Laravel can be made to work there, but the web server should expose only Laravel's public directory.

The preferred configuration is to keep the project directory separate and point the domain document root to:

project/public

Why Should the Domain Point to Laravel Public?

Laravel's public/index.php is the application's web entry point.

Serving the project root can expose files that should never be publicly accessible. Laravel's official documentation specifically recommends directing requests to public/index.php.

Do I Need php artisan storage?

You need it when your application uses Laravel's public local storage disk and needs files under storage/app/public to be available through the web.

Why Does Laravel Show a 500 Error After Uploading?

Check:

  • PHP version

  • PHP extensions

  • .env

  • APP_KEY

  • Database credentials

  • Composer dependencies

  • Directory permissions

  • Laravel logs

The error is usually easier to identify from storage/logs/laravel.log than from the browser.

Can I Deploy Laravel Without cPanel?

Yes.

Laravel can run on different hosting control panels and server environments, including DirectAdmin, aaPanel, CloudPanel, Plesk, or a manually configured VPS.

The names of the hosting controls may differ, but the Laravel deployment principles remain similar.

Host Your Laravel Application with Ceylon Web Servers

Ceylon Web Servers provides hosting options for PHP and Laravel projects, from smaller websites to applications that require their own virtual server.

Available options include:

  • Shared Hosting

  • Reseller Hosting

  • VPS Hosting

For applications that require root access, background services, custom server configurations, or additional resources, VPS hosting may be the better option.

Website: ceylonwebservers.com

Call / WhatsApp: 070 244 7722