Manually clicking “Update from Remote” and “Deploy HEAD Commit” in cPanel every time you push gets old fast. In this tutorial we’ll wire up GitHub Actions to do it automatically โ push to main, and your live theme updates within seconds.
How it works
Three pieces work together:
- cPanel Git Version Control โ clones your GitHub repo directly into the theme directory on the server
- GitHub deploy key โ lets the server authenticate with GitHub when pulling
- GitHub Actions + SSH โ on every push, Actions SSHs into your server and runs
git pullautomatically
git push origin main
โ
GitHub Actions triggers
โ
SSHs into your server
โ
git pull in theme directory
โ
Live site updated โ
Prerequisites
- A GitHub repository for your theme
- cPanel hosting with Git Version Control enabled
- SSH access to your server
- Git installed locally
Step 1 โ Set up cPanel Git Version Control
In cPanel โ Git Version Control โ Create:
- Enable Clone a Repository
- Clone URL: your GitHub SSH URL (e.g.
[email protected]:username/repo.git) - Repository Path: the full server path to your theme directory (e.g.
/home/username/public_html/site.com/wp-content/themes/your-theme)
Click Create. cPanel will clone the repo into that directory.
Step 2 โ Generate an SSH key pair
Run this on your local machine:
ssh-keygen -t ed25519 -C "github-actions-deploy" -f ~/.ssh/github_actions_deploy -N ""
This creates two files:
~/.ssh/github_actions_deployโ private key (goes to GitHub Actions)~/.ssh/github_actions_deploy.pubโ public key (goes to cPanel)
Step 3 โ Add the public key to cPanel
cPanel โ SSH Access โ Manage SSH Keys โ Import Key:
- Name:
github-actions-deploy - Private key: leave empty
- Passphrase: leave empty
- Public key: paste the output of
cat ~/.ssh/github_actions_deploy.pub
Click Import, then find the key in the list and click Authorize.
Step 4 โ Add GitHub Actions secrets
GitHub โ your repo โ Settings โ Secrets and variables โ Actions โ New repository secret. Add these three:
| Secret name | Value |
|---|---|
SSH_HOST | your server domain or IP |
SSH_USERNAME | your cPanel username |
SSH_PRIVATE_KEY | full contents of ~/.ssh/github_actions_deploy |
Step 5 โ Add the .cpanel.yml file
Create .cpanel.yml in the root of your theme repository:
---
deployment:
tasks:
- echo "Theme deployed successfully"
Since cPanel’s “Clone a Repository” setup places the git working tree directly in the deployment directory, a simple echo is all that’s needed โ git pull already updates the files in place. The cp -R approach you’ll see in some tutorials causes “same file” errors in this setup.
Step 6 โ Create the GitHub Actions workflow
Create .github/workflows/deploy.yml in your repository:
name: Deploy to cPanel
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy via SSH
uses: appleboy/[email protected]
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
port: 22
script: |
cd /path/to/your/theme
git pull origin main
Replace /path/to/your/theme with your actual server path.
Step 7 โ One-time manual deploy
The .github/workflows/deploy.yml file itself needs to land on the server before auto-deploy can work. Do one final manual deploy:
- Push everything to GitHub
- cPanel โ Git Version Control โ your repo โ Pull or Deploy tab
- Click Update from Remote
- Click Deploy HEAD Commit
This is the last time you’ll ever need to do this manually.
Test it
Make any small change, push to main, then go to GitHub โ Actions tab. You should see the workflow run and complete with a green โ within about 10โ15 seconds.
Understanding the two SSH keys
A common point of confusion โ there are two separate SSH keys doing different jobs:
| Key | Private key lives | Public key lives | Purpose |
|---|---|---|---|
id_rsa (server key) | On your server | GitHub โ Deploy keys | Server โ GitHub (git pull auth) |
github_actions_deploy | GitHub โ Actions Secrets | cPanel โ SSH Access | GitHub Actions โ Server (SSH in) |
They work in sequence: Actions uses its key to SSH into the server, then the server uses its own key to authenticate the git pull with GitHub.