Skip to content
Cloudj

VPS use cases

Self hosted Git server on a VPS: Gitea vs GitLab, sizing, setup

Plan a self hosted Git server on a VPS: compare Gitea and GitLab, size RAM and disk correctly, run SSH cloning alongside admin SSH, and set up backups.

Updated · 4 min read

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.

GiteaGitLab (Community Edition)
What it isA single Go binary: repos, issues, pull requests, packages, Actions-compatible CIA full DevOps platform: repos, merge requests, built-in CI/CD, registry, planning tools
Memory footprintSmall; comfortable on 1 to 2 GB RAM for a small teamLarge; bundles PostgreSQL, Redis, Puma, Sidekiq and Gitaly
Practical starting server1 vCPU, 2 GB RAM4 vCPU, 8 GB RAM
UpgradesSwap the binary or image tagFollow GitLab's required upgrade path between versions
Best forSmall teams, personal projects, mirrorsTeams 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.

Deploy a server or order proxies

Pick a location in the console, see the live price, and pay from your balance.