Back to articles
Technology Insight

Building a 100% Automated GitOps Infrastructure on a Linux VPS using Gitea, Woodpecker CI, and Renovate Bot

May 29, 2026

Introduction: The Imperative of Automation in Modern Infrastructure

In the contemporary digital landscape, engineering efficiency and infrastructure reliability are paramount to business success. Traditional deployment workflows, often characterized by manual interventions and fragmented scripts, present significant operational risks. These include configuration drift, prolonged recovery times, and increased security vulnerabilities. To mitigate these challenges, the industry has shifted toward GitOps—an operational framework that takes DevOps best practices used for application development, such as version control, collaboration, compliance, and CI/CD, and applies them to infrastructure automation.

While enterprise solutions like GitLab, GitHub Enterprise, and cloud-native tools offer robust GitOps capabilities, they often come with prohibitive licensing fees, resource-heavy architectures, and data privacy concerns. For small-to-medium enterprises (SMEs) and dedicated engineering teams seeking a lean, cost-effective, and highly performant alternative, a self-hosted stack on a Linux VPS provides the ideal solution. This comprehensive guide outlines how to architecture and build a 100% automated GitOps infrastructure by seamlessly integrating Gitea, Woodpecker CI, and Renovate Bot.

The Core Architectural Pillars

Before diving into the technical implementation, it is crucial to understand the distinct role each component plays within this automated ecosystem:

  • Gitea (The Git Core): A lightweight, self-hosted Git service written in Go. It provides a robust, low-resource alternative to GitHub or GitLab, acting as the single source of truth for both application code and infrastructure declarations.
  • Woodpecker CI (The Automation Engine): A community-driven fork of Drone CI. Woodpecker utilizes a container-first design, executing pipeline steps within isolated Docker containers. Its minimal footprint and asynchronous agent architecture make it perfect for running on restricted VPS environments.
  • Renovate Bot (The Dependency Guardian): An automated dependency management tool that scans repositories for outdated versions (Docker tags, Helm charts, npm packages, etc.) and automatically generates Pull Requests to keep the infrastructure secure and up-to-date.

By combining these three tools, we establish a closed-loop system where infrastructure is declared as code, tested and deployed automatically upon code changes, and proactively maintained against software obsolescence.

Phase 1: Setting Up the Foundation on Linux VPS

The first phase requires provisioning a standard Linux Virtual Private Server (VPS)—ideally running Ubuntu 24.04 LTS or Debian 12—with at least 2 vCPUs and 4GB of RAM. The fundamental prerequisite for our lightweight stack is a containerized runtime engine. We will use Docker and Docker Compose to ensure isolation and easy portability.

Step 1.1: Environment Initialization

Connect to your VPS via SSH and execute the following commands to update the system and install Docker:

sudo apt update && sudo apt upgrade -y
sudo apt install -y curl git docker.io docker-compose-plugin
sudo systemctl enable --now docker

Step 1.2: Docker Compose Configuration

We will construct a unified docker-compose.yml file to orchestrate our GitOps foundation. This file defines the networks, volumes, and service configurations for Gitea and Woodpecker CI.

version: '3.8'

networks:
  gitops-net:
    driver: bridge

volumes:
  gitea-data:
  woodpecker-server-data:
  woodpecker-agent-data:

services:
  gitea:
    image: gitea/gitea:1.21
    container_name: gitea
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - GITEA__database__DB_TYPE=sqlite3
    volumes:
      - gitea-data:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "3000:3000"
      - "2222:22"
    networks:
      - gitops-net
    restart: always

  woodpecker-server:
    image: woodpeckerci/woodpecker-server:v2.1
    container_name: woodpecker-server
    volumes:
      - woodpecker-server-data:/var/lib/woodpecker
    ports:
      - "8000:8000"
    environment:
      - WOODPECKER_GITEA=true
      - WOODPECKER_GITEA_URL=http://gitea:3000
      - WOODPECKER_HOST=http://your-vps-ip:8000
    networks:
      - gitops-net
    restart: always

  woodpecker-agent:
    image: woodpeckerci/woodpecker-agent:v2.1
    container_name: woodpecker-agent
    command: agent
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - WOODPECKER_SERVER=woodpecker-server:8000
    networks:
      - gitops-net
    restart: always
Note: For production deployments, it is highly recommended to place an HTTP reverse proxy like Nginx, Caddy, or Traefik in front of these services to handle SSL/TLS encryption via Let's Encrypt.

Phase 2: Configuring the Gitea and Woodpecker Integration

Once the containers are operational (via docker compose up -d), access the Gitea web interface at http://your-vps-ip:3000 to complete the initial setup wizard. Create your admin account, which will serve as the root administrator for your GitOps ecosystem.

Step 2.1: Creating an OAuth2 Application

To enable secure, seamless authentication between Woodpecker CI and Gitea, navigate to Site Administration > Applications in Gitea and generate a new OAuth2 Application:

  1. Application Name: Woodpecker CI
  2. Redirect URI: http://your-vps-ip:8000/authorize

Save the generated Client ID and Client Secret. Update your docker-compose.yml file under the woodpecker-server environment section with these keys:

- WOODPECKER_GITEA_CLIENT=your_client_id
- WOODPECKER_GITEA_SECRET=your_client_secret

Restart the Woodpecker services using docker compose up -d woodpecker-server to apply the configuration. You can now log into Woodpecker CI using your Gitea credentials.

Phase 3: Setting Up the Infrastructure as Code (IaC) Repository

With our version control and CI engine linked, we can establish our GitOps repository structure. Create a new repository in Gitea named infrastructure-live. This repository will hold the declarative state of our production environment.

The Declarative Directory Layout

A structured repository prevents configuration clutter and allows Woodpecker pipelines to target specific environments efficiently:

infrastructure-live/
├── .woodpecker/
│   └── deploy.yaml
├── apps/
│   └── web-app/
│       ├── docker-compose.prod.yml
│       └── renovate.json
└── README.md

Defining the Woodpecker Continuous Deployment Pipeline

Create the .woodpecker/deploy.yaml file inside your repository. This pipeline is triggered automatically whenever a push event occurs on the main branch, applying the changes directly to the VPS hosting environment.

pipeline:
  validate:
    image: linter/compose-linter:latest
    commands:
      - docker-compose -f apps/web-app/docker-compose.prod.yml config

  deploy:
    image: appleboy/drone-ssh
    settings:
      host:
        from_secret: ssh_host
      username:
        from_secret: ssh_username
      key:
        from_secret: ssh_private_key
      port: 22
      script:
        - cd /opt/gitops/apps/web-app
        - git pull origin main
        - docker compose -f docker-compose.prod.yml up -d --remove-orphans
    when:
      branch: main
      event: push

In the Woodpecker UI, navigate to the repository settings and add the secrets referenced above (ssh_host, ssh_username, and ssh_private_key) to allow the runner to securely connect back to the VPS host and initiate container updates.

Phase 4: Achieving 100% Automation with Renovate Bot

The true power of this GitOps infrastructure lies in its ability to self-maintain. Manually monitoring Docker image registries or Helm charts for security updates creates cognitive load and vulnerabilities. Renovate Bot solves this by turning updates into automated Pull Requests.

Step 4.1: Creating the Renovate Configuration

Add a renovate.json file to the root or application directory within your repository to define the bot's behavior:

{
  "$schema": "[https://docs.renovatebot.com/renovate-schema.json](https://docs.renovatebot.com/renovate-schema.json)",
  "extends": [
    "config:recommended"
  ],
  "platform": "gitea",
  "endpoint": "http://gitea:3000/api/v1",
  "automerge": true,
  "major": {
    "automerge": false
  },
  "packageRules": [
    {
      "matchPackagePatterns": ["*"],
      "pinDigests": false
    }
  ]
}

This configuration instructs Renovate to automatically merge patch and minor version updates if your Woodpecker validation pipelines pass successfully, while reserving major version changes for manual review via Pull Requests.

Step 4.2: Scheduling Renovate Executions via Woodpecker Cron

To keep the system automated without relying on external SaaS triggers, we configure a periodic cron job within Woodpecker CI to spin up Renovate Bot daily. Create .woodpecker/renovate.yaml:

pipeline:
  renovate:
    image: renovate/renovate:37
    environment:
      - RENOVATE_PLATFORM=gitea
      - RENOVATE_ENDPOINT=http://gitea:3000/api/v1
      - RENOVATE_TOKEN=from_secret:gitea_renovate_token
      - RENOVATE_AUTODISCOVER=true
    when:
      event: cron
      cron: "nightly"

Generate a Personal Access Token in Gitea under your account profile settings and add it to Woodpecker as gitea_renovate_token. Set up a Cron schedule named nightly in the Woodpecker repository panel configured to run at 0 2 * * *.

Business Benefits and Operational Impact

Implementing this lightweight, 100% automated GitOps stack provides distinct operational and strategic advantages for engineering groups:

Operational Aspect Traditional VPS Method Gitea + Woodpecker + Renovate GitOps Stack
Deployment Safety Manual SSH commands, high error margin. Declarative definitions validated via containerized pipelines.
Resource Overhead Low, but unmonitored and untraceable. Extremely minimal; total memory usage under 1.5GB RAM.
Dependency Maintenance Reactive; updates happen only after critical failures. Proactive; nightly automated scanning and safe auto-merging.
Infrastructure Audit Non-existent; logs must be manually parsed. Perfect tracking via the Git commit history timeline.

Conclusion: Embracing High-Velocity, Zero-Trust Operations

By leveraging the collective capabilities of Gitea, Woodpecker CI, and Renovate Bot, we successfully eliminate manual friction from the infrastructure lifecycle. Security vulnerabilities are instantly patched, manual configuration drift is structurally avoided, and updates are continually validated through automated regression testing pipelines—all contained within an incredibly lightweight, budget-friendly VPS footprint.

For technology leaders and system architects, embracing this self-hosted GitOps pipeline translates directly to improved developer velocity, minimal operational overhead, and absolute sovereignty over enterprise data and infrastructure code.

Building a 100% Automated GitOps Infrastructure on a Linux VPS using Gitea, Woodpecker CI, and Renovate Bot | DPTCloud