Gitea vs Forgejo: Lightweight Self-Hosted Git 2026
TL;DR
Gitea (MIT, ~44K GitHub stars, Go) and Forgejo (GPL 3.0, ~10K stars, Go) are both lightweight self-hosted Git services. Forgejo is a community-governed fork of Gitea, created in 2022 after concerns about Gitea Ltd's commercialization direction. They're functionally nearly identical today, but the choice between them is increasingly important: Forgejo has more active community governance and stronger federation plans; Gitea has more third-party integrations and a larger ecosystem. Both run in under 200MB RAM with full GitHub-like features.
Key Takeaways
- Gitea: MIT, ~44K stars, Go — original project, largest ecosystem, commercial-friendly
- Forgejo: GPL 3.0, ~10K stars, Go — community fork, stronger copyleft, federation (ActivityPub) roadmap
- Both include: Actions CI/CD, container registry, issue tracker, wikis, webhooks, API
- RAM: ~100–200MB — vastly lighter than GitLab (~4GB)
- Migration: Trivial to migrate between them (same codebase fork)
- Choose Gitea: Better third-party tool support (VS Code extensions, bots, CI integrations)
- Choose Forgejo: Community governance, copyleft license, federation plans
Gitea vs Forgejo vs GitLab CE
| Feature | Gitea | Forgejo | GitLab CE |
|---|---|---|---|
| License | MIT | GPL 3.0 | MIT |
| GitHub Stars | ~44K | ~10K | ~24K |
| RAM (idle) | ~100MB | ~100MB | ~4GB+ |
| CI/CD | Gitea Actions | Forgejo Actions | GitLab CI |
| Container Registry | Yes | Yes | Yes |
| Pages | Yes | Yes | Yes |
| Federation | Planned | In progress | No |
| LDAP/OIDC SSO | Yes | Yes | Yes |
| PostgreSQL support | Yes | Yes | Yes |
| Self-hosted runners | Yes | Yes | Yes |
Part 1: Gitea Docker Setup
# docker-compose.yml
services:
gitea:
image: gitea/gitea:latest
container_name: gitea
restart: unless-stopped
ports:
- "3000:3000"
- "2222:22" # SSH for git push
volumes:
- gitea_data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
environment:
USER_UID: "1000"
USER_GID: "1000"
GITEA__database__DB_TYPE: postgres
GITEA__database__HOST: db:5432
GITEA__database__NAME: gitea
GITEA__database__USER: gitea
GITEA__database__PASSWD: "${POSTGRES_PASSWORD}"
GITEA__server__DOMAIN: "git.yourdomain.com"
GITEA__server__ROOT_URL: "https://git.yourdomain.com/"
GITEA__server__SSH_DOMAIN: "git.yourdomain.com"
GITEA__server__SSH_PORT: "2222"
GITEA__service__DISABLE_REGISTRATION: "true"
depends_on:
- db
db:
image: postgres:16-alpine
restart: unless-stopped
volumes:
- db_data:/var/lib/postgresql/data
environment:
POSTGRES_DB: gitea
POSTGRES_USER: gitea
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
volumes:
gitea_data:
db_data:
Part 2: Forgejo Docker Setup
Forgejo uses the same config format as Gitea — just change the image:
services:
forgejo:
image: codeberg.org/forgejo/forgejo:latest
container_name: forgejo
restart: unless-stopped
ports:
- "3000:3000"
- "2222:22"
volumes:
- forgejo_data:/data
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: "${POSTGRES_PASSWORD}"
FORGEJO__server__DOMAIN: "git.yourdomain.com"
FORGEJO__server__ROOT_URL: "https://git.yourdomain.com/"
FORGEJO__service__DISABLE_REGISTRATION: "true"
depends_on:
- db
docker compose up -d
Part 3: HTTPS with Caddy
git.yourdomain.com {
reverse_proxy localhost:3000
}
SSH clone: Users clone via SSH using port 2222:
git clone ssh://git@git.yourdomain.com:2222/username/repo.git
Part 4: Initial Setup
- Visit
https://git.yourdomain.com - Installation wizard → verify database settings
- Create admin account
- Register additional users (or invite via email if registration disabled)
Add your SSH key:
# User settings → SSH/GPG Keys → Add Key
cat ~/.ssh/id_ed25519.pub
Part 5: Actions CI/CD
Both Gitea and Forgejo support GitHub Actions-compatible workflows (using .gitea/workflows/ or .forgejo/workflows/).
Set Up a Runner
# On a separate host or same host:
services:
gitea-runner: # or forgejo-runner
image: gitea/act_runner:latest
container_name: gitea-runner
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- runner_data:/data
environment:
GITEA_INSTANCE_URL: "https://git.yourdomain.com"
GITEA_RUNNER_REGISTRATION_TOKEN: "${RUNNER_TOKEN}"
GITEA_RUNNER_NAME: "docker-runner"
CONFIG_FILE: /data/config.yaml
Get the registration token: Admin Panel → Runners → Create new runner.
Example Workflow
# .gitea/workflows/ci.yml (or .forgejo/workflows/ci.yml)
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build
run: npm run build
Part 6: Container Registry
Both Gitea and Forgejo include a built-in container registry:
# Log in:
docker login git.yourdomain.com
# Tag and push:
docker tag myapp git.yourdomain.com/username/myapp:latest
docker push git.yourdomain.com/username/myapp:latest
# Pull:
docker pull git.yourdomain.com/username/myapp:latest
In your Actions workflow:
- name: Build and push Docker image
run: |
echo "${{ secrets.GITEA_TOKEN }}" | docker login git.yourdomain.com -u ${{ gitea.actor }} --password-stdin
docker build -t git.yourdomain.com/${{ gitea.repository }}:${{ gitea.sha }} .
docker push git.yourdomain.com/${{ gitea.repository }}:${{ gitea.sha }}
Part 7: Migrate Between Gitea and Forgejo
Since Forgejo is a fork of Gitea, migration is trivial:
Gitea → Forgejo
# 1. Stop Gitea:
docker compose down
# 2. Back up data:
tar -czf gitea-backup.tar.gz $(docker volume inspect gitea_gitea_data --format '{{.Mountpoint}}')
# 3. Change image in docker-compose.yml:
# gitea/gitea:latest → codeberg.org/forgejo/forgejo:latest
# 4. Update env var prefixes (optional — Gitea vars work in Forgejo too):
# GITEA__ → FORGEJO__ (in new configs)
# 5. Start:
docker compose up -d
Forgejo reads Gitea's data directory natively — no data migration needed.
Part 8: OIDC / SSO Integration
Connect to Authentik, Keycloak, or other OIDC providers:
In Admin Panel → Authentication Sources → Add OAuth2:
- Provider: OpenID Connect
- Client ID: from your OIDC provider
- Client Secret: from your OIDC provider
- OpenID Connect Auto Discovery URL:
https://auth.yourdomain.com/application/o/gitea/.well-known/openid-configuration
Users can now log in via SSO.
When to Choose Gitea vs Forgejo
Choose Gitea if:
- You need maximum third-party ecosystem support (VS Code extensions, bots, integrations)
- You want MIT license (more permissive for commercial use)
- You're following a specific tutorial that uses Gitea
- You have existing Gitea users/scripts
Choose Forgejo if:
- You prefer community governance over corporate-influenced development
- GPL 3.0 license aligns with your values
- You're excited about ActivityPub federation (repos federated across Forgejo instances)
- You're hosted on Codeberg or similar Forgejo-native platforms
Maintenance
# Update:
docker compose pull
docker compose up -d
# Backup via built-in tool:
docker exec gitea gitea admin dump -c /data/gitea/conf/app.ini
# Or direct volume backup:
tar -czf gitea-backup-$(date +%Y%m%d).tar.gz \
$(docker volume inspect gitea_gitea_data --format '{{.Mountpoint}}')
# Logs:
docker compose logs -f gitea
See all open source developer tools at OSSAlt.com/categories/developer-tools.