A self hosted Git server keeps your source code, issues and CI configuration on infrastructure you control, under your own access rules and retention policy. The hard part is not installation. It is choosing the right software for your team size, giving it enough memory, and making sure backups actually restore. This guide compares Gitea and GitLab, gives realistic sizing, walks through a Gitea install with Docker and an outline of GitLab, and finishes with backups and SSH details that trip people up.
Gitea or GitLab: decide first
The two projects solve different problems, and the choice drives everything else, including the server size.
| Gitea | GitLab (Community Edition) | |
|---|---|---|
| What it is | A single Go binary: repos, issues, pull requests, packages, Actions-compatible CI | A full DevOps platform: repos, merge requests, built-in CI/CD, registry, planning tools |
| Memory footprint | Small; comfortable on 1 to 2 GB RAM for a small team | Large; bundles PostgreSQL, Redis, Puma, Sidekiq and Gitaly |
| Practical starting server | 1 vCPU, 2 GB RAM | 4 vCPU, 8 GB RAM |
| Upgrades | Swap the binary or image tag | Follow GitLab's required upgrade path between versions |
| Best for | Small teams, personal projects, mirrors | Teams that want CI/CD, registry and planning in one product |
If you are unsure, start with Gitea. It covers what most small teams use daily and leaves room on the server for CI runners or other services. Move to GitLab when you need its integrated pipelines and permissions model, and size the server for it from day one. GitLab can be squeezed onto less memory with tuning, but an underpowered GitLab is slow enough that people stop using it.
Sizing a self hosted Git server and picking a location
A Git server is mostly idle with short bursts: clones, pushes, web page renders and the occasional large fetch from CI. Shared CPU handles Gitea well. GitLab benefits from general purpose CPU, and dedicated CPU if CI jobs run on the same box.
For European teams, Frankfurt and Amsterdam are both central choices, and monthly plans in both include 5 TB of traffic, which is plenty for repeated CI clones. See Cloudj servers in Germany and in the Netherlands, or read best VPS in Germany and best VPS in the Netherlands for location detail. The Europe VPS guide compares all seven European countries if your team sits elsewhere.
Disk is the number people underestimate. Plan for repositories, Git LFS objects, package registries, CI artifacts and at least one local backup before it is shipped off the server. Start with headroom; you can grow the disk later from the console, but cleaning a full disk under pressure is not fun.
Installing Gitea with Docker Compose
Prepare a fresh Linux server with SSH keys and a firewall first; the SSH key setup guide and Docker install guide cover both. Then create a project folder:
mkdir -p ~/gitea && cd ~/gitea
Create docker-compose.yml:
services:
gitea:
image: gitea/gitea:latest # pin a release tag in production
container_name: gitea
restart: always
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__server__DOMAIN=git.example.com
- GITEA__server__ROOT_URL=https://git.example.com/
- GITEA__server__SSH_DOMAIN=git.example.com
- GITEA__server__SSH_PORT=2222
volumes:
- ./data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "127.0.0.1:3000:3000"
- "2222:22"
Two details matter here. The web port is bound to 127.0.0.1, so it is only reachable through a reverse proxy on the same server. Git over SSH uses port 2222 on the host, which leaves port 22 for your own admin logins. Start it:
docker compose up -d
docker compose logs -f gitea
Put Nginx in front of port 3000 with a Let's Encrypt certificate (the Nginx reverse proxy and SSL guide has a ready template), then open the firewall:
sudo ufw allow 80,443/tcp
sudo ufw allow 2222/tcp
Visit https://git.example.com, finish the installer (SQLite is fine for a small team; choose PostgreSQL if you expect growth) and create the admin account. Developers clone over SSH like this:
git clone ssh://[email protected]:2222/team/project.git
To avoid typing the port, each developer can add a block to ~/.ssh/config:
Host git.example.com
Port 2222
User git
Installing GitLab: the outline
GitLab's Omnibus package installs everything in one step on Ubuntu or Debian. On a server with enough memory:
sudo apt update && sudo apt install -y curl ca-certificates
curl -fsSL https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash
sudo EXTERNAL_URL="https://git.example.com" apt install -y gitlab-ce
With an https URL and DNS already pointing at the server, the package requests a Let's Encrypt certificate itself. The initial root password is in /etc/gitlab/initial_root_password for 24 hours. Configuration lives in /etc/gitlab/gitlab.rb; after any change run sudo gitlab-ctl reconfigure. Read the official upgrade path before each version jump, because GitLab does not support skipping some required stops.
Backups you can restore
For Gitea in Docker, the simplest consistent backup is a short stop and an archive of the data folder:
cd ~/gitea
docker compose stop gitea
sudo tar czf /var/backups/gitea-$(date +%F).tar.gz data
docker compose start gitea
For GitLab, the application backup and the secrets are separate, and you need both:
sudo gitlab-backup create
sudo cp /etc/gitlab/gitlab.rb /etc/gitlab/gitlab-secrets.json /var/backups/
Then copy the archives off the server on a schedule, for example with rsync or rclone to storage in another location. Once a quarter, restore to a fresh hourly server, check that a repository clones and an issue opens, and delete the test server so it stops costing anything. Hourly servers bill as long as they exist, so deleting, not just stopping, is what ends the charge.
FAQ
How much RAM does Gitea need?
A small team runs comfortably on 1 to 2 GB RAM. Add memory when you enable Actions runners, package registries or many mirrors on the same server.
Can I run GitLab on 4 GB RAM?
It can start, but it will feel slow and may run out of memory under CI load. Treat 8 GB as the practical floor for a team that uses it every day.
Why not run Git SSH on port 22?
You can, but then your admin SSH must move. Keeping admin access on 22 and Git on 2222 is simpler to reason about and to firewall.
Should CI runners live on the same server?
For light jobs, yes. For heavy builds, run them on a separate server so a long build never slows down pushes and code review. The self-hosted GitHub Actions runner guide covers the runner side.
Deploy your Git server
Choose Gitea for a lean setup or GitLab for an all-in-one platform, size the server to match, and test a restore before you trust it. See live prices on the pricing page, or deploy from the Cloudj console, which shows the exact cost before you confirm.