I built my own Git Server

Ansari
Category : Server
Time to read : 5 mins
Wait, wait.
This is not one of those “I wrote my own version of Git” posts. I’m not that brave, and I enjoy sleeping at night 😐.
All I did was host my own Git repos on a VPS under my own fuckng domain. Git already did the hard work, I just gave it a polished home.
Completely unnecessary? Probably. Because thats what github, bitbucket, gitlab… these do right ? Yes absolutely, Even I still use GitHub. This wasn’t some rebellion against the tech overlords. It started with a single dangerous thought:
“I wonder if I could just host my own repos?”
A few hours later, I had a tiny Git server — git.ansari.wtf — happily accepting pushes (ssh), serving public clones and I couldn’t stop smiling.

The Familiar little green-and-gray world
Before I hosted a single repo, I had one very important, slightly ridiculous requirement:
It had to look like GitHub.
Not because I needed GitHub. Not because I was trying to replace it. I just wanted that familiar green-gray github world where you open a repo, click around, read files, and pretend you’re reviewing serious open-source code while actually judging someone’s README formatting.
The backend could be held together with duct tape for all I cared. I wanted the nice browsing experience.

So, naturally, I did what every developer does when they have a tiny idea and absolutely no plans to stop: I opened 47 browser tabs and disappeared into an internet rabbit hole. Turns out there’s a whole cottage industry of static Git page generators turning boring old Git repositories into pretty, browsable websites. Tiny projects solving very specific problems that most people will never know exist which, honestly is my favorite category of software.
While digging through this pile of “nobody asked for this but I’m so glad it exists” tools, I stumbled on gitmal a static page generator for repos. Written in Go, which happens to be my current programming language crush, so naturally I didn’t just use it. I cracked it open and started reading the source like it owed me money.
A little source-code archaeology turned into actual improvements. I ended up opening a PR to make some improvements, because once you start thinking “I wonder if I can tweak this…”, there is no coming back.Then I took my fork and gave it the full makeover treatment. Until it finally looked like something I’d be proud to send someone a link to.
The actual usage is embarrassingly simple: point it at a folder of repos, and it spits out clean, browsable HTML pages. If all you want is a portfolio to show off your projects, this step alone is the whole project. You are done here bubyee, just buy a cheap VPS, harden it a little, slap Caddy or Nginx or fkng Apache in front to serve the static files, done. You could stop here and still have something legit.
But no no no, I wanted more..

Because then I had another completely unnecessary thought:
“What if I made it feel even more like a real Git server?”
Because Just Looking Isn’t Enough
The static site was cool. I could open my browser, click through repos, admire my little GitHub shaped creation…
The obvious question came : “Okay, but can anyone actually clone this thing?”
Because a Git server that only lets people look at code is basically a museum. I wanted the full GitHub cosplay experience. Turns out this is one extra step away: run git update-server-info inside the repo, which generates the info/refs and objects/info/packs files Git needs to serve a clone over dumb HTTP. Voilà that’s it. Now your repo is clonable from your domain. Except when I tried it, the clone experience wasn’t as expected. It did the job but no progress, no feedback. Just a terminal cursor staring back at me like it knew something I didn’t. Meanwhile, GitHub gives you that nice live progress output:

So for the smooth version it needs something smarter than static files. It needs a server that can actually execute git-http-backend live, so you get that real-time transfer feedback instead of a clone command staring blankly back at you.
My little static setup needed to grow up. The problem? Caddy doesn’t speak CGI.
Which makes sense. Caddy is elegant, modern. It probably looks at CGI and says, “we don’t do that anymore.” So I added fcgiwrap as the middleman basically a translator between Caddy and Git's HTTP backend.
Is this the cleanest architecture? Probably not.
Is there a better way? Almost definitely. If you know one, please tell me. I will happily accept the correction and pretend I planned this learning experience all along.

Anyways now it worked. Now the repos have a proper browsing experience, clones behave like actual Git clones, and with a little SSH configuration, I can push straight to my own server.
And that’s it. That’s the whole fkng thing. A weekend, several small humiliations, one PR upstream, and a Git server that has absolutely no reason to exist except that I wanted it to, and now it does.
If you’re curious, you can take a look at it: git.ansari.wtf
Just… please don’t spam it or roast it too hard. It’s a tiny server running on a dream, some CSS, and questionable engineering decisions.