Gitea Runners Pipeline

infrastructure-engineering

Gitea Runners Pipeline

Introduction

This document explains how my CI/CD pipeline is structured using Gitea runners inside my homelab environment. The goal is to create a fully self-hosted development workflow where code can be pushed, built, tested, and deployed automatically without relying on external CI services.

My setup is built around a Kubernetes (K3s) cluster running on a small rack of machines, including Raspberry Pi nodes and a dedicated x86 machine used for heavier workloads. In addition, I use a separate development machine with an RTX 3090 for local AI workloads and testing before deployment. Gitea acts as the central source control system, while runners handle automation tasks across the cluster.


Pipeline Overview

My CI/CD pipeline is designed to be lightweight, distributed, and reproducible across my homelab.

1. Code Push

  • Developers (me or automated agents) push code to a Gitea repository.
  • Branch-based workflows are used (main, dev, feature branches).

2. Gitea Trigger

  • A webhook triggers the CI pipeline when a push event occurs.
  • The event is picked up by a Gitea runner registered in the cluster.

3. Runner Execution (K3s Cluster)

  • Runners are deployed as pods inside my Kubernetes (K3s) cluster.
  • Tasks executed include:
    • Dependency installation
    • Unit tests
    • Linting
    • Build steps (Docker images or binaries)
  • Lightweight workloads run on Raspberry Pi nodes.
  • Heavier builds are scheduled on x86 nodes for performance efficiency.

4. Artifact Build & Storage

  • Successful builds generate Docker images or packaged artifacts.
  • Images are pushed to a private container registry inside the cluster.
  • Version tags follow commit SHA or semantic versioning.

5. Deployment Stage

  • If tests pass, the pipeline triggers a deployment step.
  • Kubernetes manifests or Helm charts are applied automatically.
  • Services are rolled out using rolling updates to avoid downtime.

6. Observability

  • Logs from runners are collected and stored for debugging.
  • Cluster monitoring is handled through internal tooling and dashboards.
  • Failed builds are traced back through Gitea logs and CI output.

Architecture Notes

This system is designed to act as the “glue” of my infrastructure:

  • Gitea → Source of truth for all code and automation triggers
  • K3s Cluster → Execution layer for builds and deployments
  • Raspberry Pi Nodes → Lightweight distributed CI workers
  • x86 Machine (Dev / RTX 3090 box) → Heavy compute + local AI experimentation
  • Container Registry → Stores versioned builds for deployment

This setup allows me to iterate quickly while keeping everything fully self-hosted and portable.


Conclusion

This Gitea runner pipeline turns my homelab into a full production-style DevOps environment. Instead of relying on external CI/CD platforms, everything runs inside my own infrastructure, giving me full control over build processes, deployment logic, and compute distribution.

It also creates a strong foundation for future expansion, such as AI-driven CI agents, automated testing pipelines, and multi-service deployment systems across the cluster. As the system evolves, Gitea continues to act as the central orchestration layer that connects development, automation, and deployment into one unified workflow.

Case Study

In Progress

Bible Verse — Case Study

Production SaaS Platform · Full-Stack · Founder & Sole Engineer

A domain-driven SaaS platform with five independently scalable system boundaries: scripture content delivery, RAG-backed AI study, real-time community interaction, async media processing, and infrastructure services — built and operated end-to-end.

Our Results

37K+
Verses Indexed
5
AI Models
5
Bounded Domains
3
Job Queues

How We Built It

  • RAG pipeline grounding AI responses in actual scripture rather than model memory
  • Hybrid Llama / OpenAI routing — local inference for cost, API fallback for quality at the edge
  • Non-blocking media processing — FFmpeg jobs enqueued via BullMQ, API never waits on transcoding
  • Cross-instance real-time consistency via Redis pub/sub behind WebSocket and WebRTC layers

Lessons Learned

  • Domain boundaries enforced at the service layer prevent coupling long before scale demands microservices.
  • RAG retrieval quality matters more than model size — better embeddings outperform a larger model on poor context.
  • Async queue design should be first-class, not bolted on; BullMQ worker isolation saved the request path repeatedly.

Stack

Nuxt 3TypeScriptNitroPostgreSQLPrismaRedisBullMQWeaviateMinIOFFmpegWebRTCWebSocketsLlama 3.2OpenAI APIKubernetes
View Full Case Study

Written by

Full-Stack Engineer & Systems Architect

5+ years building production systems · AI, Backend & Infrastructure · Founder of Bible Logic

Full-stack engineer with 5+ years of hands-on experience designing and shipping production systems — from Nuxt 3 frontends and Nitro APIs to self-hosted Kubernetes clusters, RAG pipelines, and real-time AI applications. Everything I write comes from systems I've designed, deployed, and operated in production.

5+ Years Experience AI Systems Specialist Kubernetes & Infrastructure
Nuxt 3TypeScriptPostgreSQLKubernetesRAG / LLMWebRTCAWS IVSRedis