If you’ve ever wanted your own private GitHub without the complexity of GitLab or the resource hunger of enterprise solutions, Gitea is your answer. It’s a lightweight, self-hosted Git service written in Go that runs happily on a Raspberry Pi while still offering pull requests, issues, CI/CD, and package registries.

Gitea uses minimal resources (typically under 200MB of RAM) and starts in seconds. It’s the perfect fit for home labs, small teams, and anyone who wants full control over their code.

Why Self-Host Gitea?

  • Privacy — Your code stays on your hardware
  • Lightweight — Runs on minimal resources (ARM and x86)
  • Full-Featured — Issues, PRs, wikis, actions (CI/CD), packages
  • Easy Migration — Import repos from GitHub, GitLab, Bitbucket
  • No Vendor Lock-In — Standard Git, easy to move in or out
  • Free Forever — No seat limits, no feature gates

Prerequisites

Before starting, you’ll need:

  • A Linux server with Docker and Docker Compose installed
  • Basic familiarity with the terminal
  • A domain name (optional, but recommended for HTTPS)
  • About 512MB of RAM free (Gitea itself uses ~150MB)

Step 1: Create the Project Directory

mkdir -p ~/gitea && cd ~/gitea

Step 2: Create the Docker Compose File

Create a docker-compose.yml file:

version: "3"

services:
  gitea:
    image: gitea/gitea:latest
    container_name: gitea
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - GITEA__database__DB_TYPE=sqlite3
      - GITEA__server__ROOT_URL=http://localhost:3000
      - GITEA__server__SSH_DOMAIN=localhost
      - GITEA__server__SSH_PORT=2222
    restart: unless-stopped
    volumes:
      - ./data:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "3000:3000"
      - "2222:22"

This uses SQLite, which is perfect for personal use and small teams (up to ~10 users). For larger deployments, we’ll cover PostgreSQL below.

Step 3: Start Gitea

docker compose up -d

Gitea will pull the image and start. Give it about 30 seconds for first-time initialization.

Step 4: Complete the Web Setup

Open your browser and navigate to http://your-server-ip:3000. You’ll see the initial configuration page.

The defaults are sensible, but review these settings:

  • Site Title — Name your instance whatever you want
  • Server Domain — Set to your domain or IP
  • SSH Server Port — Set to 2222 (matches our compose file)
  • Base URL — Set to your full URL (e.g., http://git.yourdomain.com)

Scroll down and create your Administrator Account. This is your first user and has full control.

Click Install Gitea and you’re live.

Step 5: Configure SSH Access

To clone repos over SSH through Gitea’s built-in SSH server:

# Add to your ~/.ssh/config
Host gitea
    HostName your-server-ip
    Port 2222
    User git

Now you can clone with:

git clone gitea:username/repo.git

Add your SSH public key in Gitea under Settings → SSH/GPG Keys.

Using PostgreSQL Instead of SQLite

For teams larger than 10 or heavier workloads, swap to PostgreSQL:

version: "3"

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=your-secure-password
      - GITEA__server__ROOT_URL=http://localhost:3000
      - GITEA__server__SSH_DOMAIN=localhost
      - GITEA__server__SSH_PORT=2222
    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:16-alpine
    container_name: gitea-db
    environment:
      - POSTGRES_USER=gitea
      - POSTGRES_PASSWORD=your-secure-password
      - POSTGRES_DB=gitea
    restart: unless-stopped
    volumes:
      - ./postgres:/var/lib/postgresql/data

Replace your-secure-password with something strong.

Migrating Repos from GitHub

Gitea makes migration dead simple:

  1. Go to the + menu → New Migration
  2. Select GitHub as the source
  3. Paste the repository URL
  4. Optionally enter a GitHub personal access token (for private repos)
  5. Choose what to import: issues, labels, milestones, pull requests, releases
  6. Click Migrate Repository

Gitea preserves your entire history, issues, and even pull request discussions.

Setting Up Gitea Actions (CI/CD)

Gitea Actions is compatible with GitHub Actions workflows. Enable it by adding to your environment:

environment:
  - GITEA__actions__ENABLED=true

Then register a runner:

# Pull the runner
docker pull gitea/act_runner:latest

# Register with your instance
docker run --rm -it \
  -v ./runner-data:/data \
  gitea/act_runner:latest register \
  --instance http://your-server-ip:3000 \
  --token YOUR_RUNNER_TOKEN

Get your runner token from Site Administration → Runners in Gitea’s web UI.

Start the runner:

docker run -d \
  --name gitea-runner \
  -v ./runner-data:/data \
  -v /var/run/docker.sock:/var/run/docker.sock \
  gitea/act_runner:latest daemon

Now you can use .gitea/workflows/ in your repos with GitHub Actions-compatible YAML.

Enabling HTTPS with a Reverse Proxy

If you’re running Nginx Proxy Manager or Traefik, point a subdomain like git.yourdomain.com to port 3000. Then update the Gitea environment:

environment:
  - GITEA__server__ROOT_URL=https://git.yourdomain.com

Remove the ports mapping for 3000 if your reverse proxy connects via Docker network.

Backups

Gitea includes a built-in backup command:

docker exec -u git gitea bash -c '/usr/local/bin/gitea dump -c /data/gitea/conf/app.ini'

This creates a ZIP file with repositories, database, and configuration. Schedule it with cron for automated backups:

0 2 * * * docker exec -u git gitea bash -c '/usr/local/bin/gitea dump -c /data/gitea/conf/app.ini -f /data/backup-$(date +\%Y\%m\%d).zip'

Troubleshooting

Port 3000 is already in use

Another service is using the port. Change the left side of the port mapping:

ports:
  - "3001:3000"

SSH cloning fails with “permission denied”

Make sure you’ve added your SSH key in Gitea’s web UI and that your SSH config points to port 2222 (not 22).

Gitea is slow to start

First startup includes database migrations. Subsequent starts are fast (~2 seconds). If it stays slow, check disk I/O — SQLite on a network share will be sluggish.

“Relative URL root” errors after reverse proxy setup

Make sure ROOT_URL matches your actual external URL exactly, including the protocol (https, not http).

Resource Usage

On a typical home server, Gitea is remarkably light:

ResourceIdleActive
RAM~150MB~200MB
CPU<1%2-5%
Disk~100MB (base)Depends on repos

Compare that to GitLab’s 4GB+ RAM requirement, and you’ll see why Gitea is the home lab favorite.

Conclusion

Gitea gives you a fully featured Git platform that respects your hardware and your privacy. Whether you’re backing up personal projects, running a small team, or just want to stop depending on GitHub for everything — Gitea delivers without the bloat.

With Docker, you can have it running in under 5 minutes. Add CI/CD with Gitea Actions, migrate your existing repos, and you’ve got a complete development platform on your own terms.

Useful Links: