Building a Self-Hosted Private AI Code Reviewer Integrated with Forgejo/Gitea Webhooks on a VPS
Introduction: The Case for Private AI in Modern DevOps
In the contemporary software development lifecycle, continuous integration and continuous deployment (CI/CD) pipelines have drastically accelerated how code is tested and delivered. However, the code review process often remains a human-intensive bottleneck. While public cloud-based AI assistants offer remarkable capabilities in automated code analysis, many enterprises and privacy-conscious development teams face a strict barrier: data compliance and intellectual property protection. Sending proprietary source code to external third-party APIs is simply not an option.
This comprehensive guide demonstrates how to establish a fully autonomous, Private AI Code Reviewer hosted entirely on your Virtual Private Server (VPS). By utilizing Forgejo or Gitea—the leading lightweight, self-hosted Git platforms—and integrating them via native Webhooks, you can construct an automated system that analyzes pull requests, detects vulnerabilities, evaluates style compliance, and posts review comments directly back to your repository interface. All of this is accomplished with complete data sovereignty and zero external API dependencies.
Architectural Overview: How the Automated Pipeline Works
To implement an efficient and secure automated review system, we must decouple the Git event listener from the heavy computational workload of the AI inference engine. The architecture consists of four primary building blocks:
- The Git Platform (Forgejo/Gitea): Triggers an HTTP POST Webhook payload whenever a developer creates or updates a Pull Request (PR).
- The Webhook Listener Server: A lightweight backend service (written in Node.js, Python, or Go) running on your VPS that listens for incoming events, validates payload signatures, and extracts the PR diff data.
- The Private AI Inference Engine: A local instance of an LLM server, such as Ollama or LocalAI, executing open-source models specifically fine-tuned for coding tasks (e.g., DeepSeek-Coder, CodeLlama, or Qwen2.5-Coder).
- The Feedback Loop: The Webhook Listener parses the AI's structured response and uses Forgejo/Gitea REST APIs to automatically post targeted inline or general review comments on the PR.
Key Benefit: By hosting every component on a single VPS or a private local network, your source code never traverses the public internet or enters external data training sets.
Prerequisites and Environment Setup
Before proceeding with the implementation, ensure your VPS meets the following minimum requirements to guarantee stable performance:
- Operating System: Ubuntu 22.04 LTS or any modern Linux distribution.
- Hardware Specifications: Minimum 4 vCPUs and 8GB RAM (16GB RAM recommended if running 7B or larger parameter models without a dedicated GPU). For faster inference, a VPS with an NVIDIA GPU (vRAM > 8GB) is ideal, though CPU-only inference with optimized models is viable for asynchronous tasks like code review.
- Software Dependencies: Docker and Docker Compose installed; administrative access to a running Forgejo or Gitea instance.
Step-by-Step Implementation
Step 1: Deploying the Private AI Inference Engine
We will use Ollama due to its minimal resource footprint and excellent support for state-of-the-art coding models. Create a docker-compose.yml file on your VPS to manage the containerized AI engine:
version: '3.8'
services:
ollama:
image: ollama/ollama:latest
container_name: ollama-ai
ports:
- "11434:11434"
volumes:
- ollama_data:/root/.ollama
restart: unless-stopped
volumes:
ollama_data:Start the container and download a high-performance, developer-focused LLM, such as DeepSeek-Coder (6.7 Billion parameters), which balances exceptional contextual code understanding with lower hardware demands:
docker compose up -d
docker exec -it ollama-ai ollama run deepseek-coder:6.7b-instructStep 2: Building the Webhook Listener and Reviewer Application
Next, we build the core automation logic. This script receives the webhook notification, fetches the repository's code diff, constructs a precise system prompt for the local LLM, and submits the review feedback. Below is a conceptual implementation utilizing Node.js and Express:
const express = require('express');
const axios = require('axios');
const app = express();
app.use(express.json());
const GITEA_API_URL = 'http://your-gitea-vps-ip:3000/api/v1';
const GITEA_TOKEN = 'your_access_token_here';
const OLLAMA_URL = 'http://localhost:11434/api/generate';
app.post('/webhook/pr-review', async (req, res) => {
const payload = req.body;
// Verify event is a pull request creation or synchronization
if (payload.action === 'opened' || payload.action === 'synchronized') {
const prIndex = payload.number;
const repoFullName = payload.repository.full_name;
res.status(202).send('Review process initiated.');
try {
// 1. Fetch the Pull Request Diff raw file data
const diffResponse = await axios.get(`${GITEA_API_URL}/repos/${repoFullName}/pulls/${prIndex}.diff`, {
headers: { 'Authorization': `token ${GITEA_TOKEN}` }
});
const prDiff = diffResponse.data;
// 2. Draft the specialized Prompt for the AI
const systemPrompt = "You are an expert, strict, Senior Software Engineer and Security Auditor. Review the following Git patch/diff file. Identify bugs, logic flaws, security vulnerabilities (like SQL Injection, XSS, or memory leaks), and severe code smells. Provide your feedback in clear, constructive bullet points. If the code is excellent, state that it is approved.";
// 3. Send payload to Local Ollama Instance
const aiResponse = await axios.post(OLLAMA_URL, {
model: "deepseek-coder:6.7b-instruct",
prompt: `${systemPrompt}\n\nHere is the Diff:\n${prDiff}`,
stream: false
});
const reviewFeedback = aiResponse.data.response;
// 4. Submit the feedback as a comment back to Forgejo/Gitea
await axios.post(`${GITEA_API_URL}/repos/${repoFullName}/pulls/${prIndex}/reviews`, {
body: `### 🤖 Automated Private AI Review Feedback\n\n${reviewFeedback}`,
event: "COMMENT"
}, {
headers: { 'Authorization': `token ${GITEA_TOKEN}`, 'Content-Type': 'application/json' }
});
console.log(`Successfully posted automated review for PR #${prIndex}`);
} catch (error) {
console.error('Error handling code review pipeline:', error.message);
}
} else {
res.status(200).send('Event ignored.');
}
});
app.listen(4000, () => console.log('Webhook Reviewer listening on port 4000'));Step 3: Configuring Webhooks in Forgejo or Gitea
With your listener service running on port 4000, you must connect it to your repository workflow:
- Navigate to your repository on your Forgejo/Gitea dashboard.
- Go to Settings > Webhooks > Add Webhook.
- Select Gitea (or Forgejo) as the webhook type.
- Set the Target URL to
http://.:4000/webhook/pr-review - Under Trigger On, select Custom Events and checkmark Pull Request events (specifically open, reopen, and synchronize).
- Save the configuration. Test the connection using the built-in 'Test Delivery' tool to confirm a successful
200 OKor202 Acceptedresponse.
Optimizing Prompt Engineering for High-Quality Code Analysis
An AI model is only as effective as the boundaries and context provided to it. To prevent the AI from generating excessive noise or criticizing irrelevant stylistic choices, refine your system prompt to prioritize actionable issues.
Consider applying structured guidelines within your prompt:
- Focus Area Categorization: Explicitly instruct the model to separate its findings into distinct categories: Critical Security Flaws, Performance Inefficiencies, and Readability Enhancements.
- False Positive Reduction: Include specific rules, such as: "Do not comment on missing documentation unless it leaves a major API undocumented. Do not comment on formatting if it adheres to standard linting patterns."
- Language Awareness: Adjust the model context depending on the primary languages used in the repository to leverage language-specific best practices (e.g., memory management in C/C++, concurrent patterns in Go, or async optimization in JavaScript).
Security and Performance Best Practices
Running an autonomous AI code reviewer on a VPS introduces a unique set of operational considerations. Implementing the following protections prevents service degradation and system exposure:
Webhook Authentication and Security
Never expose your Webhook listener endpoint completely to the public web without verification. Utilize the Secret String feature in Forgejo/Gitea webhooks. Validate the X-Gitea-Signature header in your Node.js application using an HMAC-SHA256 hash calculation to confirm that incoming requests genuinely originate from your trusted Git server.
Resource Isolation and Rate Limiting
Inference pipelines consume massive CPU/GPU resources. If multiple developers push code simultaneously, a single VPS could quickly exhaust its memory, resulting in system crashing or frozen CI/CD processes. Implement a job queue mechanism (such as BullMQ or a basic in-memory array) inside your listener server. This guarantees that your local AI engine processes code diffs sequentially rather than concurrently, maintaining predictable infrastructure load.
Conclusion: Empowering Your Engineering Workflow
By establishing a private, self-hosted AI Code Reviewer, your business gains the continuous vigilance of automated code scanning without sacrificing code privacy or incurring expensive monthly SaaS subscriptions. The combination of Forgejo/Gitea's lightweight event management, simple webhooks, and local LLM execution proves that enterprise-grade DevOps automation is entirely achievable on affordable, independent infrastructure. As open-source coding models continue to advance, your self-hosted pipeline will naturally become faster, more precise, and increasingly integrated into your engineering success.
