I Got Tired of GitHub Being Down, So I Built My Own Git Platform

"GitHub is down again." That one Slack message. At 2 AM. Right before a production deploy. That was the last straw.

The Incident That Started Everything

It was a regular Wednesday night. I had a hotfix ready. CI was green locally. All I needed was to push, trigger the pipeline, and ship.

Then GitHub decided it didn't exist anymore.

No push. No pull. No Actions. Nothing. Just a sad little status page telling me "We're investigating an incident affecting Git operations." Cool. Super helpful. I'll just sit here and watch my deploy window close.

I've been a GitHub user for years. I love it, genuinely. But that night, staring at that status page, I kept thinking — why am I this dependent on a single platform I have zero control over?

So I did what any sleep-deprived developer does at 2 AM.

I opened a new terminal and typed mkdir OpencodeHub.

What Is OpenCodeHub?

OpenCodeHub is a fully self-hosted Git platform I built from scratch. Think GitHub — but running on your server, under your control, with your rules.

No more status pages. No more downtime surprises. No more "we're investigating."

The tagline I eventually landed on:

"A modern, self-hosted Git platform for teams that want speed, control, and clean workflows."

But honestly? The real tagline is: "I was angry and I had a weekend."

The Tech Stack (Because You're Going to Ask)

I didn't want to reinvent every wheel. I wanted to build something I'd actually enjoy maintaining. So I made some deliberate choices:

Layer | Choice
Framework | Astro 4.x (SSR, Node standalone)
UI | React 18 + Tailwind CSS + Radix UI
Database | Drizzle ORM (PostgreSQL, SQLite, Turso)
Auth | JWT + bcryptjs + TOTP + OAuth (arctic)
Git | Native git CLI + simple-git + isomorphic-git
SSH Server | ssh2 library
CI/CD | Dockerode (Docker API)
Queue | BullMQ + Redis
CLI | Commander.js + Inquirer

Why Astro? Because I wanted SSR without drowning in a React SPA for everything. Astro lets me drop React components exactly where I need them. It's been a genuinely pleasant choice — fast builds, clean routing.

Why Drizzle? Because Prisma was too opinionated for what I needed and raw SQL makes me sad at 3 AM. Drizzle is just TypeScript all the way down. I can switch between PostgreSQL for production, SQLite for local dev, and Turso for edge deployments. That flexibility mattered.

Features I Actually Shipped

This wasn't a weekend toy that I abandoned. Here's what's actually working:

Core Git Platform

HTTP + SSH git push/pull — yes, real SSH on port 2222, not just HTTPS

Pull Requests — comments, reviews, drafts, approvals, suggested changes

Issues — labels, milestones, project boards

Wiki — repository wiki with full revision history

Organizations — teams, collaborators, granular repository settings

Branch Protection — required reviews, status checks, push restrictions

The Thing I'm Most Proud Of: Stacked PRs

If you've ever used Graphite, you know the power of stacked PRs. Instead of one monolithic 3,000-line PR that nobody wants to review, you break your work into a clean stack of focused, reviewable pieces.

I built this into OpenCodeHub natively — both in the web UI and the CLI.

# Create a stack
och stack create feature/auth-step-1

# Submit the whole stack for review
och stack submit

# Keep it in sync as you iterate
och stack sync

This alone was worth building the whole thing.

CI/CD Pipelines

I made the pipelines GitHub Actions-compatible. Same YAML syntax. Same structure. The idea was: if you're migrating from GitHub, your workflows should just... work. No rewriting everything from scratch.

The runner uses Docker via Dockerode under the hood. Each job gets its own container. Clean, isolated, reproducible.

AI Code Review

I added AI-powered code review that runs before human reviewers even see the PR. It catches the obvious stuff — security issues, logic bugs, style inconsistencies — so human review can focus on architecture and intent.

The Merge Queue

Stack-aware merge queue with speculative builds and priority lanes. If you have a stack of 5 PRs, the queue knows about their dependencies and builds them intelligently. No more merge conflicts from PRs stepping on each other.

140+ REST API Routes + GraphQL

# Create a repo
curl -X POST http://localhost:4321/api/repos \
-H "Authorization: Bearer <token>" \
-d '{"name":"my-project","visibility":"public"}'

# List pull requests
curl http://localhost:4321/api/repos/alice/my-project/pulls \
-H "Authorization: Bearer <token>"

There's also a full GraphQL endpoint and an auto-generated OpenAPI spec. Because I hate undocumented APIs as much as the next person.

The Architecture

Clients (Browser / Git CLI / och CLI)
│
▼
OpenCodeHub Platform (Astro SSR + React)
├── Web UI
├── REST API (140+ routes)
├── GraphQL Endpoint
├── Git HTTP Server
└── SSH Git Server (port 2222)
│
▼
Persistence Layer
├── PostgreSQL / SQLite / Turso (Drizzle ORM)
├── Redis (sessions, queues, caching)
└── Pluggable Storage (S3, GCS, Azure, local…)

Four separate runtime processes keep things clean:

Process | Command | Purpose
Main App | npm run dev | Web UI + API + Git HTTP
SSH Git | npm run git:start | SSH git push/pull
Worker | npm run worker:start | Background jobs
Runner | npm run runner:start | CI/CD pipeline execution

Getting It Running (Seriously, 5 Minutes)

# Clone it
git clone https://github.com/swadhinbiswas/OpencodeHub.git
cd OpencodeHub

# Configure
cp .env.example .env
# Edit .env with your settings

# Start everything
docker-compose up -d

# Create your admin user
docker-compose exec app bun run scripts/seed-admin.ts

# Open it
open http://localhost:4321

That's it. You now have your own Git platform running locally.

For production you'll want PostgreSQL over SQLite, Redis, HTTPS via Nginx or Caddy, and external storage like S3 or MinIO. The deployment guide covers all of that, but the bones are solid out of the box.

The CLI (och)

I published the companion CLI as opencodehub-cli on npm:

npm install -g opencodehub-cli

# Authenticate against your instance
och auth login --url http://your-server.com

# The interactive cockpit — my personal favorite
och focus

20+ command groups covering stacks, merge queues, repos, issues, and more. Because clicking through a UI when you're deep in a terminal session is a crime.

What I Learned Building This

1. SSH is not that scary. I put off implementing SSH git for weeks because I thought it would be brutal. The ssh2 library made it surprisingly manageable. The tricky part was git's internal protocol, not SSH itself.

2. Drizzle ORM is criminally underrated. Type-safe queries, multiple database backends, migrations that don't feel like a punishment. I'm a convert.

3. BullMQ + Redis is the right answer for background jobs. I tried doing things without a proper queue first. That was a mistake. BullMQ is robust and the developer experience is clean.

4. Spec compatibility matters more than I thought. Making the CI pipelines GitHub Actions-compatible was extra work upfront, but it means people can actually migrate without a complete rewrite. That was the right call.

5. Storage adapters deserve abstraction from day one. I built the abstract StorageAdapter pattern early and it's paid off. I support 8+ backends — S3, GCS, Azure, Google Drive, OneDrive, Dropbox, Rclone, and local — all behind the same interface.

Is It Production Ready?

Mostly. I have 271 commits, a proper test suite (Vitest + Playwright), load tests, a PRODUCTION_READINESS.md checklist, and a CircleCI pipeline. There are 67 open issues — mostly planned features and polish items, not fires.

Would I run my team's code on it today? Yes, with proper backups and a reverse proxy in front.

Would I run a Fortune 500's engineering department on it? Give me another six months.

Why Not Just Use Gitea / Forgejo / GitLab?

Fair question. I tried them. They're good. But they didn't have native stacked PRs, and the CI/CD story always felt bolted on. I also wanted to build something in a modern TypeScript stack end-to-end, using tools I actually enjoy.

Sometimes you build a thing not just because it doesn't exist, but because you building it teaches you things no existing tool can.

Try It / Contribute

The repo is open source under MIT:

→ github.com/swadhinbiswas/OpencodeHub

Docs live at docs.opencodehub.space

If you're tired of GitHub downtime, if you have data residency requirements, if you want stacked PRs without paying for Graphite, or if you just like running your own stuff — give it a spin.

And if GitHub goes down while you're reading this... well. You know what to do.

Built with TypeScript, Astro, frustration, and an embarrassing amount of coffee. PRs welcome.

— Swadhin