This is a simple implementation of a git proxy in Java. This is a possible successor to finos/git-proxy which is written in Node.
This project is a multi-module Gradle project:
Shared library containing all proxy logic:
- Servlet filters for the transparent proxy path (
/proxy/...) - Store-and-forward push pipeline using JGit ReceivePack hooks (
/push/...) - Provider interfaces and implementations (GitHub, GitLab, Bitbucket)
- Push audit store abstraction with JDBC and MongoDB backends
- Git protocol utilities and commit inspection
Standalone Jetty server — the primary runnable module. No Spring dependency.
./gradlew :jgit-proxy-jetty:run
./gradlew :jgit-proxy-jetty:stopPlaceholder for a future Spring Boot variant.
HTTP request is forwarded to the upstream Git server. Servlet filters validate commits inline and reject the push before it reaches the upstream. Client receives a git sideband error message.
git clone http://localhost:8080/proxy/github.com/owner/repo.git
git push http://localhost:8080/proxy/github.com/owner/repo.gitPush objects are received locally using JGit's ReceivePack. A hook chain validates the commits and streams real-time feedback via git sideband before forwarding to the upstream. Each state transition is persisted as an event-log entry.
git clone http://localhost:8080/push/github.com/owner/repo.git
git push http://localhost:8080/push/github.com/owner/repo.gitAll pushes through the store-and-forward path are recorded as an event log. Each state transition (RECEIVED → APPROVED → FORWARDED, or BLOCKED/ERROR) is written as a separate row, enabling full push history and reporting.
| Type | Config value | Notes |
|---|---|---|
| In-memory (simple) | memory |
No SQL schema, data lost on restart |
| H2 in-memory | h2-mem |
SQL schema, data lost on restart. Default. |
| H2 file | h2-file |
Persistent, zero external dependencies |
| SQLite | sqlite |
Persistent, zero external dependencies |
| PostgreSQL | postgres |
Production-grade |
| MongoDB | mongo |
Compatible with git-proxy Node.js data model |
Set in git-proxy.yml (or override in git-proxy-local.yml):
# H2 in-memory (default)
database:
type: h2-mem
# H2 file
database:
type: h2-file
path: ./.data/gitproxy # H2 appends .mv.db
# SQLite
database:
type: sqlite
path: ./.data/gitproxy.db
# PostgreSQL
database:
type: postgres
host: localhost
port: 5432
name: gitproxy
username: gitproxy
password: gitproxy
# MongoDB
database:
type: mongo
url: mongodb://gitproxy:gitproxy@localhost:27017
name: gitproxyA docker-compose.yml is provided for local development with PostgreSQL and MongoDB (includes Adminer and Mongo Express web UIs):
docker compose up -d postgres # port 5432, Adminer on 8082
docker compose up -d mongo # port 27017, Mongo Express on 8081YAML-based configuration loaded from git-proxy.yml and git-proxy-local.yml (local file takes priority):
server:
port: 8080
database:
type: h2-mem
git-proxy:
providers:
github:
enabled: true
gitlab:
enabled: true
bitbucket:
enabled: true
filters:
whitelists:
- enabled: true
order: 1100
operations: [FETCH, PUSH]
providers: [github]
slugs:
- owner/repoEnvironment variable overrides use the GITPROXY_ prefix:
GITPROXY_SERVER_PORT=9090GITPROXY_PROVIDERS_GITHUB_ENABLED=false
See jgit-proxy-jetty/CONFIGURATION.md for full configuration reference.
./gradlew build
./gradlew :jgit-proxy-jetty:build./gradlew :jgit-proxy-jetty:run # starts server (PID tracked for stop)
./gradlew :jgit-proxy-jetty:stop # graceful stop via PID fileTest scripts in the repo root exercise both proxy modes end-to-end. They require a running server and a ~/.github-pat file with a GitHub personal access token.
# Store-and-forward mode
bash test-push-pass.sh # pushes that should succeed
bash test-push-fail.sh # pushes that should be rejected by validation
# Transparent proxy mode
bash test-proxy-pass.sh
bash test-proxy-fail.sh

