Plenty of small and mid-size client projects in India still run on cPanel shared hosting. No Docker, no Kubernetes, often no SSH. That doesn't mean deployment has to be "drag files into FileZilla and hope." Here is the lightweight workflow our team uses to keep client sites version-controlled and safely deployable.
1. Keep two environments, always
Every project has a local/staging copy and the live server. Nothing is edited directly on production. Even on shared hosting you can usually create a subdomain like staging.example.com for client review.
2. Git is the source of truth
Put the whole site in a Git repo, but keep secrets out of it:
.env
config/database.php
/uploads/
/cache/
Commit a config/database.example.php instead, so the next developer knows what's needed.
3. Automate the FTP upload from GitHub Actions
If the host has no SSH, FTP deploy from CI still beats manual uploads. A minimal workflow:
name: Deploy to cPanel
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
server: ${{ secrets.FTP_SERVER }}
username: ${{ secrets.FTP_USERNAME }}
password: ${{ secrets.FTP_PASSWORD }}
server-dir: public_html/
exclude: |
**/.git*
**/node_modules/**
config/database.php
The action keeps a state file on the server and only uploads changed files, so deploys take seconds instead of minutes.
4. Keep separate apps truly separate
A common trap: a main site in public_html and a second app (say, a store) in public_html/store. Give each its own repo, own database and own deploy job, and exclude the sub-app folder from the parent deploy. Otherwise one push can overwrite the other.
5. Don't forget SEO after deploy
After each release, check:
-
robots.txtdidn't accidentally switch toDisallow: /from staging - canonical tags point to the
https://www.version - the XML sitemap is regenerated and resubmitted in Google Search Console
Wrapping up
Shared hosting isn't glamorous, but with Git, a CI-driven FTP deploy and a few guardrails it's perfectly reliable for most business sites. We use this setup across client projects at Light Animation, a Jaipur-based team doing custom software and web development since 2010. Happy to answer questions in the comments.
Top comments (2)
The separate-repo rule for the sub-app is the part I would keep. One push overwriting a store folder is an easy mistake on shared hosting. I would also add a quick post-deploy check that the main site and the sub-app both still load, so a bad deploy is caught before the client finds it.
Checking robots.txt after deploy is the quiet one. A staging Disallow slipping to live hurts more than a slow deploy.