If you’re a developer tired of depending on GitHub, GitLab.com, or Bitbucket for your code repositories, self-hosting your own Git server gives you complete control, privacy, and freedom. Whether you’re managing personal projects, team collaboration, or want to escape vendor lock-in, running your own Git infrastructure is easier than ever.

💡 This article contains affiliate links. If you buy through them, we earn a small commission at no extra cost to you. Learn more.

In this comprehensive guide, we’ll compare the three most popular self-hosted Git solutions—Gitea, GitLab, and Forgejo—and show you exactly how to set up each one using Docker. By the end, you’ll know which platform fits your needs and have a production-ready Git server running on your homelab or VPS.

Why Self-Host Your Git Server?

Before diving into the platforms, let’s cover why you might want to self-host Git in the first place:

Complete Data Ownership: Your code stays on your infrastructure. No third-party access, no data mining, no compliance concerns with external providers.

Privacy and Security: Perfect for proprietary projects, sensitive client work, or personal code you don’t want publicly accessible. You control who has access at every level.

No Vendor Lock-In: Platforms like GitHub can change pricing, terms of service, or shut down features at any time. Self-hosting means you’re not at their mercy.

Unlimited Private Repositories: No artificial limits on repo counts, collaborators, or storage. Your only constraint is your hardware.

Customization: Tailor the interface, workflows, integrations, and features exactly to your needs without waiting for platform updates.

Learning Experience: Running production Git infrastructure teaches you valuable DevOps skills: reverse proxies, SSL certificates, backup strategies, and more.

Cost Control: For teams or power users with many repositories, self-hosting can be significantly cheaper than enterprise GitHub or GitLab plans.

Now let’s compare the three leading open-source Git platforms.

Gitea vs GitLab vs Forgejo — Feature Comparison

Gitea: Lightweight and Fast

Gitea is a community-managed, lightweight Git service written in Go. It’s designed to be simple, fast, and resource-efficient.

Key Features:

  • Minimal resource requirements (can run on a Raspberry Pi)
  • Built-in CI/CD with Gitea Actions (GitHub Actions compatible)
  • Issue tracking and project boards
  • Pull/merge requests with code review
  • Wiki support for project documentation
  • Package registry (Docker, npm, Maven, NuGet, etc.)
  • Migration tools from GitHub, GitLab, and others
  • SQLite, PostgreSQL, MySQL, or MSSQL database support
  • Active development with frequent releases

Resource Usage:

  • RAM: 256 MB minimum (512 MB recommended)
  • CPU: Minimal (1 core sufficient for small teams)
  • Storage: Depends on repository size

Best For: Individuals, small teams, homelab users, or anyone wanting a lightweight GitHub alternative with minimal overhead.

GitLab: Enterprise-Grade All-in-One Platform

GitLab is the most feature-rich option, offering an entire DevOps platform beyond just Git hosting.

Key Features:

  • Complete CI/CD pipeline system (GitLab Runners)
  • Advanced security scanning (SAST, DAST, dependency scanning)
  • Container registry
  • Kubernetes integration
  • Issue boards, epics, and roadmaps
  • Advanced merge request workflows
  • Built-in DevOps metrics and analytics
  • Wiki, snippets, and web IDE
  • Self-hosted or managed options
  • Enterprise features (paid tiers available)

Resource Usage:

  • RAM: 4 GB minimum (8 GB+ recommended for production)
  • CPU: 2+ cores recommended
  • Storage: Depends on repository size plus artifacts

Best For: Teams needing a complete DevOps platform, organizations with enterprise requirements, or those wanting all development tools in one interface.

Forgejo: Community-First Gitea Fork

Forgejo (pronounced “for-GAY-yo”) is a hard fork of Gitea, created in late 2022 by the community after concerns about Gitea’s governance and commercial direction.

Key Features:

  • All Gitea features (maintains compatibility)
  • Community-driven governance (no single corporate owner)
  • Focus on federation (ActivityPub integration in development)
  • Strong emphasis on free software principles
  • Similar lightweight resource profile to Gitea
  • Compatible with Gitea Actions for CI/CD
  • Growing community and independent development

Resource Usage:

  • RAM: 256 MB minimum (512 MB recommended)
  • CPU: Minimal (identical to Gitea)
  • Storage: Depends on repository size

Best For: Users who want Gitea’s performance but prefer community-driven development, those interested in federated Git platforms, or those concerned about corporate influence in open-source projects.

Quick Comparison Table

FeatureGiteaGitLabForgejo
Resource UsageLightweightHeavyLightweight
RAM Requirement256 MB+4 GB+256 MB+
CI/CDGitea ActionsAdvanced RunnersGitea Actions compatible
Package RegistryYesYesYes
Issue TrackingGoodExcellentGood
Code ReviewGoodExcellentGood
Security ScanningBasicAdvancedBasic
LicenseMITMITMIT
GovernanceCompany-backedGitLab Inc.Community-driven
Ideal ForSmall teamsEnterprisesCommunity enthusiasts

How to Set Up Gitea with Docker

Gitea is the easiest to get started with. Here’s a complete Docker Compose setup:

Prerequisites

  • Linux server or homelab machine with Docker and Docker Compose installed
  • Domain name or subdomain pointed to your server (optional but recommended)
  • Reverse proxy configured (Traefik, Caddy, or nginx)

Docker Compose Configuration

Create a directory for Gitea:

1
2
3
mkdir -p ~/gitea
cd ~/gitea
nano docker-compose.yml

Add this configuration:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
version: "3.9"

services:
  gitea:
    image: gitea/gitea:latest
    container_name: gitea
    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=changeme
    restart: unless-stopped
    volumes:
      - ./data:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "3000:3000"
      - "2222:22"
    depends_on:
      - db

  db:
    image: postgres:15-alpine
    container_name: gitea_db
    restart: unless-stopped
    environment:
      - POSTGRES_USER=gitea
      - POSTGRES_PASSWORD=changeme
      - POSTGRES_DB=gitea
    volumes:
      - ./postgres:/var/lib/postgresql/data

Important Notes:

  • Change changeme to a strong database password
  • Port 3000 is the web UI, port 2222 is for SSH Git access
  • The USER_UID and USER_GID should match your system user

Start Gitea

1
docker-compose up -d

Initial Setup

  1. Navigate to http://your-server-ip:3000

  2. Complete the installation wizard:

    • Database settings are pre-filled from environment variables
    • Set your domain name (e.g., git.yourdomain.com)
    • Create an admin account
    • Configure SSH settings (use port 2222)
  3. Once complete, you’ll have a fully functional Git server!

Enable Gitea Actions (CI/CD)

To enable GitHub Actions-compatible CI/CD, edit your app.ini configuration:

1
nano data/gitea/conf/app.ini

Add this section:

1
2
[actions]
ENABLED = true

Restart Gitea:

1
docker-compose restart gitea

You’ll now be able to create .gitea/workflows/ directories in your repositories with YAML workflow files.

How to Set Up GitLab with Docker

GitLab is more resource-intensive but provides an all-in-one DevOps platform.

Prerequisites

  • Server with at least 4 GB RAM (8 GB recommended)
  • 2+ CPU cores
  • Docker and Docker Compose installed
  • Domain name configured

Docker Compose Configuration

Create a directory:

1
2
3
mkdir -p ~/gitlab
cd ~/gitlab
nano docker-compose.yml

Configuration:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
version: "3.9"

services:
  gitlab:
    image: gitlab/gitlab-ce:latest
    container_name: gitlab
    restart: unless-stopped
    hostname: 'git.yourdomain.com'
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url 'https://git.yourdomain.com'
        gitlab_rails['gitlab_shell_ssh_port'] = 2222
        # Add your SMTP settings here if needed
    ports:
      - '80:80'
      - '443:443'
      - '2222:22'
    volumes:
      - './config:/etc/gitlab'
      - './logs:/var/log/gitlab'
      - './data:/var/opt/gitlab'
    shm_size: '256m'

Start GitLab

1
docker-compose up -d

GitLab takes 5-10 minutes to fully initialize. Monitor progress:

1
docker logs -f gitlab

Initial Setup

  1. Get the root password:
1
docker exec -it gitlab grep 'Password:' /etc/gitlab/initial_root_password
  1. Navigate to your domain (or http://server-ip)
  2. Log in as root with the password from step 1
  3. Change the root password immediately
  4. Create your first project or migrate repositories

Configure GitLab Runner (CI/CD)

For CI/CD pipelines, you’ll need GitLab Runner:

1
2
3
4
docker run -d --name gitlab-runner --restart unless-stopped \
  -v /srv/gitlab-runner/config:/etc/gitlab-runner \
  -v /var/run/docker.sock:/var/run/docker.sock \
  gitlab/gitlab-runner:latest

Register the runner with your GitLab instance:

1
docker exec -it gitlab-runner gitlab-runner register

Follow the prompts to connect it to your GitLab server.

How to Set Up Forgejo with Docker

Forgejo setup is nearly identical to Gitea since it’s a compatible fork.

Docker Compose Configuration

1
2
3
mkdir -p ~/forgejo
cd ~/forgejo
nano docker-compose.yml

Configuration:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
version: "3.9"

services:
  forgejo:
    image: codeberg.org/forgejo/forgejo:1.21
    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=changeme
    restart: unless-stopped
    volumes:
      - ./data:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "3000:3000"
      - "2222:22"
    depends_on:
      - db

  db:
    image: postgres:15-alpine
    container_name: forgejo_db
    restart: unless-stopped
    environment:
      - POSTGRES_USER=forgejo
      - POSTGRES_PASSWORD=changeme
      - POSTGRES_DB=forgejo
    volumes:
      - ./postgres:/var/lib/postgresql/data

The setup process is identical to Gitea—navigate to port 3000, complete the wizard, and you’re ready to go.

Migration from GitHub/GitLab

All three platforms support migration from existing Git services:

Using Built-in Migration Tools

Both Gitea and Forgejo have migration wizards in their web UI:

  1. Click “+” → “New Migration”
  2. Select your source (GitHub, GitLab, etc.)
  3. Enter source URL and credentials
  4. Choose which data to migrate (issues, PRs, wiki, etc.)
  5. Click “Migrate Repository”

Manual Migration with Git

For any Git server:

1
2
3
4
5
6
7
8
9
# Clone with all branches and tags
git clone --mirror https://github.com/user/repo.git
cd repo.git

# Add new remote
git remote add new-origin https://your-git-server.com/user/repo.git

# Push everything
git push --mirror new-origin

This preserves all history, branches, and tags.

SSL/TLS with Reverse Proxy

For production use, run your Git server behind a reverse proxy with SSL. Here’s a Traefik example:

Traefik Labels for Gitea

Add to your Gitea service in docker-compose.yml:

1
2
3
4
5
6
labels:
  - "traefik.enable=true"
  - "traefik.http.routers.gitea.rule=Host(`git.yourdomain.com`)"
  - "traefik.http.routers.gitea.entrypoints=websecure"
  - "traefik.http.routers.gitea.tls.certresolver=letsencrypt"
  - "traefik.http.services.gitea.loadbalancer.server.port=3000"

Remove the ports section and add to a Traefik network. Now Gitea will be accessible via HTTPS with automatic Let’s Encrypt certificates.

Backup Strategies

Protect your code repositories with automated backups:

Simple Backup Script

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#!/bin/bash
BACKUP_DIR="/backups/gitea"
DATE=$(date +%Y-%m-%d)

# Stop Gitea
docker-compose stop gitea

# Backup data directory
tar -czf "$BACKUP_DIR/gitea-data-$DATE.tar.gz" -C ~/gitea data/

# Backup database
docker exec gitea_db pg_dump -U gitea gitea > "$BACKUP_DIR/gitea-db-$DATE.sql"

# Start Gitea
docker-compose start gitea

# Keep only last 7 days
find "$BACKUP_DIR" -type f -mtime +7 -delete

Schedule with cron for automated daily backups.

Performance Tuning

Gitea/Forgejo Optimization

Edit data/gitea/conf/app.ini:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
[server]
LFS_START_SERVER = true
OFFLINE_MODE = false

[cache]
ENABLED = true
ADAPTER = memory
INTERVAL = 60

[indexer]
ISSUE_INDEXER_TYPE = bleve
REPO_INDEXER_ENABLED = true

GitLab Optimization

For smaller servers, reduce GitLab’s memory footprint:

Add to GITLAB_OMNIBUS_CONFIG in docker-compose.yml:

1
2
3
puma['worker_processes'] = 2
sidekiq['max_concurrency'] = 10
postgresql['shared_buffers'] = "256MB"

Which Platform Should You Choose?

Choose Gitea if:

  • You want a lightweight, fast Git server
  • Running on limited hardware (Raspberry Pi, low-spec VPS)
  • Need GitHub Actions compatibility
  • Want simple setup and maintenance

Choose GitLab if:

  • You need enterprise DevOps features
  • Want built-in CI/CD, security scanning, and container registry
  • Have adequate server resources (8+ GB RAM)
  • Managing larger teams with complex workflows

Choose Forgejo if:

  • You want Gitea’s performance with community governance
  • Interested in federated Git (future feature)
  • Prefer projects without corporate backing
  • Value FOSS principles and community development

For most homelabbers and small teams, Gitea or Forgejo are the ideal choices. They provide excellent GitHub-like experiences without the resource demands of GitLab. If you need GitLab’s advanced features, the resource investment is worth it.

Conclusion

Self-hosting your Git server gives you complete control over your code infrastructure. Whether you choose the lightweight simplicity of Gitea, the enterprise power of GitLab, or the community-driven approach of Forgejo, you’ll gain privacy, flexibility, and independence from commercial platforms.

Start with the Docker Compose configurations provided in this guide, configure your reverse proxy for HTTPS access, set up automated backups, and you’ll have a production-ready Git server that rivals any hosted solution. Your code, your rules, your infrastructure.

Recommended Next Steps:

  • Set up SSH keys for secure Git operations
  • Configure webhooks for automation and notifications
  • Integrate with your existing development workflow
  • Enable two-factor authentication for security
  • Explore CI/CD capabilities with Gitea Actions or GitLab Runners

Happy self-hosting!