Building a Simple Git Server with Rust and Axum
Sometimes the best projects don’t start with a plan—they start with old hardware and curiosity.
After installing antiX Linux on an old HP Pavilion dm1, I had a simple idea:
What if I could build my own Git server… using Rust?
Not a full GitHub clone—but something minimal. Something I could understand end-to-end.
This project became my way of learning Axum, Rust’s web framework, while exploring how Git actually works under the hood.
I want to mention that
The Kingdom of Aksum (c. 100–940 AD) was a powerful, wealthy ancient civilization located in modern-day northern Ethiopia and Eritrea, serving as a major trading hub between Rome, Persia, and India. Renowned for its enormous granite stelae (obelisks) and early adoption of Christianity, it was considered a major world power and developed its own native script, Ge’ez.
What We’re Building
A lightweight Git server that can:
- Initialize repositories
- Accept pushes
- Serve repositories over HTTP
- Run on low-end hardware
No UI. No complexity. Just the fundamentals.
Prerequisites
Before starting, make sure you have:
- Rust installed (
rustup) - Git installed
- A Linux machine (or WSL/macOS works too)
Step 1: Create the Project
cargo new git-server
cd git-server Add dependencies in Cargo.toml:
[dependencies]
axum = "0.7"
tokio = { version = "1", features = ["full"] }
tower = "0.4" Step 2: Basic Axum Server
Create a simple server in main.rs:
use axum::{routing::get, Router};
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/", get(root));
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000")
.await
.unwrap();
axum::serve(listener, app).await.unwrap();
}
async fn root() -> &'static str {
"Git Server Running"
} Run it:
cargo run Visit http://localhost:3000 — you should see:
Git Server Running Step 3: Create a Repository Endpoint
We’ll create an endpoint to initialize a Git repository.
use axum::{routing::post, Router};
use std::process::Command;
async fn create_repo() -> String {
let output = Command::new("git")
.args(["init", "--bare", "repos/test.git"])
.output()
.expect("failed to execute git");
if output.status.success() {
"Repository created".to_string()
} else {
"Failed to create repo".to_string()
}
} Add route:
let app = Router::new()
.route("/", get(root))
.route("/create", post(create_repo)); Step 4: Serve Repositories (Git HTTP Backend)
Git already provides a tool for serving repositories:
git http-backend
We just need to connect it to Axum.
Here’s a simplified handler:
use axum::response::IntoResponse;
async fn git_backend() -> impl IntoResponse {
let output = Command::new("git")
.env("GIT_PROJECT_ROOT", "./repos")
.env("GIT_HTTP_EXPORT_ALL", "1")
.arg("http-backend")
.output()
.expect("failed to run git backend");
String::from_utf8_lossy(&output.stdout).to_string()
} Route it:
.route("/git", get(git_backend)) Step 5: Test It Locally
- Create repo:
curl -X POST http://localhost:3000/create - Clone it:
git clone http://localhost:3000/git/test.git - Push code:
cd test
echo "hello" > README.md
git add .
git commit -m "init"
git push Running on Old Hardware
This project was designed to run on a low-spec machine.
On antiX Linux:
- Keep services minimal
- Run with
screenortmux - Use a lightweight file system layout
Rust’s performance makes it ideal for this kind of setup.
What I Learned
This project taught me more than just Axum:
- How Git actually serves repositories
- How backend services interact with system processes
- How to design minimal, focused systems
- How to build something useful with limited resources
Most importantly, it reminded me:
You don’t need complex infrastructure to build something meaningful.
What’s Next
This is just the foundation. You could extend it with:
- Authentication (SSH keys or tokens)
- A simple web UI
- Repository listing
- Logging and monitoring
- Docker deployment
Final Thoughts
Building this wasn’t about replacing GitHub.
It was about understanding the system behind it.
And sometimes, the best way to learn is to build a smaller version yourself.
If you have an old machine lying around, try it.
You might learn more from it than any tutorial and less E-waste.