Project template yang aku pakai saat ini memang sudah aku simpan ke GitHub. Nah, biasanya kalau mau nambah fitur baru, yang aku lakukan adalah testing dulu di localhost. Setelah itu kan ada catatan file apa saja yang berubah, nah file itu aku copas satu per satu ke WordPress yang ada di hosting lewat FTP.

Sampai suatu ketika ada file yang ketinggalan. Aku pusing nyari file mana yang kira-kira belum ke-upload.

Setelah aku pikir-pikir, cara ini bakal merepotkan dan rawan terjadi kesalahan. Akhirnya aku putuskan untuk melakukan otomatisasi untuk proses deployment — yang biasa aku terapkan di project-project lain.


Konsep Awal

Konsepnya adalah repo punya 2 branch:

Hosting sudah support Git Version Control di cPanel, remote repository pakai GitHub. Secara teori, alurnya seperti ini:

[Lokal - branch dev]
       ↓ merge
[GitHub - branch main]
       ↓ trigger GitHub Actions
[Hosting via SSH - git pull]

Kelihatannya bersih. Kenyataannya tidak semulus itu.


Git-kan Apa Dulu?

Sebelum mulai, ada satu pertanyaan penting yang perlu dijawab dulu: apakah yang di-git itu seluruh instalasi WordPress lokal, atau tema saja?

Jawabannya tema saja. Alasannya:

Jadi struktur repo-nya hanya isi folder tema:

wp-content/
└── themes/
    └── portofolio/     ← git init di sini
        ├── .gitignore
        ├── style.css
        ├── functions.php
        ├── index.php
        └── ...

Setup Awal: Repo dan .gitignore

Karena tema ini plain PHP/CSS/JS tanpa build tool apapun, .gitignore-nya relatif sederhana. Yang perlu diabaikan antara lain file-file OS seperti .DS_Store dan Thumbs.db, file editor seperti .vscode/ dan .idea/, log dan file temporary, serta yang paling penting: wp-config.php, folder uploads/, dan cache WordPress.

Setelah .gitignore siap, init repo di folder tema:

cd /laragon/www/enricoriskip/wp-content/themes/portofolio/

git init
git add .
git commit -m "initial commit"
git remote add origin https://github.com/enricoriskip/wp-template.git

git checkout -b dev
git push -u origin dev

git checkout -b main
git push -u origin main

Error Pertama: cPanel Tidak Bisa Clone via HTTPS

Langkah awal clone repository GitHub ke cPanel menggunakan fitur Git Version Control
Langkah awal clone repository GitHub ke cPanel menggunakan fitur Git Version Control

Masalah pertama muncul saat mencoba menambahkan repository di cPanel → Git Version Control menggunakan URL HTTPS biasa.

Error: (XID 5fk2rk) "/usr/local/cpanel/3rdparty/bin/git" reported error code "128"
when it ended: fatal: could not read Username for 'https://github.com':
No such device or address

Ternyata cPanel berjalan di background dan tidak punya layar interaktif untuk menampilkan prompt username/password. Saat GitHub meminta autentikasi, prosesnya langsung gagal karena tidak ada yang bisa menjawab.

Solusinya: pakai SSH, bukan HTTPS.


Error Kedua: SSH Permission Denied (dan Perjalanan Panjangnya)

Ini bagian yang paling makan waktu. Setelah beralih ke SSH, aku buka Terminal cPanel dan langsung test koneksi ke GitHub:

ssh -T git@github.com
# git@github.com: Permission denied (publickey).

ssh -T git@github.com itu ngapain? Perintah ini untuk test apakah koneksi SSH ke GitHub berhasil atau tidak. -T artinya kita tidak minta terminal interaktif, cukup cek autentikasi saja. Kalau berhasil, GitHub akan balas dengan pesan sambutan. Kalau gagal, muncul “Permission denied”.

Oke, berarti ada masalah dengan key. Aku cek dulu isi folder .ssh:

ls -la ~/.ssh/

ls -la ~/.ssh/ itu ngapain? ls adalah perintah untuk lihat isi folder. -l artinya tampilkan detail (ukuran, permission, tanggal), -a artinya tampilkan semua file termasuk yang tersembunyi (file yang namanya diawali titik). Folder .ssh ini menyimpan semua SSH key milik kita.

Hasilnya:

-rw-------  enricori  github_deploy_wp_portfolio_theme      ← private key
-rw-r--r--  enricori  github_deploy_wp_portfolio_theme.pub  ← public key

Key sudah ada. Tapi masalahnya: SSH tidak tahu harus pakai key yang mana saat konek ke GitHub, karena namanya bukan nama default (id_rsa). Jadi aku buat file config supaya SSH tahu.

nano ~/.ssh/config

nano ~/.ssh/config itu ngapain? nano adalah text editor di terminal. Perintah ini membuka (atau membuat kalau belum ada) file bernama config di dalam folder .ssh. File inilah yang jadi “panduan” bagi SSH — di sini kita bisa atur: kalau mau konek ke server A, pakai key ini; kalau ke server B, pakai key itu.

Setelah disimpan, test lagi:

ssh -T git@github.com
# Bad owner or permissions on /home/enricori/.ssh/config

Nah, ini error baru lagi. File config tadi ternyata permission-nya salah. Aku cek:

ls -la ~/.ssh/
# -rw-rw-r--  config   ← permission ini yang bermasalah

Kenapa permission file config harus diatur ketat? SSH itu sangat ketat soal keamanan. File yang menyimpan konfigurasi atau private key tidak boleh bisa dibaca oleh orang lain selain pemiliknya. Kalau permission-nya terlalu “terbuka” (seperti rw-rw-r-- yang artinya orang lain juga bisa baca), SSH langsung menolak untuk jalan — ini fitur keamanan, bukan bug.

Fix-nya:

chmod 600 ~/.ssh/config

chmod 600 itu ngapain? chmod adalah perintah untuk mengubah permission file. Angka 600 artinya: pemilik file boleh baca dan tulis (6), tapi orang lain sama sekali tidak boleh akses (00). Ini standar yang diminta SSH untuk file-file sensitif.

Test lagi:

ssh -T git@github.com
# Enter passphrase for key '/home/enricori/.ssh/github_deploy_wp_portfolio_theme':

Error baru lagi. SSH sudah bisa menemukan key-nya, tapi key ini punya passphrase — semacam password ekstra untuk membuka private key. Untuk auto-deploy, ini jadi masalah karena tidak ada yang bisa mengetik passphrase saat proses berjalan otomatis di background.


Error Ketiga: Passphrase yang Tidak Bisa Dihapus dari UI cPanel

Waktu generate key via form cPanel, kolom passphrase terisi. Aku coba hapus passphrase dari key yang ada:

ssh-keygen -p -f ~/.ssh/github_deploy_wp_portfolio_theme

Tapi setelah key dihapus dan coba dibuat ulang lewat form cPanel, passphrase-nya muncul lagi. Ternyata form Generate Key di cPanel memang tidak bisa dikosongkan kolom passphrase-nya.

Password harus tetap di isi kalau lewat form
Password harus tetap di isi kalau lewat form

Solusi finalnya: bypass form UI cPanel, buat key langsung dari terminal:

ssh-keygen -t ed25519 -C "cpanel-deploy" -f ~/.ssh/github_deploy -N ""

Perintah ini apa artinya satu per satu?

Hasilnya dua file baru: github_deploy (private key) dan github_deploy.pub (public key).

Setelah itu jalankan perintah ini di terminal untuk mendapatkan key

cat ~/.ssh/github_deploy.pub

Copy outputnya, lalu daftarkan ke GitHub repo → Settings → Deploy keys → Add deploy key.

Penambahan Deploy Key Github
Penambahan Deploy Key Github

Kenapa Perlu File ~/.ssh/config?

Ini pertanyaan penting yang perlu dijelaskan tersendiri.

SSH secara default akan mencari private key dengan nama id_rsa, id_ed25519, atau beberapa nama baku lainnya. Kalau kamu pakai nama itu, SSH langsung tahu mau pakai key yang mana — tidak perlu konfigurasi tambahan.

Tapi karena aku pakai nama custom (github_deploy), SSH tidak tahu kalau key itu harus dipakai untuk konek ke github.com. Makanya perlu file config yang isinya seperti “panduan”:

Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/github_deploy

Artinya: “kalau ada yang mau konek ke github.com, pakai private key yang ada di ~/.ssh/github_deploy.”

Kalau kamu pakai nama default (id_ed25519 misalnya), langkah membuat file config ini tidak diperlukan.

Setelah config dibuat dengan benar dan permission-nya diperbaiki (chmod 600), test SSH akhirnya berhasil:

ssh -T git@github.com
# Hi EnricoRP/portfolio-wp-theme! You've successfully authenticated...

cPanel Git Version Control pun bisa di-create dengan URL SSH tanpa error.


Setup GitHub Actions untuk Auto-Deploy

Setelah koneksi cPanel → GitHub berjalan, langkah selanjutnya adalah membuat GitHub Actions agar setiap push ke branch main otomatis men-trigger git pull di hosting.

GitHub Actions perlu bisa SSH masuk ke server hosting, jadi dibutuhkan key tersendiri — berbeda dengan key untuk cPanel ke GitHub tadi. Buat di Terminal cPanel:

ssh-keygen -t ed25519 -C "github-actions-deploy" -f ~/.ssh/github_actions -N ""

Public key-nya ditambahkan ke authorized_keys di server:

cat ~/.ssh/github_actions.pub >> ~/.ssh/authorized_keys

cat ... >> authorized_keys itu ngapain? cat membaca isi file, lalu >> menambahkan isinya ke file lain (tanpa menghapus isi yang sudah ada). authorized_keys adalah daftar public key yang diizinkan masuk ke server via SSH. Jadi perintah ini intinya: “daftarkan public key ini supaya boleh masuk ke server.”

Private key-nya disimpan sebagai secret di GitHub repo (Settings → Secrets and variables → Actions):

Secret NameIsi
CPANEL_HOSTIP server hosting
CPANEL_USERNAMEenricori
CPANEL_SSH_PRIVATE_KEYIsi private key ~/.ssh/github_actions

Untuk menemukan IP hosting, cukup jalankan di terminal:

curl ifconfig.me

curl ifconfig.me itu ngapain? curl adalah perintah untuk mengambil konten dari URL. ifconfig.me adalah website yang membalas dengan IP publik si penanya. Jadi perintah ini secara sederhana: “tunjukkan IP server ini.”

File workflow dibuat di .github/workflows/deploy.yml:

name: Deploy to Hosting

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Deploy via SSH to cPanel
        uses: appleboy/ssh-action@v1.0.0
        with:
          host: ${{ secrets.CPANEL_HOST }}
          username: ${{ secrets.CPANEL_USERNAME }}
          key: ${{ secrets.CPANEL_SSH_PRIVATE_KEY }}
          script: |
            cd /home/enricori/public_html/wp-content/themes/portofolio
            git pull origin main

Error Terakhir: Branch main Tidak Ada di Lokal

Saat hendak push ke main untuk test workflow:

PS> git checkout main
error: pathspec 'main' did not match any file(s) known to git

Branch main memang belum pernah di-checkout di lokal setelah semua perubahan tadi. Solusinya:

git checkout -b main
git merge dev
git push origin main

Push ke main berhasil, dan GitHub Actions langsung berjalan otomatis.


Alur Kerja Sehari-hari

Setelah semua setup selesai, workflow hariannya jadi seperti ini:

# Kerja di branch dev
git checkout dev
# ... edit tema ...
git add .
git commit -m "update header layout"
git push origin dev

# Kalau sudah siap naik ke production
git checkout main
git merge dev
git push origin main
# → GitHub Actions otomatis jalan → hosting ter-update

Kalau Kamu Kena Permission Denied, Cek Ini

Berikut langkah diagnosa yang bisa diikuti kalau muncul masalah serupa.

1. Cek apakah private key sudah ada

ls -la ~/.ssh/

Harusnya ada sepasang file, contoh:

github_deploy        ← private key (tanpa ekstensi)
github_deploy.pub    ← public key

2. Kalau nama key-nya custom (bukan id_rsa atau id_ed25519), wajib buat file config

nano ~/.ssh/config

Isi dengan:

Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/nama_private_key_kamu

Kenapa perlu ini? Karena SSH secara default hanya mencari file key dengan nama baku. Kalau namanya lain, SSH tidak tahu harus pakai key yang mana — dan hasilnya Permission Denied meski key-nya sudah terdaftar di GitHub.

3. Pastikan permission file config sudah benar

chmod 600 ~/.ssh/config

Kalau dilewati, SSH akan menolak jalan dengan error “Bad owner or permissions”.

4. Test koneksi

ssh -T git@github.com

Kalau berhasil, muncul pesan sambutan dari GitHub. Kalau masih gagal, kemungkinan besar public key belum didaftarkan ke GitHub Deploy keys.


Ringkasan Masalah dan Solusi

MasalahPenyebabSolusi
Error 128 saat clone HTTPScPanel tidak bisa autentikasi interaktifGanti ke SSH
Permission denied publickeyPublic key belum didaftarkan ke GitHubAdd deploy key di GitHub repo
Bad owner or permissionsPermission file ~/.ssh/config salahchmod 600 ~/.ssh/config
Diminta passphrase saat SSHKey dibuat dengan passphraseBuat ulang key via terminal dengan flag -N ""
Form cPanel paksa passphraseLimitasi UI cPanelBypass form, gunakan terminal langsung
Branch main tidak ditemukanBelum pernah checkout main di lokalgit checkout -b main lalu merge dari dev

Seluruh proses ini makan waktu lebih lama dari yang seharusnya — tapi sebagian besar karena hal-hal kecil seperti permission file, nama key yang tidak default, dan passphrase tersembunyi di balik form UI cPanel. Pelajarannya: kalau cPanel-nya susah diajak kerja sama, langsung saja pakai terminal.