How to Host a Laravel Project on a Shared Hosting Server
1. Navigating to Server & Cloning Repository
Deploying a Laravel application on shared hosting (such as cPanel, Hostinger hPanel, or Namecheap) starts with placing your project files in the appropriate web root directory. Instead of manually uploading ZIP files via FTP, using Git makes deployment and future updates fast and reliable.
Open your hosting terminal (via SSH or the cPanel / Hostinger Terminal utility) and navigate to your target root folder (typically public_html or your domain directory):
# Navigate to your domain web root directory cd ~/public_html # Clone your Laravel repository into the current directory git clone https://github.com/your-username/your-laravel-repo.git . # Install Composer production dependencies (if composer is available) composer install --no-dev --optimize-autoloader
! TIP
Notice the dot (.) at the end of the git clone command — this clones the repository contents directly into the current directory instead of nesting it into a new subfolder.
2. Environment Setup (.env) & App Key
Laravel requires a dedicated .env file containing your production settings, encryption key, and database configuration.
- Copy the example environment template
.env.exampleto.env. - Generate a unique 32-character application encryption key (
APP_KEY). - Set your production URL and environment flags.
# Copy .env.example to active .env cp .env.example .env # Generate secure application encryption key php artisan key:generate
Update your top-level environment configuration in .env:
APP_NAME="Your App" APP_ENV=production APP_KEY=base64:... APP_DEBUG=false APP_URL=https://yourdomain.com
3. Database Creation & Configuration (cPanel / Hostinger)
Now set up your MySQL database on your hosting control panel:
- cPanel: Go to MySQL Database Wizard → Create Database → Create User with strong password → Check ALL PRIVILEGES.
- Hostinger: Go to Databases → Management→ Create MySQL Database, User & Password.
- Open
.envin your root directory and fill in your database credentials:
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=cpaneluser_dbname DB_USERNAME=cpaneluser_dbuser DB_PASSWORD=your_strong_password_here
Run your database schema migrations via terminal:
php artisan migrate --force
! WEB ROUTE FALLBACK (NO SSH)
If your hosting package does not allow terminal access or artisan commands, you can temporarily trigger migrations by adding this route in routes/web.php and visiting yourdomain.com/run-migrations in your browser:
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Route;
Route::get('/run-migrations', function () {
try {
Artisan::call('migrate --force');
return 'Database migrated successfully: ' . Artisan::output();
} catch (\Exception $e) {
return 'Migration error: ' . $e->getMessage();
}
});(Remember to remove or comment out this route once the migration completes.)
4. Configuring Root .htaccess for Public Redirection
In a standard Laravel installation, all web traffic should enter via the public/ folder where index.php resides. On shared hosting, rather than manually hacking paths or splitting the Laravel core across different folders, the cleanest and most maintainable method is placing an Apache .htaccess file directly in your project root directory (e.g. public_html/.htaccess).
Create or edit the .htaccess file in the root directory of your Laravel application with the following rules:
<IfModule mod_rewrite.c>
RewriteEngine On
# Redirect /public/something or /public to /something or / permanently
RewriteCond %{THE_REQUEST} \s/public/?([^\s?]*) [NC]
RewriteRule ^public/?(.*)$ /%1 [L,R=301]
# Redirect all requests to the public directory internally
RewriteCond %{REQUEST_URI} !^/public/
RewriteRule ^(.*)$ public/$1 [L]
</IfModule>How this .htaccess works:
- Automatic Clean URLs: If a visitor manually navigates to
example.com/public/login, Apache issues a301 Permanent Redirecttoexample.com/login. - Internal Routing: All incoming requests to the domain are transparently routed into the
public/folder internally without modifying the URL in the browser bar. - Zero File Splitting: Your entire Git repository remains untouched and fully intact, making future
git pulldeployments effortless!
5. Storage Symlink, Permissions & Going Live
To wrap up and make your Laravel project ready for production:
- Create Storage Symlink: Allows uploaded files in
storage/app/publicto be served publicly. - Set Folder Permissions: Ensure web server write access to
storageandbootstrap/cache. - Cache Configuration & Routes: Boost performance on shared hosting by compiling routes, configs, and blade templates.
# Create storage symlink php artisan storage:link # Set correct write permissions chmod -R 775 storage bootstrap/cache # Optimize application cache for production php artisan config:cache php artisan route:cache php artisan view:cache
! STORAGE LINK VIA WEB ROUTE
If SSH is unavailable, link your storage via routes/web.php:
Route::get('/link-storage', function () {
try {
Artisan::call('storage:link');
return 'Storage symbolic link created successfully!';
} catch (\Exception $e) {
return 'Symlink error: ' . $e->getMessage();
}
});Deployment Complete!
Your Laravel application is now live, secure, and running with clean URLs on your shared hosting server.