Kendi sunucunda çalışan, tamamen açık kaynak ve az kaynak tüketen bir CI/CD aracı arıyorsan Woodpecker CI listenin başında olmalı. Drone'un topluluk çatalı olarak doğdu, aynı sadeliği ve konteyner tabanlı pipeline modelini korudu, ama lisans tarafındaki belirsizliği tamamen ortadan kaldırdı: Apache 2.0 ile dağıtılıyor ve ölçeğe bağlı bir kısıt taşımıyor.
Woodpecker CI kurulumu iki bileşenden oluşur — bir server ve bir ya da daha fazla agent — ve tipik bir kurulum tek bir Compose dosyasıyla ayağa kalkar. Bu rehberde önce mimariyi netleştireceğim, Git sağlayıcısı tarafındaki OAuth adımını yapacağız, Compose dosyasını yazıp servisleri başlatacağız, deponun kökündeki .woodpecker.yml dosyasıyla çalışan bir hat kuracağız ve secret yönetimini güvenli biçimde tamamlayacağız. Sonda da üretimde en çok zaman kaybettiren tuzaklar var.
Woodpecker Nedir, Drone'dan Farkı Ne#
Woodpecker, Drone'un açık kaynak sürümünden ayrılarak bağımsız geliştirilen bir projedir. Temel model aynıdır: pipeline tanımı deponun içinde yaşar, her adım bir konteynerde çalışır, gizli bilgiler arayüzde tanımlanır. Bu yüzden Drone bilen biri Woodpecker'a birkaç saatte geçer.
Farklar üç başlıkta toplanıyor. Lisans: Woodpecker Apache 2.0'dır, kullanım ölçeğine bağlı bir koşul taşımaz. Söz dizimi: Woodpecker kendi yolunu çizdi; steps bloğunun yapısı, when koşullarının yazımı ve matris desteği sürümler arasında Drone'dan ayrıştı, dolayısıyla bir .drone.yml dosyasını olduğu gibi kopyalayamazsın. Ekosistem: Drone'un eklenti kütüphanesi daha geniştir, ama Woodpecker Drone eklentilerinin çoğunu çalıştırabilir çünkü eklenti dediğimiz şey sonuçta ortam değişkenleriyle beslenen bir konteynerdir.
| Konu | Woodpecker | Drone |
|---|---|---|
| Lisans | Apache 2.0, kısıtsız | Ölçeğe bağlı koşullar |
| Yapılandırma dosyası | .woodpecker.yml | .drone.yml |
| Bileşenler | Server + agent | Server + runner |
| Kaynak tüketimi | Çok düşük | Çok düşük |
| Git sağlayıcıları | Gitea, Forgejo, GitHub, GitLab, Bitbucket | GitHub, GitLab, Gitea, Bitbucket |
İki aracın hangi durumda hangisinin seçileceğini merak ediyorsan Drone CI kurulumu yazısındaki karşılaştırma tabloları da işine yarar. Kendi Git sunucunla birlikte tam bağımsız bir yığın kurmak istiyorsan Woodpecker'ın Gitea ve Forgejo desteği bu ikiliyi doğal bir eşleşme yapıyor.
Mimari: Server ve Agent#
Server, web arayüzünü sunar, Git sağlayıcısıyla konuşur, webhook'ları karşılar ve iş kuyruğunu tutar. Derleme yapmaz. Agent ise server'a bağlanır, kuyruktan iş alır ve adımları konteyner olarak çalıştırır. İkisi arasındaki güven WOODPECKER_AGENT_SECRET değeriyle kurulur ve bu değerin iki tarafta birebir aynı olması zorunludur.
Agent, server ile gRPC üzerinden konuşur ve varsayılan port 9000'dir. Aynı makinedeyseler bu portu dışarı açmana gerek yoktur; agent'ı ayrı bir sunucuya taşıdığında ise 9000 portunu yalnızca o sunucuya açmalı, mümkünse araya TLS koymalısın. Aksi hâlde ağı dinleyen biri, sırrı ele geçirip kuyruktan iş çekebilir.
Bir server'a birden fazla agent bağlayabilirsin ve ölçeklemenin yolu budur: yük arttığında server'a dokunmadan yeni bir agent sunucusu eklersin. Her agent'ın eşzamanlı çalıştıracağı iş sayısını WOODPECKER_MAX_WORKFLOWS belirler; sunucunun çekirdek sayısına göre mütevazı tutmak, derlemelerin birbirini boğmasını engeller.
Git Sağlayıcı Tarafında OAuth#
Woodpecker kendi kullanıcı veritabanını tutmaz; kimlik doğrulamayı Git sağlayıcın üzerinden yapar. Gitea kullanıyorsan Ayarlar → Uygulamalar → OAuth2 Uygulamaları bölümünden yeni bir uygulama oluşturursun. Tek kritik alan geri dönüş adresidir:
Uygulama adı: Woodpecker CI
Yönlendirme URI'si: https://ci.firmaniz.com/authorize
/authorize yolunu unutmak, girişte "redirect uri mismatch" hatasının bir numaralı sebebidir. GitHub kullanıyorsan aynı işi Settings → Developer settings → OAuth Apps yolundan yapar ve aynı geri dönüş adresini girersin. Kendi Git sunucunu henüz kurmadıysan Gitea ile kendi Git sunucunuz yazısı bu adımın öncesini kapsıyor.
Uygulamayı oluşturduğunda Client ID ve Client Secret alırsın. Bir de agent sırrı üretmen gerekiyor:
# Server ile agent arasındaki paylaşılan sır
openssl rand -hex 32
Docker Compose ile Kurulum#
Aşağıdaki dosya Gitea entegrasyonlu bir kurulumdur. GitHub kullanıyorsan WOODPECKER_GITEA* değişkenlerini WOODPECKER_GITHUB* ile değiştirirsin; yapı aynı kalır.
services:
woodpecker-server:
image: woodpeckerci/woodpecker-server:latest
restart: unless-stopped
ports:
- "127.0.0.1:8000:8000" # arayüz, ters vekil arkasında
volumes:
- woodpecker-veri:/var/lib/woodpecker # SQLite veritabanı
environment:
WOODPECKER_HOST: https://ci.firmaniz.com
WOODPECKER_AGENT_SECRET: ${AGENT_SECRET}
WOODPECKER_GITEA: "true"
WOODPECKER_GITEA_URL: https://git.firmaniz.com
WOODPECKER_GITEA_CLIENT: ${GITEA_CLIENT_ID}
WOODPECKER_GITEA_SECRET: ${GITEA_CLIENT_SECRET}
WOODPECKER_ADMIN: kullaniciadin # Git sağlayıcıdaki kullanıcı adı
WOODPECKER_OPEN: "false" # herkes kayıt olamasın
woodpecker-agent:
image: woodpeckerci/woodpecker-agent:latest
restart: unless-stopped
depends_on: [woodpecker-server]
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
WOODPECKER_SERVER: woodpecker-server:9000
WOODPECKER_AGENT_SECRET: ${AGENT_SECRET} # server ile AYNI
WOODPECKER_MAX_WORKFLOWS: "2"
volumes:
woodpecker-veri:
Değerleri yanına koyacağın .env dosyasında tut ve o dosyayı sürüm kontrolüne ekleme:
# .env — depoya EKLENMEYECEK
AGENT_SECRET=...
GITEA_CLIENT_ID=...
GITEA_CLIENT_SECRET=...
docker compose up -d
docker compose logs -f woodpecker-agent | head -20
# Beklenen: agent'ın server'a başarıyla kaydolduğunu belirten satır
WOODPECKER_OPEN: "false" ayarı önemlidir: true bırakırsan Git sağlayıcında hesabı olan herkes CI'a giriş yapabilir. Kapalı tutup kullanıcıları arayüzden ya da WOODPECKER_ADMIN listesiyle eklemek doğru yaklaşımdır. Compose dosyalarının yapısı ve .env kullanımıyla ilgili ayrıntılar için Docker Compose kullanımı yazısına bakabilirsin.
Son adım ters vekil ve TLS'tir; WOODPECKER_HOST değerinde https yazdığın için sertifikayı Nginx tarafında sonlandırıp X-Forwarded-Proto başlığını iletmelisin. Aksi hâlde webhook adresleri yanlış üretilir ve derlemeler hiç tetiklenmez.
İlk .woodpecker.yml Dosyası#
Deponun köküne .woodpecker.yml koyarsın; birden çok hattı ayrı dosyalara bölmek istersen .woodpecker/ dizini altına yerleştirebilirsin ve her dosya bağımsız bir pipeline olur.
steps:
- name: testler
image: node:22-alpine
commands:
- npm ci
- npm run lint
- npm test
- name: imaj
image: woodpeckerci/plugin-docker-buildx
settings:
registry: kayit.firmaniz.com
repo: kayit.firmaniz.com/api
tags:
- ${CI_COMMIT_SHA}
- latest
username:
from_secret: kayit_kullanici
password:
from_secret: kayit_parola
when:
- branch: main
event: push
- name: dagitim
image: appleboy/drone-ssh
settings:
host: 185.12.34.56
username: deploy
key:
from_secret: ssh_anahtari
script:
- cd /srv/uygulama
- docker compose pull
- docker compose up -d --remove-orphans
when:
- branch: main
event: push
services:
- name: veritabani
image: postgres:16-alpine
environment:
POSTGRES_PASSWORD: test
POSTGRES_DB: testdb
Birkaç davranışı bilmen işini kolaylaştırır. Adımlar varsayılan olarak sırayla çalışır; biri başarısız olursa sonrakiler atlanır. services bölümündeki konteynerler pipeline boyunca ayakta kalır ve adımlardan servis adıyla (veritabani:5432) erişilir. Bir adımın başarısızlıkta da çalışmasını istiyorsan when içinde status: [success, failure] belirtirsin; bildirim adımları için tipik kullanım budur.
İmajı ${CI_COMMIT_SHA} ile etiketlemek, hangi kodun yayında olduğunu kesinleştirir ve geri almayı tek adıma indirir. Yalnızca latest kullanmak, bir sorun çıktığında dönecek referansın olmaması demektir. Etiketleme ve katman sırası alışkanlıkları için Dockerfile en iyi pratikler yazısı iyi bir tamamlayıcı.
Secret Yönetimi ve Güvenlik#
Parolaları .woodpecker.yml içine yazamazsın; o dosya depoda duruyor. Woodpecker'ın secret deposu depo ayarlarındaki Secrets sekmesindedir ve pipeline'da from_secret ile çağrılır. Dikkat etmen gereken üç nokta var:
- Olay kapsamı. Bir secret'ı hangi olaylarda (push, tag, pull_request, deployment) kullanılabilir yapacağını sen seçersin. Dış katkı alan bir depoda secret'ları
pull_requestolayına açmak, kötü niyetli bir katkının yapılandırmayı değiştirip değeri dışarı yazdırmasına kapı açar. Varsayılanı bozma. - Kapsam seviyesi. Secret'lar depo, organizasyon veya küresel seviyede tanımlanabilir. Üretim SSH anahtarını küresel yapmak, o anahtarı CI'daki her depoya vermek demektir; mümkün olan en dar kapsamı seç.
- Ayrıcalıklı eklentiler. Bazı eklentiler ana makine soketine ya da ayrıcalıklı moda ihtiyaç duyar ve bunlar yönetici tarafından açıkça izin verilmedikçe çalışmaz. Bu izni vermeden önce eklentinin ne yaptığını gerçekten bildiğinden emin ol; ayrıcalıklı bir konteyner, sunucunun tamamına erişim demektir. Konunun ayrıntısı Docker daemon socket permission denied yazısında.
Kimlik bilgisi sızıntısının pratikte ne kadar hızlı istismar edildiğini görmek istersen .git klasörü ve .env dosyası ifşası yazısı iyi bir uyarıdır.
Koşullar, Matris ve Önbellek#
when bloğu hangi adımın ne zaman çalışacağını belirler ve birden fazla koşulu birlikte yazabilirsin:
when:
- branch: [main, "surum/*"]
event: [push, tag]
- event: pull_request
path: ["api/**", "package-lock.json"]
path koşulu tek depoda birden çok servis tutuyorsan çok işe yarar: yalnızca ilgili dizin değiştiğinde o servisin testleri çalışır ve pipeline süresi belirgin biçimde kısalır.
Matris ile aynı adımı farklı sürümlerde çalıştırabilirsin:
matrix:
NODE_VERSION:
- "20"
- "22"
steps:
- name: testler
image: node:${NODE_VERSION}-alpine
commands:
- npm ci
- npm test
Önbellek konusunda Woodpecker hazır bir çözüm dayatmaz; iki pratik yol vardır. Birincisi, bağımlılıkları bir nesne deposuna gönderen eklentileri kullanmak. İkincisi ve küçük kurulumlarda çok daha basiti, bağımlılıkları kendi temel imajına gömüp o imajı haftada bir yenilemektir — her derlemede yüzlerce paketi indirmekten çok daha hızlıdır. İmajları küçük tutmanın yolları için Docker imaj boyutu optimizasyonu yazısına göz atabilirsin.
Sık Yapılan Hatalar ve Tuzaklar#
Agent sırrını iki tarafta farklı yazmak. Derlemeler kuyrukta bekliyor ve hiç başlamıyorsa ilk bakılacak yer budur; agent log'unda kimlik doğrulama hatası görünür.
WOODPECKER_HOST değerini yanlış vermek. Bu adres hem webhook'ların hem OAuth geri dönüşünün temelidir. Sondaki eğik çizgiyi koyma ve protokolü gerçek durumla (ters vekilde TLS varsa https) uyumlu tut.
Depoyu arayüzde etkinleştirmeyi unutmak. Woodpecker, depoyu arayüzden etkinleştirene kadar webhook kurmaz. .woodpecker.yml dosyası deponun içinde olsa bile hiçbir şey çalışmaz; arayüzdeki depo listesinden "Etkinleştir" adımını atlama.
WOODPECKER_OPEN ayarını açık bırakmak. Git sağlayıcın herkese açık kayıt kabul ediyorsa, CI arayüzün de fiilen herkese açık hâle gelir. Kapalı tut ve kullanıcıları elle ekle.
Disk temizliğini ihmal etmek. Her derleme yeni imaj katmanları ve geçici hacimler bırakır. Haftalık bir temizlik görevi kur; birikimin nasıl bir soruna dönüştüğünü Docker diski doldurdu, nasıl temizlenir yazısında anlattım.
# Haftalık temizlik için uygun komut
docker system prune -af --filter "until=168h"
Sürüm yükseltmelerinde söz dizimi değişikliklerini atlamak. Woodpecker majör sürümler arasında pipeline söz diziminde değişiklikler yaptı. Yükseltmeden önce sürüm notlarını okumak ve latest yerine sabit bir sürüm etiketi kullanmak, bir sabah tüm hatların kırılmasını engeller.
Sıkça Sorulan Sorular#
Woodpecker CI ücretsiz mi#
Evet, Woodpecker Apache 2.0 lisansıyla dağıtılan tamamen açık kaynak bir projedir. Kullanıcı sayısı, depo sayısı ya da derleme adedi için hiçbir ücret veya lisans koşulu yoktur. Tek maliyetin server ve agent'ı çalıştıracağın sunucudur; küçük bir ekip için mütevazı bir sanal sunucu fazlasıyla yeter.
Woodpecker ile Drone arasındaki fark nedir#
Woodpecker, Drone'un açık kaynak sürümünden ayrılan bir topluluk projesidir. En büyük fark lisanstadır: Woodpecker kısıtsız Apache 2.0 iken Drone belirli bir ölçeğin üzerinde ticari lisans gerektirir. Söz dizimi de zamanla ayrıştı, bu yüzden bir .drone.yml dosyasını olduğu gibi kopyalayamazsın; ama kavramlar aynı olduğu için dönüştürmesi birkaç saatlik iştir.
Derlemeler neden başlamıyor#
Sırayla üç şeyi kontrol et. Birincisi, depo arayüzde etkinleştirilmiş mi — etkinleştirilmemiş bir depoya webhook kurulmaz. İkincisi, Git sağlayıcının depo ayarlarındaki webhook kayıtlarında son teslimat başarılı mı; başarısızsa WOODPECKER_HOST değeri ya da ters vekil yapılandırması hatalıdır. Üçüncüsü, agent server'a bağlanabiliyor mu; agent log'unda kayıt satırı yoksa sır uyuşmuyordur.
Ne kadar sunucu kaynağı gerekir#
Server bileşeni çok hafiftir ve birkaç yüz megabayt bellekle çalışır. Asıl tüketim agent'ın çalıştırdığı adımlardadır. Küçük bir ekip için 2 çekirdek ve 4 GB bellekli bir sunucu rahatlıkla yeter; derlemeler ağırsa WOODPECKER_MAX_WORKFLOWS değerini düşük tutup gerektiğinde ikinci bir agent sunucusu eklemek daha öngörülebilir bir yoldur.
GitHub Actions yerine Woodpecker kullanmalı mıyım#
Kodun GitHub'daysa ve özel bir gereksinimin yoksa GitHub Actions daha az bakım ister. Woodpecker'ı şu durumlarda tercih et: kodun kendi Git sunucunda duruyor, derleme çıktılarının dışarı çıkmasını istemiyorsun, iç ağdaki kaynaklara erişmen gerekiyor ya da dakika kotası ekonomik olmaktan çıkmış. Kendi altyapında tam kontrol istiyorsan doğal seçenek budur.
Birden fazla agent ekleyebilir miyim#
Evet ve yük arttığında yapman gereken tam olarak budur. Yeni sunucuya yalnızca agent konteynerini kurar, WOODPECKER_SERVER değerine server'ın adres ve gRPC portunu, WOODPECKER_AGENT_SECRET değerine de aynı sırrı verirsin. Agent kendini kaydeder ve kuyruktan iş almaya başlar. Farklı mimarilerde agent çalıştırıp adımları etiketlerle yönlendirmek de mümkündür.
Kapanış#
Woodpecker, kendi altyapısında kalmak isteyen ekipler için kurulumu en hızlı ve lisans tarafı en net CI seçeneklerinden biri. Sağlıklı bir kurulum için şu dördünü aklında tut: agent sırrını iki tarafta birebir aynı yaz, WOODPECKER_HOST değerini ters vekildeki gerçek protokolle uyumlu tut, WOODPECKER_OPEN ayarını kapalı bırak ve imaj etiketlerinde commit sha'sını kullanarak geri dönüş yolunu açık tut. Bir de haftalık disk temizliği görevi kurmayı unutma.
Woodpecker server ve agent'larını barındırmak için tam root erişimli VDS ya da ihtiyaca göre büyüyen bulut sunucu paketlerimiz uygun bir zemin sunuyor; agent'ı ayrı bir makinede tutmak istersen sanal sunucu ekonomik bir başlangıç olur. Sunucu kurulumu, güncellemeler ve yedekleme planıyla uğraşmak istemiyorsan sunucu yönetimi ve yedekleme hizmetlerimiz bu işi sizin yerinize üstlenir.