Back to Blog Building a Simple Git Server with Rust and Axum
RustAxumGitSelf-HostingLinuxBackend Development

Building a Simple Git Server with Rust and Axum

2 nov, 2025
4 min read
...
views

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

  1. Create repo:
curl -X POST http://localhost:3000/create
  1. Clone it:
git clone http://localhost:3000/git/test.git
  1. 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 screen or tmux
  • 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.