Cara Install Woodpecker CI di VPS: Pipeline Otomatis Abis Push ke Gitea

Coba inget-inget, udah berapa kali kamu ngetik urutan command yang sama abis push kode ke Gitea? Build image, jalanin test, terus restart container manual lewat SSH. Ngebosenin, dan gampang kelewatan satu langkah pas buru-buru. Di titik inilah CI/CD jadi penting – bukan buat perusahaan besar doang, tapi buat siapa aja yang capek ngulang-ngulang proses deploy manual. Woodpecker CI ngasih solusi yang pas buat self-hoster: ringan, container-native, dan terintegrasi langsung sama Gitea. Tinggal push, sisanya jalan sendiri. Di artikel ini saya bakal bahas cara install Woodpecker CI di VPS pakai Docker dari nol, lengkap dengan penjelasan detail di setiap langkahnya.

Apa Itu Woodpecker CI

Buat yang belum familiar, CI/CD itu singkatan dari Continuous Integration / Continuous Deployment. Intinya: setiap kali kamu push kode, sistem otomatis nge-build, nge-test, dan nge-deploy tanpa kamu harus jalanin command manual satu-satu.

Woodpecker CI adalah engine CI/CD yang ringan dan container-native. Awalnya ini fork dari Drone CI yang muncul setelah Drone berubah jadi produk komersial. Setiap step pipeline dijalanin di container Docker terpisah, jadi environment-nya bersih dan gampang direproduksi. Konfigurasinya cukup satu file YAML per repo.

Woodpecker terdiri dari dua komponen utama:

  • Woodpecker Server: Otak dari sistem. Dia yang nangani web UI, API, nyimpen data pipeline, nerima webhook dari Gitea, dan nge-assign job ke agent. Data pipeline disimpen di SQLite (default), jadi gak perlu database tambahan buat skala kecil-menengah
  • Woodpecker Agent: Eksekutor yang beneran ngerjain step-step pipeline di dalam container Docker. Agent nerima instruksi dari server lewat gRPC (port 9000), lalu jalanin setiap step di container terpisah. Kamu bisa jalanin beberapa agent sekaligus kalau butuh parallel builds

Cara kerjanya simpel: kamu push kode ke Gitea, Gitea ngirim webhook ke Woodpecker Server, server nge-assign job ke agent, agent jalanin step-step pipeline di container, hasilnya dilaporin balik ke dashboard.

Diagram Arsitektur Woodpecker CI di VPS

Bedanya Woodpecker Sama GitHub Actions, Jenkins, dan Drone

Karena CI/CD tools banyak pilihannya, ini perbandingan singkat biar jelas posisi masing-masing:

GitHub Actions cocok kalau repo kamu emang di GitHub. Tapi begitu kamu pindah ke Gitea yang self-hosted, Actions otomatis gak relevan lagi. Gitea punya Gitea Actions sendiri, tapi masih relatif baru dan ekosistemnya belum selengkap Woodpecker.

Jenkins itu veteran di dunia CI/CD, fiturnya lengkap banget. Tapi resource-nya berat (butuh Java runtime), maintenance plugin-nya makan waktu, dan setup-nya jauh lebih kompleks. Buat VPS kecil, Jenkins kebesaran.

Drone CI itu “kakak” Woodpecker – codebase aslinya sama. Tapi Drone udah berubah jadi produk komersial dengan lisensi yang lebih ketat. Woodpecker tetep full open source dan community-driven.

Kapan pilih Woodpecker: kalau kamu pakai Gitea (atau Forgejo) self-hosted, butuh CI/CD yang ringan, dan gak mau ribet setup Jenkins atau bayar lisensi Drone.

Prasyarat Sebelum Install Woodpecker CI di VPS

Woodpecker emang ringan, tapi ada beberapa hal yang wajib disiapin dulu biar instalasinya lancar.

1. VPS dengan Spesifikasi Minimum

Woodpecker sendiri gak berat, tapi agent-nya bakal nge-build image Docker yang bisa makan resource lumayan. Spek minimum:

  • RAM: Minimal 2GB. Server Woodpecker cuma makan sekitar 100-200MB, tapi agent butuh lebih buat build container
  • CPU: Minimal 2 vCPU. Build Docker image itu CPU-intensive
  • Storage: Minimal 20GB kosong. Docker image dan build cache bisa makan space lumayan
  • OS: Ubuntu 22.04 atau 24.04 LTS

Cara cek spek VPS kamu:

free -h          # cek RAM tersedia
df -h            # cek disk space
nproc            # cek jumlah CPU
lsb_release -a   # cek versi OS

2. Docker dan Docker Compose Sudah Terinstall

Woodpecker jalan sepenuhnya di atas container Docker. Kalau belum terinstall, ikutin dulu panduan Cara Install Docker di Ubuntu VPS. Verifikasi:

docker --version
docker compose version

3. Instance Gitea yang Sudah Jalan

Woodpecker butuh “forge” (platform Git) buat nerima webhook dan autentikasi user. Di artikel ini kita pakai Gitea yang self-hosted. Pastiin Gitea kamu udah jalan dan bisa diakses lewat HTTPS. Bisa di server yang sama atau server lain yang satu jaringan.

Verifikasi Gitea bisa diakses:

curl -I https://gitea.domainmu.com

4. Domain atau Subdomain

Woodpecker butuh domain/subdomain yang udah diarahin ke VPS karena OAuth callback dan webhook cuma jalan mulus lewat HTTPS. Siapin subdomain kayak woodpecker.domainmu.com dan pastiin A record-nya udah ngarah ke IP VPS.

Verifikasi DNS:

dig woodpecker.domainmu.com +short

5. Port yang Dibutuhin

Woodpecker pakai dua port utama:

  • Port 8000 – Web UI dan webhook endpoint. Ini yang diakses user lewat browser dan Gitea buat ngirim webhook
  • Port 9000 – gRPC komunikasi internal antara server dan agent. Jangan buka port ini ke publik

Cek apakah port masih kosong:

sudo lsof -i :8000
sudo lsof -i :9000

Cara Install Woodpecker CI di VPS Step by Step

Sekarang masuk ke bagian inti. Ikutin langkah-langkah di bawah ini satu per satu.

Step-by-Step Installation Flow — Woodpecker CI di VPS

Step 1 – Buat Folder Project

Login ke VPS lewat SSH, lalu bikin folder khusus buat Woodpecker:

mkdir -p /opt/woodpecker
cd /opt/woodpecker

Step 2 – Generate Agent Secret

Server dan agent perlu shared secret yang sama persis biar bisa saling percaya. Generate pakai OpenSSL:

openssl rand -hex 32

Catat hasilnya. Ini bakal dipakai di file environment nanti.

Step 3 – Setup OAuth di Gitea

Sebelum bikin docker-compose, kita perlu bikin OAuth2 application di Gitea dulu biar Woodpecker bisa autentikasi user lewat Gitea. Ini bagian yang paling sering bikin bingung, jadi ikutin dengan teliti:

Di Gitea:

  • Login ke Gitea sebagai admin
  • Masuk ke Site Administration > Applications
  • Klik Create a new OAuth2 Application
  • Isi Application Name: Woodpecker CI
  • Isi Redirect URI: https://woodpecker.domainmu.com/authorize

Penting banget soal Redirect URI:

  • Harus pakai https://, bukan http://
  • Domain harus sama persis dengan yang bakal kamu set di WOODPECKER_HOST
  • Path harus /authorize (bukan /auth atau /callback)
  • Jangan ada trailing slash di akhir
  • OAuth itu strict banget soal exact match URL – beda satu karakter aja bikin gagal

Setelah application dibuat, Gitea bakal ngasih Client ID dan Client Secret. Catat kedua nilai ini.

Step 4 – Buat File Environment (.env)

Bikin file .env buat nyimpen semua credential:

nano .env

Paste isi berikut dan ganti nilainya:

WOODPECKER_AGENT_SECRET=hasil-openssl-rand-hex-32-tadi
WOODPECKER_GITEA_CLIENT=client-id-dari-gitea
WOODPECKER_GITEA_SECRET=client-secret-dari-gitea

Penjelasan setiap variabel:

  • WOODPECKER_AGENT_SECRET: Shared secret buat komunikasi server-agent. Harus sama persis di kedua service. Beda satu karakter aja bikin handshake gagal diam-diam
  • WOODPECKER_GITEA_CLIENT: Client ID dari OAuth2 application yang baru dibikin di Gitea
  • WOODPECKER_GITEA_SECRET: Client Secret dari OAuth2 application yang sama

Simpan file dengan Ctrl+O lalu Enter, keluar dengan Ctrl+X.

Step 5 – Buat File docker-compose.yml

Masih di folder /opt/woodpecker, bikin file Docker Compose:

nano docker-compose.yml

Paste isi berikut:

services:
  woodpecker-server:
    image: woodpeckerci/woodpecker-server:v3
    container_name: woodpecker-server
    restart: always
    ports:
      - "8000:8000"
    volumes:
      - woodpecker-server-data:/var/lib/woodpecker/
    environment:
      - WOODPECKER_OPEN=false
      - WOODPECKER_HOST=https://woodpecker.domainmu.com
      - WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET}
      - WOODPECKER_GITEA=true
      - WOODPECKER_GITEA_URL=https://gitea.domainmu.com
      - WOODPECKER_GITEA_CLIENT=${WOODPECKER_GITEA_CLIENT}
      - WOODPECKER_GITEA_SECRET=${WOODPECKER_GITEA_SECRET}

  woodpecker-agent:
    image: woodpeckerci/woodpecker-agent:v3
    container_name: woodpecker-agent
    command: agent
    restart: always
    depends_on:
      - woodpecker-server
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - woodpecker-agent-config:/etc/woodpecker
    environment:
      - WOODPECKER_SERVER=woodpecker-server:9000
      - WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET}

volumes:
  woodpecker-server-data:
  woodpecker-agent-config:

Penjelasan setiap environment variable di server:

  • WOODPECKER_OPEN=false: Matiin registrasi terbuka. Cuma user yang udah ada di Gitea yang bisa login. Kalau di-set true, siapa aja yang punya akun Gitea bisa akses Woodpecker
  • WOODPECKER_HOST: URL publik Woodpecker kamu. Harus sama persis dengan Redirect URI yang di-set di Gitea OAuth. Pakai HTTPS
  • WOODPECKER_AGENT_SECRET: Shared secret buat komunikasi server-agent. Diambil dari file .env
  • WOODPECKER_GITEA=true: Aktifin Gitea sebagai forge (platform Git)
  • WOODPECKER_GITEA_URL: URL Gitea kamu. Harus bisa diakses dari container Woodpecker
  • WOODPECKER_GITEA_CLIENT dan SECRET: Credential OAuth dari Gitea. Diambil dari file .env

Penjelasan komponen agent:

  • WOODPECKER_SERVER=woodpecker-server:9000: Alamat server yang dikonek agent lewat gRPC. Pakai nama service Docker Compose, bukan IP
  • /var/run/docker.sock: Mount Docker socket dari host ke agent. Ini yang bikin agent bisa jalanin container buat setiap step pipeline. Perhatian: mount ini praktis ngasih akses setara root ke host – nanti dibahas di bagian keamanan
  • depends_on: Agent baru start setelah server udah jalan

Ganti woodpecker.domainmu.com dan gitea.domainmu.com dengan domain kamu yang sebenarnya.

Step 6 – Jalankan Container

Jalanin Woodpecker:

docker compose up -d

Cek status container:

docker compose ps

Kamu harusnya liat dua container running:

  • woodpecker-server – status Up
  • woodpecker-agent – status Up

Kalau salah satu terus-terusan restart, cek log-nya:

docker compose logs woodpecker-server --tail 50
docker compose logs woodpecker-agent --tail 50

Penyebab paling umum restart: typo di environment variable atau WOODPECKER_AGENT_SECRET gak sama antara server dan agent.

Step 7 – Login ke Dashboard Woodpecker

Kalau kamu udah setup reverse proxy (Traefik atau Nginx) di depan port 8000, buka dashboard lewat domain:

https://woodpecker.domainmu.com

Kalau belum setup reverse proxy, bisa akses langsung lewat IP dan port:

http://ip-vps-kamu:8000

Kamu bakal diarahin ke halaman login Gitea (OAuth). Login pakai akun Gitea kamu, lalu authorize Woodpecker buat akses. Setelah authorize, kamu bakal di-redirect balik ke dashboard Woodpecker dan liat list repository dari Gitea kamu.

Kalau redirect gagal atau error: Cek ulang Redirect URI di Gitea OAuth application. Harus sama persis dengan WOODPECKER_HOST + /authorize.

Bikin Pipeline Pertama

Step 8 – Buat File .woodpecker.yml di Repo

Pipeline Woodpecker dikonfigurasi lewat file .woodpecker.yml yang diletakkan di root repository. File ini otomatis kedetek tiap ada push atau pull request.

Di Gitea, buka salah satu repo kamu (pilih yang kecil dulu buat testing). Bikin file baru .woodpecker.yml di root repo:

steps:
  - name: test
    image: alpine
    commands:
      - echo "Hello from Woodpecker CI!"
      - echo "Build triggered at $(date)"
      - echo "Pipeline is working!"

Ini pipeline paling sederhana – cuma nge-print pesan buat verifikasi Woodpecker beneran jalan. Penjelasan:

  • steps: List langkah-langkah yang dijalanin pipeline
  • name: test: Nama step (bebas)
  • image: alpine: Docker image yang dipakai buat jalanin step ini. Alpine itu image Linux yang super ringan
  • commands: Command yang dijalanin di dalam container

Contoh pipeline yang lebih realistis buat proyek yang di-deploy lewat Docker:

steps:
  - name: build
    image: docker:cli
    commands:
      - docker build -t myapp:latest .

  - name: test
    image: myapp:latest
    commands:
      - npm test

  - name: deploy
    image: docker:cli
    commands:
      - docker push registry.domainmu.com/myapp:latest
    when:
      branch: main

Step deploy di atas cuma push image baru ke registry, bukan langsung SSH terus restart container. Ini sengaja. Kalau server produksi kamu udah pakai Watchtower, dia bakal narik image baru itu dan restart container-nya otomatis. Pemisahan tanggung jawab kayak gini bikin pipeline-nya lebih simpel dan gak perlu nyimpen credential SSH produksi di dalam Woodpecker.

Step 9 – Aktifkan Repo di Dashboard Woodpecker

Sebelum pipeline bisa jalan, kamu harus aktifin repo-nya dulu di dashboard Woodpecker:

  • Buka dashboard Woodpecker
  • Klik Add repository atau cari repo kamu di list
  • Klik repo yang mau diaktifin
  • Klik Enable

Begitu repo diaktifin, Woodpecker otomatis bikin webhook di Gitea. Setiap push ke repo itu bakal nge-trigger pipeline.

Step 10 – Test Push dan Verifikasi Pipeline

Sekarang test apakah semuanya berfungsi. Push perubahan ke repo yang udah diaktifin:

# di local machine kamu
git add .woodpecker.yml
git commit -m "test: add woodpecker pipeline"
git push origin main

Setelah push, buka dashboard Woodpecker. Kamu harusnya liat pipeline baru yang running atau udah selesai. Klik pipeline-nya buat liat detail setiap step:

  • Status hijau (success): Pipeline berhasil. Semua step jalan tanpa error
  • Status merah (failure): Ada step yang gagal. Klik step-nya buat liat log error
  • Status kuning (pending): Pipeline nunggu agent. Cek apakah agent container running

Kalau pipeline pertama kamu berhasil (status hijau) dengan output “Hello from Woodpecker CI!”, selamat – CI/CD kamu udah berfungsi. Setiap push ke repo ini bakal otomatis nge-trigger pipeline.

Yang Perlu Diperhatiin Setelah Install Woodpecker CI

Ada beberapa masalah yang sering muncul dan tips penting yang perlu kamu tau.

Pipeline Stuck di Pending dan Gak Pernah Mulai

Ini biasanya karena agent belum konek ke server. Cek log agent-nya:

docker compose logs woodpecker-agent --tail 30

Penyebab paling umum:

  • WOODPECKER_AGENT_SECRET gak sama: Nilai secret di server dan agent harus identik. Beda satu karakter aja bikin handshake gagal diam-diam tanpa error yang jelas
  • Agent gak bisa reach server: Pastiin WOODPECKER_SERVER=woodpecker-server:9000 bener. Kalau agent jalan di server terpisah, ganti dengan IP/domain server Woodpecker
  • Port 9000 di-block: Kalau agent di server terpisah, pastiin port 9000 terbuka di firewall server Woodpecker

Webhook dari Gitea Gak Nge-trigger Pipeline

Kalau push ke repo gak nge-trigger pipeline sama sekali, masalahnya ada di webhook. Cek beberapa hal:

  • Redirect URI salah: Cek ulang di Gitea OAuth application. Harus sama persis: https://woodpecker.domainmu.com/authorize
  • Webhook gak terkirim: Di Gitea, masuk ke repo > Settings > Webhooks. Cek apakah webhook Woodpecker ada dan statusnya success (centang hijau). Kalau ada X merah, klik buat liat error detail
  • ALLOWED_HOST_LIST di Gitea: Kalau Gitea dan Woodpecker jalan di jaringan internal (Docker network), Gitea mungkin nge-block webhook ke alamat internal. Edit app.ini Gitea dan tambahin alamat Woodpecker ke ALLOWED_HOST_LIST di section [webhook]
  • Repo belum diaktifin: Pastiin kamu udah enable repo di dashboard Woodpecker (Step 9)

Error Permission Docker Socket

Kalau build gagal dengan error permission soal Docker socket, biasanya user di dalam image agent belum punya akses cukup ke docker.sock yang di-mount. Solusi:

# cek permission docker.sock di host
ls -la /var/run/docker.sock

# kalau perlu, tambahin permission
sudo chmod 666 /var/run/docker.sock

Warning: chmod 666 itu solusi cepat tapi kurang aman buat production. Solusi yang lebih proper adalah jalanin agent dengan user yang masuk ke group docker.

Keamanan – Docker Socket dan Endpoint

Ada dua hal keamanan yang penting banget buat Woodpecker:

1. Docker Socket Mount: Agent mount /var/run/docker.sock yang praktis ngasih akses setara root ke host. Dampaknya bisa ke seluruh server, bukan cuma ke container Woodpecker. Kalau memungkinkan, jalanin agent di VPS terpisah yang khusus buat build. Jangan jalanin agent di server produksi yang nyimpen data sensitif.

2. Web Endpoint: Port 8000 (web UI dan webhook) memang harus bisa diakses dari luar biar Gitea bisa ngirim webhook. Tapi jangan expose port 8000 mentah-mentah ke publik. Taruh Traefik atau reverse proxy di depannya biar traffic lewat HTTPS. Port 9000 (gRPC server-agent) jangan dibuka ke publik – cukup jalan di jaringan internal Docker Compose.

Woodpecker vs Cronicle – Beda Fungsi

Kalau server kamu udah punya Cronicle buat jadwalin job rutin, penting misahin dua jenis otomasi ini:

  • Cronicle: Buat kerjaan yang jadwalnya pasti (time-based). Misalnya backup tiap jam 2 pagi, cleanup log tiap minggu, atau health check tiap 5 menit
  • Woodpecker: Buat kerjaan yang react ke event (event-based). Yaitu push kode, yang timingnya gak nentu. Build langsung jalan begitu ada push masuk

Yang sering ketauan di lapangan: ada yang pakai Cronicle buat jadwalin git pull terus build tiap sejam sekali. Padahal itu nutupin celah yang harusnya diisi CI beneran. Masalahnya, delay antara push dan deploy bisa sampai hampir sejam. Kalau pakai Woodpecker, build langsung jalan begitu push masuk. Jadi keduanya saling melengkapi, bukan saling gantiin.

Kesimpulan

Woodpecker CI ngasih kemampuan CI/CD yang proper buat self-hoster tanpa kompleksitas Jenkins atau ketergantungan ke platform cloud. Ringan, container-native, dan terintegrasi langsung sama Gitea. Setiap push otomatis nge-trigger build, test, dan deploy tanpa kamu harus SSH manual ke server.

Tips buat yang baru mulai: gak perlu langsung migrasiin semua repo sekaligus. Coba dulu satu repo kecil biar kamu ngerti alur push sampai deploy-nya, baru pelan-pelan tambahin repo lain begitu udah yakin pipeline-nya stabil. Mulai dari pipeline sederhana (echo test), lalu gradually tambahin step build, test, dan deploy.

Kalau digabungin sama Watchtower buat auto-pull image baru, kamu punya pipeline end-to-end yang fully automated: push kode ke Gitea, Woodpecker build dan push image ke registry, Watchtower detect image baru dan restart container di production. Semua jalan otomatis tanpa satu pun SSH manual.

Jundi Husni Mubaraq

Jundi Husni Mubaraq

Saya seorang software engineer yang sejak awal 2026 megang penuh (sendirian) tanggung jawab infrastruktur server di tempat saya kerja: deploy dan maintain server Linux Ubuntu on-premises, bangun keamanan berlapis pakai CrowdSec dan Cloudflare, kelola job scheduling dan monitoring pakai Cronicle, deploy aplikasi containerized pakai Docker, sampai ngurusin mail server korporat dari nol. Sebelumnya saya 3+ tahun jadi Software Engineer/Fullstack Developer di beberapa perusahaan, termasuk proyek skala internasional (EUDR compliance system buat Lindt & Sprungli) dan sistem rumah sakit (SIMRS, rekam medis elektronik, integrasi BPJS Kesehatan) di RS PKU Muhammadiyah Surakarta. jundi.hm ini tempat saya dokumentasiin apa yang beneran saya kerjain dan pelajarin di lapangan, bukan sekadar riset teori, S.Kom dari Universitas Duta Bangsa Surakarta jadi bekal awal, tapi yang nulis di sini adalah pengalaman langsung ngelola server production sehari-hari. Selengkapnya: https://iam.jundi.hm

Lihat Juga Nih

Selanjutnya Nih

Kasih Komentar

Email kamu gak bakal ditampilin ke publik. Kalau ada tanda ini artinya wajib diisi ya *

Rekomendasi.

Lagi Viral.