Lewati ke isi

Server & Infrastruktur

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.

Terbit 6 menit baca

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
  1. Bagaimana alurnya bekerja?
  2. Langkah menyiapkan deploy otomatis
  3. 1. Buat user khusus deploy di VPS
  4. 2. Buat SSH key khusus deploy
  5. 3. Simpan secrets di repository
  6. 4. Tulis file workflow
  7. 5. Tambahkan tes sebelum deploy
  8. 6. Uji dan pantau
  9. Bagaimana menjaga deploy tetap aman?
  10. Ringkasan langkah dan hal yang sering terlewat
  11. 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 secretIsi
SSH_PRIVATE_KEYIsi file deploy_key (private key)
SSH_HOSTIP atau hostname VPS
SSH_USERdeploy
SSH_KNOWN_HOSTSHasil 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 main dengan branch protection.
  • Jangan menaruh file .env produksi 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

LangkahYang perlu dicek
User deployBukan root, hanya punya hak di folder aplikasi
SSH keyKey khusus, private key hanya di GitHub Secrets
known_hostsFingerprint dicek saat menyiapkan
WorkflowAda concurrency, tes jalan sebelum deploy
rsync--exclude untuk .env dan folder upload
ReloadSudo 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 deploy dibuat dan login dengan key berhasil
  • Empat secret tersimpan di repo
  • .env dan folder upload aman dari --delete
  • Tes berjalan sebelum job deploy
  • Cara rollback sudah dicoba sekali

Sumber & referensi

Baca juga