Why Self-Host Git in 2026?
GitHub is great. It’s also not yours. You don’t control your data, you don’t control your CI/CD pipeline, and when GitHub goes down (it happens), so does your deployment infrastructure.
Self-hosting git is the move if you:
- Need to run CI/CD without leaving your network (security, compliance, data residency)
- Want to avoid vendor lock-in and GitHub pricing at scale
- Have to isolate repositories from the internet (defense contractors, I see you)
- Just want to own your tooling stack end-to-end
The problem: which platform? You’ve got three serious contenders. GitLab CE is the kitchen sink. Gitea is the nimble workhorse. Forgejo is Gitea’s community-driven fork that’s quietly becoming the safer bet.
Here’s how to pick.
Gitea: The Lightweight Workhorse
Gitea started in 2016 as a response to Gogs (a simpler git service). It’s a single Go binary that weighs almost nothing and runs anywhere. Your Raspberry Pi? Cool. Your 2GB VPS? Even cooler.
What you get:
- Repository hosting, PR/MR workflows, webhooks
- Built-in issue tracking and wiki
- Git LFS support
- Simple web UI, zero bloat
- ~50–100 MB memory footprint (yes, really)
What you don’t:
- Built-in CI/CD (you wire up Gitea Actions or Drone separately)
- Container registry (need to add it yourself or use external registries)
- SAST scanning, dependency checks, or other security features
- Enterprise SSO out of the box (LDAP works, OAuth is basic)
The story: Gitea was developed by a community and a company. Then Gitea Inc. formed and things got complicated. The company’s roadmap started shifting toward features that required beefier infrastructure and closed-source components. Some community members felt the project was drifting away from its lightweight roots.
This friction led to Forgejo.
Forgejo: The Community Fork That Actually Matters
Forgejo forked Gitea in late 2023, when concerns about governance and licensing grew loud enough that staying put felt risky.
What changed:
- Fully community-governed (no for-profit company steering decisions)
- Doubles down on lightweight, self-hosted ethos
- Backports Gitea features that matter for self-hosters
- Adds features Gitea dropped (e.g., improved webhook signing)
- Ships security fixes faster than upstream
Forgejo vs Gitea today (2026):
Both are essentially the same at the core. Forgejo is Gitea, maintained by people who are invested in keeping it simple and self-hostable. It’s the same ~50 MB footprint, same UI, same feature set. The difference is governance: Forgejo won’t become GitLab-lite, because community members control the roadmap.
The practical reality: If you’re starting fresh, Forgejo is the safer pick. If you’re already on Gitea, migrating is painless (we’ll cover it).
GitLab CE: The Full-Stack Freight Train
GitLab Community Edition is the self-hosted version of gitlab.com. It does everything: git hosting, CI/CD (integrated), container registry, SAST scanning, dependency scanning, secret detection, license management, environment tracking, deployment approvals, and about forty other enterprise features you probably don’t need.
What you get:
- Built-in GitLab CI/CD (powerful, battle-tested)
- Container registry (push, scan, deploy)
- Security scanning (SAST, secret detection, dependency checks)
- Advanced LDAP/SAML SSO
- Kubernetes integration
- Advanced audit logging
- The entire feature set of GitLab.com (minus some features gated behind EE)
What it costs:
- Memory: 4 GB minimum, 8+ GB recommended. Heavy workloads? 16+ GB. We’ve seen CE instances spike to 50+ GB on larger installations.
- Disk: 200+ GB depending on repos and artifacts
- CPU: 4+ cores recommended
- Complexity: Installing it takes 20+ minutes. Managing it is an ongoing job.
- Dependencies: PostgreSQL, Redis, Gitaly (file server), a bunch of services running in parallel
GitLab CE is not a single binary. It’s a distributed system pretending to be an all-in-one tool.
Feature Comparison
| Feature | Gitea | Forgejo | GitLab CE |
|---|---|---|---|
| Git hosting | ✅ | ✅ | ✅ |
| PR/MR workflows | ✅ | ✅ | ✅ |
| CI/CD (built-in) | ❌ | ❌ | ✅ |
| Container registry | ❌ | ❌ | ✅ |
| SAST scanning | ❌ | ❌ | ✅ |
| Webhooks | ✅ | ✅ | ✅ |
| LDAP/SAML | 🟡 | 🟡 | ✅ |
| LFS | ✅ | ✅ | ✅ |
| Memory footprint | ~50 MB | ~50 MB | 4+ GB |
| Single binary? | ✅ | ✅ | ❌ |
| Easy to self-host | ✅ | ✅ | 🟡 |
Production Forgejo Setup (Docker Compose)
Let’s assume you want Forgejo with PostgreSQL and a reverse proxy. Here’s a production-ready setup:
version: "3.8"
services: # PostgreSQL database db: image: postgres:16-alpine container_name: forgejo-db environment: POSTGRES_DB: forgejo POSTGRES_USER: forgejo POSTGRES_PASSWORD: ${DB_PASSWORD:-change_me_please} volumes: - db_data:/var/lib/postgresql/data ports: - "5432:5432" restart: unless-stopped healthcheck: test: ["CMD-SHELL", "pg_isready -U forgejo"] interval: 10s timeout: 5s retries: 5
# Forgejo application forgejo: image: codeberg.org/forgejo/forgejo:latest container_name: forgejo environment: USER_UID: 1000 USER_GID: 1000 FORGEJO__database__DB_TYPE: postgres FORGEJO__database__HOST: db:5432 FORGEJO__database__NAME: forgejo FORGEJO__database__USER: forgejo FORGEJO__database__PASSWD: ${DB_PASSWORD:-change_me_please} FORGEJO__server__ROOT_URL: https://git.example.com/ FORGEJO__server__DOMAIN: git.example.com FORGEJO__server__PROTOCOL: https FORGEJO__service__DISABLE_REGISTRATION: "false" FORGEJO__service__REQUIRE_SIGNIN_VIEW: "false" FORGEJO__security__PASSWORD_HASH_ALGO: pbkdf2 volumes: - forgejo_data:/data - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro ports: - "3000:3000" - "2222:22" depends_on: db: condition: service_healthy restart: unless-stopped
volumes: db_data: forgejo_data:To use it:
# Set a real passwordexport DB_PASSWORD=$(openssl rand -base64 16)
# Start itdocker compose up -d
# Check logsdocker compose logs -f forgejoAccess on port 3000. The first user registered becomes admin. Then:
- Set
FORGEJO__service__DISABLE_REGISTRATION: "true"to close signups - Add your reverse proxy (Caddy, Nginx, etc.) on port 443
- Set up SSH keys for SSH git cloning on port 2222
- Optional: wire up external CI/CD (Gitea Actions, Drone, GitHub Actions)
Gitea → Forgejo Migration
If you’re on Gitea and want to switch:
# Stop Giteadocker compose stop gitea
# Back up the datadocker compose exec db pg_dump -U forgejo forgejo > backup.sql
# Update docker image to Forgejo# In your compose file, change:# image: gitea/gitea:latest# to:# image: codeberg.org/forgejo/forgejo:latest
docker compose up -d
# Done. Your data is compatible.That’s it. Forgejo reads Gitea’s database and UI without any conversion. You’re migrated.
When to Pick Which
Pick Forgejo if:
- You’re running 1–50 developers
- Your server has <4 GB RAM
- You want a single-binary, ops-light solution
- You need git + webhooks + basic CI/CD wiring (external)
- You care about long-term governance and community trust
Pick Gitea if:
- You’re already on it and happy
- You want the exact same lightweight product but don’t care about the fork drama
- You’re running an older setup that works
Pick GitLab CE if:
- You have 50+ developers and want unified git + CI/CD + registry
- You have the RAM budget (seriously, budget it)
- You need SAST scanning, advanced audit logs, or enterprise SSO
- You’re willing to manage a complex system
- You want everything in one place (even if that place is heavy)
The Real Talk
Here’s the thing: most self-hosters don’t need GitLab CE. You’ll spin up a Kubernetes cluster, allocate 16 GB RAM, manage PostgreSQL backups, and then realize you’re using 10% of its features. Forgejo or Gitea handles 90% of use cases at a fraction of the ops burden.
GitLab CE wins if you have a team large enough that unifying git + CI/CD + registry saves you from wiring disparate tools together. Otherwise, you’re paying the complexity tax for features you don’t use.
Forgejo is the right call for new setups: lightweight, community-backed, and zero vendor risk.
Your 2 AM self will thank you when your git platform boots in seconds and uses less RAM than a web browser.