UnderHost
Knowledgebase Docs

Deploy your website from Git automatically

Set up push-to-deploy for your site: cPanel Git Version Control with .cpanel.yml, a bare repository with a post-receive hook on a VPS, and CI deploys over SSH or FTP with GitHub Actions.

On this page

Deploying from Git means your live site is updated from a repository instead of by copying files by hand. You push a commit, and the server or a CI job puts that exact version live. Each deploy is repeatable, and an older commit is one step away if something breaks. If you are new to Git, start with Git basics.

Choose a deployment method

MethodWorks onBest for
cPanel Git Version Control with .cpanel.ymlcPanel accounts with SSH, such as Managed Business hostingSimple sites managed from cPanel
Bare repository and post-receive hookCloud VPS, dedicated serversPush straight to the server with git push
CI deploy over SSH (GitHub Actions, GitLab CI)Cloud VPS, dedicated servers, Managed Business hostingTeams, tests and build steps before deploy
CI deploy over FTP with TLSShared hostingShared plans, which do not include SSH

Before you automate

  • Keep secrets out of Git. Database passwords and API keys belong in a .env or config file that lives only on the server. Add it to .gitignore.
  • Do not commit uploads or caches. Folders such as wp-content/uploads or storage/ should be ignored and left untouched by deploys.
  • Deploy one branch. Use main (or production) for the live site, and work in other branches.
  • Back up first. Take a backup before the first automated deploy. See backup best practices.

cPanel Git Version Control

cPanel includes Files → Git Version Control, which can create or clone a repository in your account and deploy it with a .cpanel.yml file. Cloning a private repository needs an SSH key on the account, so this method suits cPanel accounts with SSH access, such as Managed Business hosting.

  1. Clone the repository

    In Git Version Control, click Create, turn on Clone a Repository, paste the clone URL, and choose a folder outside public_html, for example /home/user/repositories/site.

  2. Add .cpanel.yml to the repository

    This file tells cPanel which files to copy into the live folder. Commit it to the root of the repository.

  3. Pull and deploy

    Open the repository's Manage → Pull or Deploy tab. Click Update from Remote, then Deploy HEAD Commit.

.cpanel.yml
---
deployment:
  tasks:
    - export DEPLOYPATH=/home/user/public_html/
    - /bin/cp -R public/* $DEPLOYPATH
    - /bin/cp public/.htaccess $DEPLOYPATH

Replace user with your cPanel username and public with the folder in your repository that holds the website. cPanel will not deploy if the working tree has uncommitted changes.

VPS: push to deploy with a hook

On a Cloud VPS or dedicated server you can push straight to the server. A bare repository receives the push, and a hook checks the files out into the web folder.

on the server
# as the user that owns the website files
git init --bare ~/repos/site.git
mkdir -p /var/www/example.com

cat > ~/repos/site.git/hooks/post-receive <<'EOF'
#!/bin/sh
TARGET=/var/www/example.com
while read oldrev newrev ref; do
  if [ "$ref" = "refs/heads/main" ]; then
    git --work-tree="$TARGET" --git-dir="$HOME/repos/site.git" checkout -f main
    echo "Deployed $(git --git-dir="$HOME/repos/site.git" rev-parse --short main) to $TARGET"
  fi
done
EOF
chmod +x ~/repos/site.git/hooks/post-receive
on your computer
git remote add live deploy@your-server-ip:repos/site.git
git push live main

Add build steps to the hook if your site needs them, for example composer install --no-dev (see Composer) or npm ci && npm run build. Use an SSH key for the push. See SSH key authentication.

GitHub Actions over SSH

With CI, every push to main can run your tests and then copy the result to the server with rsync. Create a separate key pair for the deploy, put the public key in the server user's authorized_keys, and store the private key as a repository secret.

.github/workflows/deploy.yml
name: Deploy
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Deploy with rsync over SSH
        env:
          SSH_KEY: ${{ secrets.DEPLOY_KEY }}
          HOST: ${{ secrets.DEPLOY_HOST }}
        run: |
          install -m 600 /dev/null ~/.ssh_deploy_key
          echo "$SSH_KEY" > ~/.ssh_deploy_key
          rsync -az --delete --exclude '.git' --exclude '.env' \
            -e "ssh -i ~/.ssh_deploy_key -o StrictHostKeyChecking=accept-new" \
            ./ deploy@"$HOST":/var/www/example.com/
--delete removes files that are not in the repository

Exclude every folder the site writes to, such as uploads, caches and .env, or rsync deletes them on the server. Test the command once with --dry-run.

Shared hosting: deploy over FTP

Shared hosting plans do not include SSH, but a CI job can still upload changed files over FTP with TLS. Create a dedicated FTP account in cPanel → FTP Accounts, limited to your site's folder, and store its login as repository secrets. With lftp:

CI step
sudo apt-get install -y lftp
lftp -u "$FTP_USER","$FTP_PASS" -e "set ftp:ssl-force true; set ssl:verify-certificate yes; \
  mirror -R --only-newer --exclude-glob .git* --exclude .env ./public/ /public_html/; quit" "$FTP_HOST"

See FTP vs SFTP for why FTP with TLS is the right choice on shared plans.

Roll back a bad deploy

  • Hook or CI: revert the commit with git revert <commit> and push again. The fix goes out the same way as any deploy.
  • cPanel: revert in your repository, push, then Update from Remote and Deploy HEAD Commit again.
  • Database changes are not rolled back by Git. Back up the database before deploys that change it.

FAQ

Shared plans do not include SSH, so you cannot push to the server. Deploy from a CI job over FTP with TLS instead, or move to Managed Business hosting or a Cloud VPS, which include SSH.
No. Keep the repository outside the web root and deploy only the site files into it. A .git folder inside public_html can expose your code history.
In a config or .env file that exists only on the server and is listed in .gitignore. CI secrets go in the repository's encrypted secrets, never in the code.

Related: Git basics | Git workflow | SSH key authentication | Composer for PHP

Was this article helpful?

Need a developer-friendly server?

Use an UnderHost Cloud VPS for SSH, Git, Node.js, Python, Laravel, Docker, cron, and custom development workflows.

Related articles

Back to Developer Tools