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
vendordirectoryYour Laravel project files
Your production
.envconfiguration
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.lockStep 2: Create Your Domain or Subdomain
Create the domain you want to use for the application.
For example:
example.comor:
app.example.comIf your hosting panel allows you to choose a document root, point it directly to Laravel's public directory.
For example:
/home/username/laravel-app/publicThis 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.lockDo 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/publicYour users visit:
https://example.comwhile the web server serves:
laravel-app/public/index.phpVisitors should not need to enter:
https://example.com/publicWhat If Shared Hosting Does Not Allow Changing the Document Root?
Some hosting environments force your domain to use:
public_htmlIf your Laravel project is directly inside public_html, you may temporarily use a root .htaccess rewrite.
Create:
public_html/.htaccessand add:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/public/
RewriteRule ^(.*)$ public/$1 [L]
</IfModule>Laravel's normal .htaccess should remain inside:
public/.htaccessChanging 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-appThen run:
composer install --no-dev --optimize-autoloaderFor a production application, --no-dev prevents development-only dependencies from being installed.
Do not normally run:
composer updateduring 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-autoloaderThen 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_passwordDo 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=productionAvoid:
APP_ENV=localon the live website.
Disable APP_DEBUG
Production applications should normally use:
APP_DEBUG=falseLaravel's deployment documentation recommends keeping debug mode disabled in production because debug responses can expose sensitive configuration information.
Do not leave:
APP_DEBUG=trueenabled 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:generateDo 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:
A MySQL database
A database user
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_passwordSome hosting providers use a database hostname other than:
localhostUse 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.sqlOpen 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 --forceThe --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/cachePermissions depend on your server configuration and file ownership.
Do not automatically set everything to:
777because 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:linkLaravel stores public-disk files under:
storage/app/publicand uses a symbolic link at:
public/storageto make those files available through the web.
After creating the link, a file may be accessible through:
https://example.com/storage/image.jpgStorage Link Already Exists Error
You may see:
ERROR The [public/storage] link already exists.Check what currently exists:
ls -l public/storageIf 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/storageThen recreate the link:
php artisan storage:linkBe 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:clearThis clears generated optimization caches.
You may also clear individual caches when troubleshooting:
php artisan config:clear
php artisan route:clear
php artisan view:clearStep 14: Optimize Laravel for Production
Once the application is configured and working, run:
php artisan optimizeCurrent 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:cacheBe 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.comThen update:
APP_URL=https://example.comand run:
php artisan optimize:clear
php artisan optimizeTest 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.cssPreferred:
https://example.com/css/app.cssDo 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 buildThis 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:clearStep 18: Configure Laravel Queue Workers
Some Laravel applications send emails, notifications, reports, or other tasks through queues.
If your application uses:
QUEUE_CONNECTION=databaseor another asynchronous queue driver, queued jobs need a worker.
A typical worker command is:
php artisan queue:workHowever, 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/.envThe 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/publicrather than exposing the entire Laravel project.
Step 21: Check Laravel Logs
If the application returns a 500 error, check:
storage/logs/laravel.logFor example:
tail -f storage/logs/laravel.logThe 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
.htaccessMissing
vendordirectoryInvalid
.envMissing
APP_KEYCache permission problems
Application exceptions
Start by checking:
storage/logs/laravel.logand the hosting server's error log.
Composer Command Not Found
If:
composerreturns:
command not foundyour 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
vendorUse 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 -vThe 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 installor regenerate Composer's autoloader:
composer dump-autoloadThen:
php artisan optimize:clearNo 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:generateThen 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
/adminreturns 404, check:
public/.htaccessApache
mod_rewriteDomain 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 buildand 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/storageThen create it if necessary:
php artisan storage:linkMake sure files actually exist under:
storage/app/publicLaravel'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/cachedepending 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/publicinstead of:
/home/username/laravel-appIf 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:clearThen test again.
After everything works, you can run:
php artisan optimizeAPP_URL Changed but Laravel Still Uses the Old Domain
Update:
APP_URL=https://newdomain.comThen:
php artisan optimize:clear
php artisan optimizeAlso 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=databaseThis 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 optimizeNot 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=productionAPP_DEBUG=false.envis not publicly accessibleDomain points to
publicDatabase 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 optimizeLaravel 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/publicWhy 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
.envAPP_KEYDatabase 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