Picture this: you’re tasked with setting up a CI/CD pipeline for your team’s project. You look at Jenkins and feel overwhelmed by its complexity. You consider GitHub Actions, but you want something self-hosted. GitLab CI is great, but it’s too heavyweight for your needs. What if there was a simpler, lighter alternative that just works?
Enter Woodpecker CI – a lightweight, container-based CI/CD tool that brings simplicity back to continuous integration and deployment.
What is Woodpecker CI?
Woodpecker CI is a CI/CD automation tool designed with three core principles in mind:
- Lightweight: It’s so efficient it can run on a Raspberry Pi
- Simple: Clean, straightforward configuration with minimal complexity
- Fast: Container-based execution that gets your code from development to production quickly
If you’ve worked with Drone CI before, Woodpecker might look familiar – it’s actually a community-maintained fork of Drone that emerged when Drone moved away from its open-source roots. The community took the reins and created something even better.
Why Consider Woodpecker CI?
The Traditional CI/CD Problem
Let’s be honest: setting up CI/CD shouldn’t require a PhD. Jenkins requires managing plugins, understanding Groovy, and dealing with a UI from 2010. GitLab CI is powerful but comes with the overhead of the entire GitLab platform. Even cloud-based solutions like CircleCI or Travis CI lock you into their ecosystem and pricing.
The Woodpecker Approach
Woodpecker takes a different path:
- Container-Native: Everything runs in containers. If you’re already using Docker, you’ll feel right at home.
- YAML Configuration: Simple, declarative pipeline definitions in
.woodpecker.ymlfiles - Self-Hosted: Full control over your infrastructure and data
- Platform Integration: Native support for GitHub, GitLab, Gitea, and Forgejo
- Minimal Resource Usage: Doesn’t eat your server resources for breakfast
Getting Started with Woodpecker CI
Prerequisites
Before diving in, you’ll need:
- A server or VM (even a Raspberry Pi works!)
- Docker and Docker Compose installed
- Access to a Git hosting platform (GitHub, GitLab, Gitea, or Forgejo)
- Basic understanding of containers and YAML
Quick Setup
Let’s get Woodpecker up and running. The easiest way is using Docker Compose:
# docker-compose.yml
version: '3'
services:
woodpecker-server:
image: woodpeckerci/woodpecker-server:latest
ports:
- "8000:8000"
volumes:
- woodpecker-server-data:/var/lib/woodpecker/
environment:
- WOODPECKER_OPEN=true
- WOODPECKER_HOST=http://localhost:8000
- WOODPECKER_GITHUB=true
- WOODPECKER_GITHUB_CLIENT=${WOODPECKER_GITHUB_CLIENT}
- WOODPECKER_GITHUB_SECRET=${WOODPECKER_GITHUB_SECRET}
- WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET}
woodpecker-agent:
image: woodpeckerci/woodpecker-agent:latest
depends_on:
- woodpecker-server
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- WOODPECKER_SERVER=woodpecker-server:9000
- WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET}
volumes:
woodpecker-server-data:Then spin it up:
$ docker-compose up -dConfiguring Your Git Platform
You’ll need to create an OAuth application on your Git platform. For GitHub:
- Go to Settings → Developer settings → OAuth Apps
- Create a new OAuth App
- Set the Homepage URL to your Woodpecker instance (e.g.,
http://localhost:8000) - Set the Authorization callback URL to
http://localhost:8000/authorize - Copy the Client ID and Client Secret
Add these to your environment variables:
$ export WOODPECKER_GITHUB_CLIENT=your_client_id
$ export WOODPECKER_GITHUB_SECRET=your_client_secret
$ export WOODPECKER_AGENT_SECRET=$(openssl rand -hex 32)Creating Your First Pipeline
Now for the fun part – creating a pipeline! Let’s build a simple Node.js application pipeline.
Basic Pipeline Structure
Create a .woodpecker.yml file in your repository root:
# .woodpecker.yml
when:
- event: push
branch: main
steps:
install:
image: node:20-alpine
commands:
- npm ci
test:
image: node:20-alpine
commands:
- npm test
build:
image: node:20-alpine
commands:
- npm run build
deploy:
image: plugins/docker
settings:
registry: docker.io
repo: yourname/yourapp
username:
from_secret: docker_username
password:
from_secret: docker_password
tags: latestUnderstanding the Pipeline
Let’s break down what’s happening:
- when: Defines when the pipeline runs (on push to main branch)
- steps: Individual stages of your pipeline, each running in its own container
- image: The Docker image to use for each step
- commands: Shell commands to execute
The Conveyor Belt Analogy
Think of your pipeline as a conveyor belt in a factory:
- Install step: Gathering raw materials (dependencies)
- Test step: Quality control check
- Build step: Manufacturing the product
- Deploy step: Shipping to customers
Each step runs independently in a fresh container, ensuring consistency and reproducibility.
Advanced Features
Matrix Builds
Need to test across multiple Node.js versions? Easy:
matrix:
NODE_VERSION:
- 18
- 20
- 22
steps:
test:
image: node:${NODE_VERSION}-alpine
commands:
- npm ci
- npm testThis creates three parallel pipelines, one for each Node.js version.
Using Secrets
Never hardcode credentials! Woodpecker has built-in secret management:
- Add secrets through the Woodpecker UI for your repository
- Reference them in your pipeline:
steps:
deploy:
image: plugins/ssh
settings:
host: example.com
username:
from_secret: ssh_username
password:
from_secret: ssh_password
script:
- ./deploy.shService Containers
Need a database for testing? Use services:
services:
postgres:
image: postgres:16
environment:
POSTGRES_DB: testdb
POSTGRES_USER: test
POSTGRES_PASSWORD: test
steps:
test:
image: node:20-alpine
environment:
DATABASE_URL: postgres://test:test@postgres:5432/testdb
commands:
- npm testThe service container runs alongside your pipeline steps, accessible by its service name (postgres in this case).
Real-World Use Cases
Continuous Deployment for a Web App
Here’s a complete pipeline for a Next.js app:
when:
- event: push
branch: [main, develop]
steps:
install:
image: node:20-alpine
commands:
- npm ci
lint:
image: node:20-alpine
commands:
- npm run lint
test:
image: node:20-alpine
commands:
- npm test
build:
image: node:20-alpine
commands:
- npm run build
when:
branch: main
deploy-staging:
image: appleboy/ssh-action
settings:
host: staging.example.com
username:
from_secret: ssh_user
key:
from_secret: ssh_key
script:
- cd /var/www/app
- git pull
- npm ci
- pm2 restart app
when:
branch: develop
deploy-production:
image: appleboy/ssh-action
settings:
host: example.com
username:
from_secret: ssh_user
key:
from_secret: ssh_key
script:
- cd /var/www/app
- git pull
- npm ci
- npm run build
- pm2 restart app
when:
branch: mainDocker Image Build and Push
Building and publishing Docker images:
steps:
build-and-push:
image: woodpeckerci/plugin-docker-buildx
settings:
registry: ghcr.io
repo: ghcr.io/yourorg/yourapp
username:
from_secret: github_username
password:
from_secret: github_token
tags:
- latest
- ${CI_COMMIT_SHA:0:8}
platforms:
- linux/amd64
- linux/arm64Woodpecker vs. Other CI/CD Tools
Woodpecker vs. Jenkins
| Feature | Woodpecker | Jenkins |
|---|---|---|
| Setup Complexity | Low | High |
| Resource Usage | Minimal | Heavy |
| Configuration | YAML | Groovy/UI |
| Container Support | Native | Plugin-based |
| Learning Curve | Gentle | Steep |
Woodpecker vs. GitHub Actions
| Feature | Woodpecker | GitHub Actions |
|---|---|---|
| Self-Hosted | Yes | Optional |
| Platform Lock-in | No | GitHub only |
| Cost | Free (self-hosted) | Limited free tier |
| Customization | Full control | Limited |
When to Choose Woodpecker
Woodpecker is an excellent choice when:
- You want full control over your CI/CD infrastructure
- You need a lightweight solution that doesn’t consume excessive resources
- You’re already using containers in your workflow
- You prefer simple, declarative configuration over complex scripting
- You want to avoid vendor lock-in with cloud providers
- You’re working with smaller teams or personal projects
Common Pitfalls and Troubleshooting
Agent Not Connecting
Problem: Woodpecker agent can’t connect to the server.
Solution: Ensure the WOODPECKER_AGENT_SECRET matches between server and agent:
$ docker logs woodpecker-agentLook for authentication errors and verify your secret configuration.
Pipeline Failing Silently
Problem: Pipeline steps complete but show no output.
Solution: Check your step configuration and ensure commands are properly formatted:
steps:
test:
image: node:20-alpine
commands:
- set -e # Exit on error
- npm testDocker Socket Permission Issues
Problem: Agent can’t access Docker socket.
Solution: Ensure proper permissions on /var/run/docker.sock or run the agent with appropriate privileges:
woodpecker-agent:
image: woodpeckerci/woodpecker-agent:latest
privileged: true # Use with caution
volumes:
- /var/run/docker.sock:/var/run/docker.sockBest Practices
1. Keep Pipelines Fast
Minimize build times by:
- Using slim Docker images (Alpine-based when possible)
- Caching dependencies between runs
- Running independent steps in parallel
steps:
lint:
image: node:20-alpine
commands:
- npm ci
- npm run lint
test:
image: node:20-alpine
commands:
- npm ci
- npm test
depends_on: [] # Run in parallel2. Use Pipeline Templates
For multiple similar projects, create reusable pipeline templates:
# .woodpecker/common.yml
variables:
- &node-install
image: node:20-alpine
commands:
- npm ci
# Then reference in your main pipeline
steps:
install:
<<: *node-install3. Implement Proper Secret Management
- Store secrets in Woodpecker’s secret management, not in your repository
- Use different secrets for different environments
- Rotate secrets regularly
4. Monitor Your Pipelines
Set up status badges in your README:
[](https://woodpecker.example.com/yourorg/yourrepo)My Experience with Woodpecker CI
I started using Woodpecker CI for my personal projects after getting frustrated with the complexity of Jenkins and the costs of cloud-based CI/CD solutions. The learning curve was surprisingly gentle – if you understand Docker and YAML, you’re basically 80% there.
What impressed me most was how little resources it consumes. I’m running Woodpecker on a small VPS alongside other services, and it barely makes a dent in memory or CPU usage. The container-based approach means every build is reproducible and isolated.
The community is also fantastic. Since it’s open-source and actively maintained, issues get addressed quickly, and there’s a growing ecosystem of plugins and integrations.
Getting Started Today
Ready to try Woodpecker CI? Here’s your action plan:
- Set up a test instance using the Docker Compose example above
- Connect your Git repository through the OAuth integration
- Create a simple
.woodpecker.ymlfile with basic build steps - Watch your first pipeline run and iterate from there
- Explore plugins and advanced features as needed
Conclusion
Woodpecker CI brings refreshing simplicity to the often-overcomplicated world of CI/CD. It’s lightweight enough to run on minimal hardware, yet powerful enough for serious production workloads. The container-native approach, clean YAML configuration, and active community make it a compelling alternative to heavyweight solutions like Jenkins or expensive cloud services.
If you’re tired of wrestling with complex CI/CD setups or paying for features you don’t need, give Woodpecker CI a try. You might be surprised how much you can accomplish with such a lightweight tool.
The future of CI/CD doesn’t have to be complicated. Sometimes, the best tool is the one that just gets out of your way and lets you focus on what matters: shipping great code.