Deploy Golang App dengan Github Actions & Tanpa Docker!
Intro
Beberapa bulan terakhir (6 bulan lalu dari tulisan ini dirilis), saya sedang menyelesaikan projek untuk tugas akhir S1. Karena saya mengambil peminatan di Rekayasa Perangkat Lunak, jadi saya mengambil judul tugas akhir yang mengembangkan sistem backend menggunakan bahasa pemrograman Go.
Saat itu, saya memasukkan di proposal penelitian bahwa aplikasi ini akan di-deploy di server menggunakan Docker. Namun, setelah seminar proposal telah dilaksanakan dan tahap pengembangan saya lakukan, saya menemukan videonya Mas Didit yang membahas deployment Go tanpa Docker!
Setelah menonton itu jadi tahu kalau sebenernya kita bisa deploy tanpa Docker :D. Dengan rasa penasaran yang cukup besar akhirnya saya mencoba melakukannya dan mengimplementasikannya.
Pada kasus saya ini, saya juga mengintegrasikannya dengan GitHub Actions, sehingga jika ada trigger berupa push ke main branch maka deployment akan dijalankan. Tahapan dari deployment-nya adalah sebagai berikut:
- Build
- SSH ke server
- Stop service yang lagi berjalan
- Copy hasil build ke server
- Start service lagi
- Selesai!
Inisiasi Repo
Sebelum memulai lebih jauh, saya menyiapkan sebuah repositori Go sebagai demo dari metode ini.
Repositori di atas terdapat file main.go yang memiliki sebuah endpoint dan jalan pada port 8080, serta terdapat file deployment pada direktori .github/workflows
yang akan digunakan pada GitHub Actions. Kode pada file tersebut adalah seperti di bawah ini:
name: Deploying Go
on:
push:
branches:
- main
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: "1.22" # Set this to your Go version
- name: Build binary
run: |
GOOS=linux GOARCH=amd64 go build -o go-deploy
- name: Stop service
uses: appleboy/ssh-action@v0.1.4
with:
host: ${{ secrets.SERVER_IP }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
port: 22
script: |
systemctl stop go-deploy
- name: Copy Binary File to Server
uses: appleboy/scp-action@v0.1.2
with:
host: ${{ secrets.SERVER_IP }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
port: 22
source: "go-deploy"
target: "/home/gh-actions"
- name: Restart service
uses: appleboy/ssh-action@v0.1.4
with:
host: ${{ secrets.SERVER_IP }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
port: 22
script: |
systemctl restart go-deploy
Inisiasi Server
Untuk melakukan uji coba ini, saya menggunakan sebuah server dengan Amazon Lightsail dengan operasi sistem Debian. Untuk melakukannya tidak harus dengan menggunakan Amazon Lightsail, silahkan sesuaikan dengan kebutuhan masing-masing.
Membuat User
Saya membuat user baru di server, user ini dinamakan gh-actions
dan tidak memiliki akses sudo
. Pada nantinya, gh-actions ini yang akan menjalankan dan memberhentikan service yang kita deploy.
Menambahkan Service File
Selanjutnya, jika sudah membuat user baru. Kita akan membuat sebuah file service pada systemd. Nantinya, kita akan menjalankan service ini dengan perintah systemctl.
Untuk dapat menambahkan file service baru, kita membutuhkan user root atau yang memiliki akses sudo. File service akan ditambahkan di direktori /lib/systemd/system/
.
Saya akan menjalankan perintah sudo vim /lib/systemd/system/go-deploy.service
go-deploy merupakan nama service yang akan digunakan dan ini dapat disesuaikan dengan kebutuhan masing-masing. Lalu silahkan paste kode di bawah ini dan save.
[Unit]
Description=Go-Deploy Service
[Service]
Type=simple
Restart=always
RestartSec=5s
WorkingDirectory=/home/gh-actions
ExecStart=/home/gh-actions/go-deploy
[Install]
WantedBy=multi-user.target
Pada kode di atas dapat dilihat terdapat WorkingDirectory
merupakan direktori spesifik di mana program disimpan dan dijalankan. ExecStart
akan mengeksekusi file yang sesuai dengan path yang sudah ditentukan. Jadi, nantinya akan menjalankan file go-deploy
pada direktori gh-actions
.
Menambahkan/Memberi akses User
Setelah menyimpannya, kita dapat mencoba menjalankan dengan perintah sudo systemctl start go-deploy.service
atau sudo systemctl start go-deploy
. Tentunya jika dicek status-nya maka akan terlihat error dikarenakan kita belum memiliki file go-deploy.
Agar user gh-actions dapat menjalankan serta memberhentikan service tanpa memerlukan sudo, kita akan mengatur file policy pada polkit-1.
Jalankan sudo vim /etc/polkit-1/rules.d/10-go-deploy.rules
dan tambahkan kode di bawah ini ke dalam file tersebut.
polkit.addRule(function(action, subject) {
if (action.id == "org.freedesktop.systemd1.manage-units" &&
action.lookup("unit") == "go-deploy.service" &&
subject.user == "gh-actions") {
return polkit.Result.YES;
}
});
Setelah disimpan, maka kita dapat menjalankan dan memberhentikan service tanpa memerlukan sudo pada user gh-actions.
Seperti gambar di atas, gambar pertama (kiri) merupakan hasil ketika file policy belum ditambahkan dan kita tidak dapat memberhentikan service tanpa akses sudo. Pada gambar kedua, setelah file policy ditambahkan, kita berhasil memberhentikan service.
Menambahkan SSH-Key
Pada GitHub Actions nantinya, kita memerlukan SSH Key. SSH Key akan menjadi “kunci” agar server GitHub Actions dapat “masuk” ke server deployment kita.
Jika belum memiliki ssh-key
, silahkan generate terlebih dahulu dengan ssh-keygen. Setelah berhasil kita memiliki 2 file key yaitu public key
dan private key
. Tambahkan isi dari public key
ke dalam file authorized_keys
di direktori ~/.ssh/
pada user gh-actions
.
Deployment
Konfigurasi GitHub Env
Pastikan kode yang akan digunakan sudah dipush ke GitHub. Jika sudah, dapat menuju ke settings
dan ke bagian Secrets and Variables
dan memilih Actions
.
Pada Repository secrets
silahkan tambahkan secret yang akan digunakan, yaitu ada:
- SERVER_IP yang berisikan IP dari server deployment.
- SERVER_USER yang berisikan nama user, di sini saya memasukkan gh-actions
- SSH_PRIVATE_KEY yang berisikan private key dari SSH yang dimiliki/dibuat sebelumnya
Pastikan penamaannya sudah sesuai.
Re-run Jobs
Jika sudah selesai menambahkan secrets, kita akan mencoba re-run jobs yang gagal karena sebelumnya belum menambahkan secrets.
Jika sudah berhasil maka akan berubah menjadi checklist dan berwarna hijau
Final
Kita dapat memanggil <IP>:8080 untuk melihat apakah service sudah berjalan atau belum.
Seperti pada gambar di atas, service sudah berhasil berjalan dan mengembalikan hasil sesuai yang diinginkan!
Sampai jumpa pada tulisan saya berikutnya! :)