DEV Community

Elder Fernandes
Elder Fernandes

Posted on Originally published at selfhoststack-8z4.pages.dev

Self-Hosted CI/CD in 2026: Ditch GitHub Actions Minute Caps with Woodpecker CI & Gitea Actions

Self-Hosted CI/CD in 2026: Ditch GitHub Actions Minute Caps with Woodpecker CI & Gitea Actions

If your team runs automated test suites, Docker image builds, and multi-stage deployments, cloud CI/CD pricing has a way of creeping up on you.

On GitHub Actions, free tiers evaporate quickly once you have active pull request pipelines, matrix builds, or heavy integration test suites. Paying $0.008 per Linux minute (or higher for larger compute runners / macOS) means an active team of 5 developers can easily spend $150 to $400/month just waiting on build queues and compute charges.

Meanwhile, a single $6 to $12/month Hetzner or DigitalOcean VPS provides dedicated 4-core CPU performance, 8 GB RAM, NVMe disk caching, and unlimited build minutes 24/7.

In this guide, we'll look at the modern self-hosted CI/CD landscape in 2026, comparing Woodpecker CI and Gitea Actions, with production-ready Docker Compose configurations and caching strategies.


The True Cost of Cloud CI/CD vs. Dedicated Self-Hosted Runners

Metric GitHub Actions (Cloud) Woodpecker CI / Gitea Actions on VPS
Pricing Model Per-minute billing ($0.008/min+) Flat $5.50 – $12/month VPS
Concurrency Limits Throttled by subscription tier Bound only by CPU/RAM
Docker Layer Caching Slower network artifact caching Blazing local NVMe layer cache
Secret & VPC Access Requires external tunnel / OpenID Direct local network / Tailscale VPC
Resource Allocation Shared 2-vCPU instances Dedicated 4–8 vCPUs

Top Self-Hosted CI/CD Contenders in 2026

1. Woodpecker CI (The Modern Drone Fork)

  • Why it shines: Ultra-lightweight, native multi-pipeline support, modular plugin ecosystem, and zero telemetry. It connects effortlessly to GitHub, GitLab, Gitea, or Forgejo.
  • Resource usage: Server: ~60 MB RAM. Agent: ~40 MB RAM.

2. Gitea Actions (Native GitHub-Compatible Workflows)

  • Why it shines: Uses the act_runner engine, allowing you to use existing .github/workflows/*.yaml syntax directly without rewriting your pipeline manifests.
  • Resource usage: Runner daemon: ~80 MB RAM.

Production Setup: Woodpecker CI with Docker Compose

Here is a turnkey, production-grade docker-compose.yml to run Woodpecker CI Server and Agent with automatic SSL support via Traefik or reverse proxy.

version: '3.8'

services:
  woodpecker-server:
    image: woodpeckerci/woodpecker-server:latest
    container_name: woodpecker-server
    restart: unless-stopped
    ports:
      - "8000:8000"
      - "9000:9000" # gRPC communication with agents
    environment:
      - WOODPECKER_OPEN=true
      - WOODPECKER_HOST=https://ci.yourdomain.com
      - WOODPECKER_SERVER_ADDR=:9000
      - WOODPECKER_GRPC_SECRET=${WOODPECKER_SECRET} # Generate with: openssl rand -hex 32
      # GitHub OAuth Integration
      - WOODPECKER_GITHUB=true
      - WOODPECKER_GITHUB_CLIENT=${GITHUB_CLIENT_ID}
      - WOODPECKER_GITHUB_SECRET=${GITHUB_CLIENT_SECRET}
    volumes:
      - woodpecker-server-data:/var/lib/woodpecker
    networks:
      - ci-network

  woodpecker-agent:
    image: woodpeckerci/woodpecker-agent:latest
    container_name: woodpecker-agent
    restart: unless-stopped
    depends_on:
      - woodpecker-server
    environment:
      - WOODPECKER_SERVER=woodpecker-server:9000
      - WOODPECKER_SECRET=${WOODPECKER_SECRET}
      - WOODPECKER_MAX_WORKFLOWS=4 # Concurrent builds
      - DOCKER_HOST=unix:///var/run/docker.sock
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - ci-network

volumes:
  woodpecker-server-data:

networks:
  ci-network:
    driver: bridge
Enter fullscreen mode Exit fullscreen mode

Example .woodpecker.yaml Pipeline

pipeline:
  test:
    image: node:20-alpine
    commands:
      - npm ci
      - npm run lint
      - npm run test:coverage

  build-docker:
    image: plugins/docker
    settings:
      repo: registry.yourdomain.com/app
      tags: [latest, "${CI_COMMIT_SHA:0:7}"]
      username:
        from_secret: docker_username
      password:
        from_secret: docker_password
    when:
      branch: main
      event: push
Enter fullscreen mode Exit fullscreen mode

Essential Caching & Build Optimization Strategies

  1. Local Docker Registry Mirror: Run a local registry proxy (registry:2) on your build server to cache base images (alpine, node, golang, python) instantly across jobs.
  2. Persistent Volumes for Dependencies: Mount host directories for npm (~/.npm), Go (/go/pkg/mod), and Maven caches to reduce test runtimes from 4 minutes to 15 seconds.
  3. RAM Disk for Temporary Build Artifacts: Mount /tmp as a tmpfs volume to maximize IOPS during compile-heavy steps.

Recommended Hardware & Hosting

For optimal CI/CD performance with fast NVMe drives:

Check our VPS Hosting Guide & Hardware Benchmarks to compare IOPS, bandwidth, and CPU specs across providers.


Explore More Alternatives

Looking to replace other expensive dev tools?


🚀 Want the complete, pre-hardened self-hosted setup?

Grab the Self-Hosted Starter Stack Pack ($29) — featuring production Docker Compose manifests, Traefik v3 SSL automation, automated Restic offsite backup scripts, and a security hardening checklist for your VPS.

Top comments (0)