DEV Community

Cover image for Deploying Laravel Applications to Shared Hosting via Git and cPanel
Akshay Joshi
Akshay Joshi

Posted on

Deploying Laravel Applications to Shared Hosting via Git and cPanel

For teams deploying Laravel apps to shared hosting using Git push, post-receive hooks, and manual cPanel setups, this SOP enables:

  • Clean deployment via Git
  • MySQL database configuration
  • Environment setup via .env
  • Seamless handling of subdomains vs. root domains
  • Production-ready deployment without root access

šŸ“¦ Assumptions

  • Shared hosting (e.g., A2, Hostinger, Bluehost) with cPanel + SSH
  • Git, Composer, and PHP (>= 7.4) are available
  • Laravel version 8+
  • DNS already configured to hosting server

šŸ” SSH Key Setup (One-Time)

  1. Generate SSH key on your local machine:
ssh-keygen -t rsa -b 4096 -C "[email protected]"
Enter fullscreen mode Exit fullscreen mode
  1. Copy the public key:
cat ~/.ssh/id_rsa.pub
Enter fullscreen mode Exit fullscreen mode
  1. SSH into the server and append it to ~/.ssh/authorized_keys:
nano ~/.ssh/authorized_keys
# Paste the key and save
Enter fullscreen mode Exit fullscreen mode

šŸ”§ Laravel Deployment Structure

ā— Subdomain vs. Primary Domain: Key Differences

Context Laravel Folder Placement Document Root Target Notes
Subdomain Full Laravel app (including /public) /subdomain.domain.com/public Clean separation; recommended for staging/UAT
Primary Domain Laravel core outside /public_html /public_html/ Must expose only public/, rest stays outside

🌐 Subdomain Deployment (Recommended)

šŸ”¹ Step-by-Step

  1. Create Subdomain in cPanel

    • Navigate to Domains > Subdomains
    • Example: uat.domain.com
    • Set Document Root: /home/<username>/subdomains/uat.domain.com/public
  2. Create Bare Git Repo on Server

mkdir -p /home/<username>/repos/laravel-uat.git
cd /home/<username>/repos/laravel-uat.git
git init --bare
Enter fullscreen mode Exit fullscreen mode
  1. Configure post-receive Hook
nano hooks/post-receive
Enter fullscreen mode Exit fullscreen mode
#!/bin/sh
GIT_WORK_TREE=/home/<username>/subdomains/uat.domain.com git checkout -f
cd /home/<username>/subdomains/uat.domain.com
composer install --no-dev
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
Enter fullscreen mode Exit fullscreen mode
chmod +x hooks/post-receive
Enter fullscreen mode Exit fullscreen mode
  1. Deploy from Local or GitHub
git remote add live ssh://<username>@<host_ip>/home/<username>/repos/laravel-uat.git
git push live uat
git push live master
Enter fullscreen mode Exit fullscreen mode

šŸ  Primary Domain Deployment (domain.com)

ā— Caveat

Shared hosting ties domain.com to /public_html. You cannot place the full Laravel folder in /public_html. Use the approach below:

šŸ”¹ Directory Structure

/home/<username>/laravel_main
/home/<username>/public_html    ← contains only files from `/public`
Enter fullscreen mode Exit fullscreen mode

šŸ”¹ Steps

  1. Push Full Laravel App to ~/laravel_main

  2. Copy /public Contents to /public_html

cp -R laravel_main/public/* public_html/
Enter fullscreen mode Exit fullscreen mode
  1. Edit public_html/index.php

Update paths:

require __DIR__.'/../laravel_main/vendor/autoload.php';
$app = require_once __DIR__.'/../laravel_main/bootstrap/app.php';
Enter fullscreen mode Exit fullscreen mode
  1. Install Dependencies & Migrate
cd ~/laravel_main
composer install --no-dev
php artisan migrate --force
php artisan key:generate
php artisan config:cache
Enter fullscreen mode Exit fullscreen mode
  1. Set Permissions
chmod -R 775 storage
chmod -R 775 bootstrap/cache
Enter fullscreen mode Exit fullscreen mode

šŸ› ļø MySQL Database Setup

  1. Go to cPanel > MySQL Databases
  2. Create database: db_laravel
  3. Create user: user_laravel
  4. Assign user to database with All Privileges
  5. Update .env:
DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=db_laravel
DB_USERNAME=user_laravel
DB_PASSWORD=StrongPassword123
Enter fullscreen mode Exit fullscreen mode

āš ļø Common Issues & Fixes

Problem Cause Fix
500 Internal Server Error Wrong index paths / file permissions Fix index.php, run chmod -R 775 storage bootstrap/cache
Composer not installed Shared host restriction Install locally and upload vendor/
.env missing Laravel config errors Upload .env, run php artisan config:cache
Directory listing visible Wrong document root Set root to public/, not project root
Artisan fails PHP CLI outdated Check php -v, request upgrade or use compatible Laravel version

šŸ“Œ Summary Table

Context Code Location Public Files Location Method
Subdomain ~/subdomains/app/ ~/subdomains/app/public Full Laravel folder used
Primary Domain ~/laravel_main ~/public_html public folder only exposed

āœ… Post-Deployment Checklist

  • [ ] .env configured correctly
  • [ ] php artisan key:generate run
  • [ ] storage and bootstrap/cache are writable
  • [ ] Composer dependencies installed
  • [ ] Artisan commands run: config:cache, route:cache, view:cache
  • [ ] Database connection tested
  • [ ] Subdomain or root domain resolving properly
  • [ ] Debug mode off in production (APP_DEBUG=false)

P.S. - This post was refined with the help of ChatGPT and includes an image sourced from the web. If anyone has concerns or would like the content removed, I’m open to doing so.

Top comments (0)