Gitea: Lightweight Self-Hosted Git Server
GitHub is the default for most developers, but there are reasons to run your own Git server: private repositories without subscription costs, full data control, internal team use without internet dependency, or wanting to keep certain code completely off third-party infrastructure. Gitea is the most popular lightweight option: under 100MB of RAM, GitHub-like UI, and more features than you'd expect from something that runs on a Raspberry Pi.
Photo by Markus Spiske on Unsplash
What Gitea Includes
- Git hosting: Repositories, branches, tags, Git LFS support
- Code review: Pull requests with inline comments, reviews, and merge controls
- Issues and milestones: Basic project tracking
- Wiki: Per-repository wikis
- Gitea Actions: GitHub Actions-compatible CI/CD workflows
- Package registry: Host npm, Docker, PyPI, Maven, and other packages
- OAuth2: SSO via GitHub, Google, Keycloak, or any OAuth2 provider
- Web editor: Edit files in browser
- Webhooks: Trigger external services on push, PR, etc.
Gitea is not a replacement for GitHub at enterprise scale. For a team of 2-50 people or personal use, it's more than capable.
Docker Deployment
services:
gitea:
image: gitea/gitea:latest
container_name: gitea
restart: always
environment:
USER_UID: 1000
USER_GID: 1000
GITEA__database__DB_TYPE: postgres
GITEA__database__HOST: gitea-db:5432
GITEA__database__NAME: gitea
GITEA__database__USER: gitea
GITEA__database__PASSWD: change-this
GITEA__server__DOMAIN: git.yourdomain.com
GITEA__server__SSH_DOMAIN: git.yourdomain.com
GITEA__server__ROOT_URL: https://git.yourdomain.com/
GITEA__server__SSH_PORT: 222
ports:
- "3000:3000" # Web UI
- "222:22" # SSH (avoid port 22 conflict with host)
volumes:
- gitea-data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
depends_on:
- gitea-db
gitea-db:
image: postgres:15-alpine
restart: always
environment:
POSTGRES_USER: gitea
POSTGRES_PASSWORD: change-this
POSTGRES_DB: gitea
volumes:
- gitea-db:/var/lib/postgresql/data
volumes:
gitea-data:
gitea-db:
First startup: Visit http://your-server:3000. Gitea presents an installation wizard — most settings are pre-filled from environment variables. Confirm database settings and create the admin account.
For SQLite (minimal setup, no separate DB):
environment:
GITEA__database__DB_TYPE: sqlite3
# Remove all other database settings
SQLite works fine for personal use or small teams.
SSH Configuration
To use SSH for git operations (recommended over HTTPS for developer workflows):
The compose above maps port 222 on the host to port 22 inside the container. SSH clone URL becomes:
git clone ssh://[email protected]:222/username/repo.git
To avoid the custom port, you can set up SSH config on developer machines:
# ~/.ssh/config
Host git.yourdomain.com
Port 222
User git
Then git clone [email protected]:username/repo.git works normally.
Gitea Actions (CI/CD)
Gitea Actions is compatible with GitHub Actions workflow syntax. Most GitHub Actions workflows run on Gitea with minimal changes.
Set up an actions runner:
# Add to docker-compose.yml
gitea-runner:
image: gitea/act_runner:latest
environment:
CONFIG_FILE: /config.yaml
GITEA_INSTANCE_URL: http://gitea:3000
GITEA_RUNNER_REGISTRATION_TOKEN: "your-token-from-gitea-ui"
GITEA_RUNNER_NAME: homelab-runner
volumes:
- ./runner-config.yaml:/config.yaml
- /var/run/docker.sock:/var/run/docker.sock # For Docker-in-Docker
- runner-data:/data
depends_on:
- gitea
volumes:
runner-data:
Get the registration token from Gitea: Site Administration → Runners → Create new runner.
Example workflow (.gitea/workflows/ci.yml):
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
- run: npm ci
- run: npm test
Package Registry
Gitea hosts packages natively. For npm:
# Set registry for a package
npm config set @yourorg:registry https://git.yourdomain.com/api/packages/username/npm/
# Authenticate
npm config set //git.yourdomain.com/api/packages/username/npm/:_authToken YOUR_TOKEN
# Publish
npm publish
For Docker packages:
docker login git.yourdomain.com
docker tag myimage git.yourdomain.com/username/myimage:latest
docker push git.yourdomain.com/username/myimage:latest
This turns Gitea into a complete internal DevOps platform: code hosting, CI/CD, and artifact registry.
Organization and Team Management
Gitea supports organizations with teams and fine-grained permissions:
- Create an organization (top nav → + → New Organization)
- Add teams with Owner, Admin, Write, Read, or custom permissions
- Add repositories to teams
- Invite members by username or email
For internal company use, set up LDAP/AD authentication or OAuth2 via your identity provider.
Migrating from GitHub
Gitea can mirror or migrate repositories from GitHub:
- Repository → New Migration → GitHub
- Enter GitHub token, select repos to migrate
- Choose: clone (one-time) or mirror (ongoing sync)
Mirrors keep the Gitea repo in sync with GitHub on a schedule — useful for having a backup or internal copy of external repos.
Backup
# Database backup
docker exec -t gitea-db pg_dump -U gitea gitea > gitea_backup_$(date +%Y%m%d).sql
# Git data and config backup
docker run --rm -v gitea-data:/data -v $(pwd):/backup alpine \
tar czf /backup/gitea-data-$(date +%Y%m%d).tar.gz /data
Restore: restore the database, restore the data volume, start the container.
Gitea vs. Forgejo
Forgejo is a fork of Gitea created by the community in 2022 after concerns about Gitea's governance direction. The two are nearly identical at present:
- Gitea: Original project, backed by Gitea Inc., active development
- Forgejo: Community fork, slightly more conservative release pace, soft-forked from Gitea
Both use the same configuration format and are fully compatible. Choose Forgejo if you prefer community governance; Gitea if you prefer the original project. Most self-hosting guides apply to both.
Resource Usage
- Idle: ~30-80MB RAM
- Under load: 100-200MB RAM
- CPU: Minimal except during git operations and CI
A Raspberry Pi 4 (4GB) can comfortably run Gitea, a Postgres database, and a CI runner for a small team. A VPS with 1GB RAM works for personal use.
