Cara Deploy Otomatis ke VPS dengan GitHub Actions
Langkah menyiapkan deploy otomatis dari GitHub ke VPS: user khusus, SSH key, secrets, file workflow, rsync, dan cara menjaga deploy tetap aman.
Jawaban singkat
Deploy otomatis ke VPS dengan GitHub Actions cukup butuh user deploy khusus di server, SSH key yang disimpan sebagai secret repo, dan satu file workflow yang menyalin kode lalu memuat ulang aplikasi setiap kali ada push ke branch utama.
Daftar isi
- Bagaimana alurnya bekerja?
- Langkah menyiapkan deploy otomatis
- 1. Buat user khusus deploy di VPS
- 2. Buat SSH key khusus deploy
- 3. Simpan secrets di repository
- 4. Tulis file workflow
- 5. Tambahkan tes sebelum deploy
- 6. Uji dan pantau
- Bagaimana menjaga deploy tetap aman?
- Ringkasan langkah dan hal yang sering terlewat
- Pertanyaan yang sering diajukan
Masih login ke VPS, menjalankan git pull, lalu me-restart aplikasi setiap kali ada perubahan kecil? Cara itu jalan, tapi rawan lupa langkah dan sulit dilacak siapa mengubah apa. GitHub Actions bisa mengambil alih pekerjaan ini: setiap kali kode masuk ke branch utama, GitHub menjalankan skrip yang menyalin kode ke VPS dan memuat ulang aplikasi.
Intinya ada tiga bahan. Satu user khusus deploy di server, satu SSH key yang disimpan sebagai secret di repo, dan satu file workflow YAML. Panduan ini memakai contoh aplikasi web biasa di Ubuntu, tapi polanya sama untuk Laravel, Node.js, atau situs statis.
Bagaimana alurnya bekerja?
GitHub Actions menjalankan pekerjaan di mesin sementara yang disebut runner. Runner milik GitHub (misalnya ubuntu-latest) dibuat baru untuk setiap job lalu dibuang setelah selesai. Dari runner inilah koneksi SSH dibuka ke VPS kamu.
Urutannya kira-kira begini: kamu push ke main, workflow terpicu, runner mengambil kode dengan actions/checkout, menjalankan tes atau build bila ada, lalu memakai rsync lewat SSH untuk mengirim hasilnya ke folder aplikasi di server. Terakhir, runner menjalankan perintah reload di server.
Artinya, VPS harus bisa dihubungi lewat SSH dari internet. Kalau kamu sudah membatasi SSH hanya untuk IP kantor, ingat bahwa alamat IP runner GitHub tidak tetap. Solusinya bisa memakai self-hosted runner, atau membuka SSH dengan key saja (tanpa password) seperti dibahas di SSH key vs password.
Langkah menyiapkan deploy otomatis
1. Buat user khusus deploy di VPS
Jangan memakai root untuk deploy. Buat user terpisah yang hanya punya hak atas folder aplikasi:
sudo adduser --disabled-password --gecos "" deploy
sudo mkdir -p /var/www/app
sudo chown deploy:deploy /var/www/app
Kalau aplikasi perlu di-restart lewat systemd, beri izin sudo hanya untuk satu perintah itu. Buat file dengan sudo visudo -f /etc/sudoers.d/deploy lalu isi:
deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart app.service
Dengan begitu, kalau key deploy bocor, penyerang tidak otomatis mendapat akses root. Cara membuat user dan sudo lebih lengkap ada di panduan user baru dan sudo.
2. Buat SSH key khusus deploy
Buat pasangan key baru di laptop, jangan memakai key pribadimu:
ssh-keygen -t ed25519 -C "github-deploy" -f ./deploy_key -N ""
Salin isi deploy_key.pub ke /home/deploy/.ssh/authorized_keys di server, dengan izin folder .ssh 700 dan file 600, dimiliki user deploy. Uji dulu dari laptop dengan ssh -i ./deploy_key deploy@IP-SERVER.
3. Simpan secrets di repository
Buka repo di GitHub, masuk ke Settings, lalu Secrets and variables, lalu Actions. Tambahkan:
| Nama secret | Isi |
|---|---|
SSH_PRIVATE_KEY | Isi file deploy_key (private key) |
SSH_HOST | IP atau hostname VPS |
SSH_USER | deploy |
SSH_KNOWN_HOSTS | Hasil ssh-keyscan -t ed25519 IP-SERVER, dicek cocok dengan fingerprint server |
Secret tidak tampil di log workflow dan tidak bisa dibaca ulang dari antarmuka GitHub setelah disimpan. Menyimpan known_hosts sebagai secret lebih aman daripada menjalankan ssh-keyscan di setiap deploy, karena kamu memastikan fingerprint sekali saat menyiapkan, bukan mempercayai apa pun yang menjawab di alamat itu.
Setelah tersimpan, hapus file deploy_key dari laptop atau simpan di pengelola password.
4. Tulis file workflow
Buat file .github/workflows/deploy.yml di repo:
name: Deploy ke VPS
on:
push:
branches: [main]
workflow_dispatch:
concurrency:
group: deploy-produksi
cancel-in-progress: false
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Siapkan SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
echo "${{ secrets.SSH_KNOWN_HOSTS }}" > ~/.ssh/known_hosts
- name: Kirim file
run: |
rsync -az --delete --exclude ".git" --exclude ".env" \
./ ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:/var/www/app/
- name: Muat ulang aplikasi
run: |
ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} \
"sudo /usr/bin/systemctl restart app.service"
Bagian concurrency mencegah dua deploy berjalan bersamaan kalau ada dua push beruntun. workflow_dispatch menambahkan tombol untuk menjalankan deploy secara manual dari tab Actions.
Perhatikan opsi --delete pada rsync. Opsi ini menghapus file di server yang tidak ada di repo, jadi pastikan folder upload pengguna atau file .env tidak berada di dalam folder tujuan, atau dikecualikan dengan --exclude.
5. Tambahkan tes sebelum deploy
Deploy otomatis paling berguna kalau kode yang rusak tidak ikut terkirim. Pisahkan job tes dan job deploy, lalu buat job deploy menunggu tes dengan needs: test. Bila tes gagal, deploy tidak dijalankan.
6. Uji dan pantau
Push perubahan kecil ke main, lalu buka tab Actions di repo. Setiap langkah punya log sendiri, sehingga kalau gagal kamu bisa melihat di mana berhentinya. Kesalahan yang paling sering muncul di percobaan pertama adalah izin folder di server dan isi known_hosts yang tidak cocok.
Bagaimana menjaga deploy tetap aman?
Beberapa kebiasaan yang membantu:
- Pakai fitur Environments di GitHub untuk produksi, lalu aktifkan aturan persetujuan bila timmu lebih dari satu orang. Deploy baru jalan setelah ada yang menyetujui.
- Batasi siapa yang boleh push langsung ke
maindengan branch protection. - Jangan menaruh file
.envproduksi di repo. Simpan di server saja, di luar jangkauan rsync. - Kunci versi action pihak ketiga. Untuk action dari luar GitHub, dokumentasi keamanan GitHub menyarankan merujuk ke commit SHA lengkap agar tidak berubah diam-diam.
Ringkasan langkah dan hal yang sering terlewat
| Langkah | Yang perlu dicek |
|---|---|
| User deploy | Bukan root, hanya punya hak di folder aplikasi |
| SSH key | Key khusus, private key hanya di GitHub Secrets |
| known_hosts | Fingerprint dicek saat menyiapkan |
| Workflow | Ada concurrency, tes jalan sebelum deploy |
| rsync | --exclude untuk .env dan folder upload |
| Reload | Sudo terbatas pada satu perintah |
Pertanyaan yang sering diajukan
Apakah deploy lewat GitHub Actions gratis?
GitHub memberi kuota menit runner untuk akun gratis dan berbayar, dan repo publik punya ketentuan sendiri. Besarnya bisa berubah, jadi cek halaman billing GitHub untuk angka terbaru. Deploy sederhana dengan rsync biasanya hanya butuh waktu singkat per jalan.
Lebih baik git pull di server atau rsync dari runner?
rsync dari runner membuat server tidak perlu akses ke repo dan memungkinkan build dilakukan di runner. git pull di server lebih sederhana, tapi server butuh deploy key untuk membaca repo dan build terjadi di mesin produksi.
Bisakah deploy ke VPS yang SSH-nya hanya dibuka untuk IP tertentu?
Bisa, dengan self-hosted runner yang dipasang di jaringan yang diizinkan, atau lewat VPN. Runner milik GitHub memakai IP yang berganti-ganti, sehingga sulit dimasukkan ke whitelist.
Bagaimana kalau aplikasinya pakai Docker?
Polanya mirip. Runner membangun image, mendorongnya ke registry, lalu lewat SSH menjalankan docker compose pull dan docker compose up -d di server.
Checklist sebelum menyalakan deploy otomatis:
- User
deploydibuat dan login dengan key berhasil - Empat secret tersimpan di repo
.envdan folder upload aman dari--delete- Tes berjalan sebelum job deploy
- Cara rollback sudah dicoba sekali


