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 "your_email@example.com" 
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)