← All Guides
beginner

Gitea: Self-Hosted Git Server on Docker

Set up Gitea on Docker for a self-hosted GitHub alternative: code hosting, issue tracking, pull requests, and CI/CD pipelines on your own server.

Budget Homelab ·
dockergitself-hosting

Gitea is a self-hosted Git service: your own GitHub, running on your homelab. It handles repositories, issues, pull requests, code review, and (with Gitea Actions) CI/CD pipelines. The interface is familiar if you’ve used GitHub, and it runs in a single lightweight container.

Reasons to self-host your Git repos: privacy for personal projects, keeping code off third-party servers, having a backup of all your GitHub repos, or just wanting to run your own infrastructure. Gitea is the right tool for all of these.

Gitea’s built-in wiki is fine for a README-sized amount of documentation. Once you’re writing more than that, it’s worth looking at a dedicated tool instead: BookStack vs Outline vs Wiki.js compares the three on what they actually cost you in dependencies and RAM.

Installation

Gitea needs a database. PostgreSQL is the recommended choice for anything beyond minimal use. That makes this a two-container stack rather than a single service, so it’s a step up from the simplest deployments (Docker Compose basics if depends_on and named services are new to you).

mkdir -p /opt/gitea

Create /opt/gitea/docker-compose.yml:

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

  gitea-db:
    image: postgres:16-alpine
    container_name: gitea-db
    environment:
      - POSTGRES_USER=gitea
      - POSTGRES_PASSWORD=changeme
      - POSTGRES_DB=gitea
    volumes:
      - /opt/gitea/pgdata:/var/lib/postgresql/data
    restart: unless-stopped

USER_UID and USER_GID: Run Gitea as your regular user. Check your UID with id -u and GID with id -g.

Port 222: SSH for Git operations. Maps to a non-standard port because port 22 is usually used by the host’s SSH. You’ll configure Git clients to use this port for SSH operations.

changeme: Update the database password in both the gitea and gitea-db environment sections.

Start Gitea

cd /opt/gitea
docker compose up -d

Access the setup page at http://YOUR_SERVER_IP:3000. The first time you open Gitea, it shows an installation wizard.

Initial Configuration

The install wizard pre-fills most settings from your environment variables. Verify and adjust:

Database settings: should be pre-filled from your compose env vars.

General settings:

Admin account: Create your admin user at the bottom of the page.

Click Install Gitea.

Creating Your First Repository

After logging in:

  1. Click + > New Repository
  2. Fill in name, description, visibility
  3. Initialize with a README if it’s a new project

You can clone via HTTPS or SSH.

HTTPS clone:

git clone http://YOUR_SERVER_IP:3000/username/repo-name.git

SSH clone (requires SSH key setup, see below):

git clone ssh://git@YOUR_SERVER_IP:222/username/repo-name.git

SSH Key Setup

For SSH access, add your public key to Gitea:

Settings > SSH / GPG Keys > Add Key

Paste your public key (~/.ssh/id_ed25519.pub or ~/.ssh/id_rsa.pub).

Then configure SSH to use port 222 for your Gitea server. Add to ~/.ssh/config on your local machine:

Host your-server-ip
    Port 222
    User git

Test it:

ssh -T git@your-server-ip -p 222

You should see a message confirming you’re authenticated as your Gitea user.

Mirroring from GitHub

Gitea can mirror GitHub repositories, which is useful for keeping local copies of all your GitHub repos.

Create repository > Settings > enable “Mirror”, then set the source URL.

For bulk mirroring, Gitea has a migration wizard:

  1. + > Migrate
  2. Choose GitHub as the source
  3. Enter your GitHub access token and username
  4. Gitea lists all your repositories; select which to mirror

Mirrored repos sync automatically on a schedule you configure.

Gitea Actions (CI/CD)

Gitea Actions is compatible with GitHub Actions syntax. your existing .github/workflows/ files work with minor changes. To use it:

  1. Enable Actions in Gitea admin settings
  2. Deploy a Gitea Actions runner (a separate container that actually runs the workflows)

Create /opt/gitea-runner/docker-compose.yml:

services:
  gitea-runner:
    image: gitea/act_runner:latest
    container_name: gitea-runner
    environment:
      - GITEA_INSTANCE_URL=http://YOUR_SERVER_IP:3000
      - GITEA_RUNNER_REGISTRATION_TOKEN=
    volumes:
      - /opt/gitea-runner/data:/data
      - /var/run/docker.sock:/var/run/docker.sock
    restart: unless-stopped

Get the registration token from Gitea admin panel > Settings > Actions > Runners > Create new Runner. Add it to GITEA_RUNNER_REGISTRATION_TOKEN.

Backups

Back up both the data directory and database:

# Database dump
docker exec gitea-db pg_dump -U gitea gitea > /backup/gitea-db-$(date +%Y%m%d).sql

# Data directory (repositories, config, attachments)
tar -czf /backup/gitea-data-$(date +%Y%m%d).tar.gz /opt/gitea/data/

The data directory contains all your repositories in bare Git format. A proper backup includes both the database (issues, users, pull requests) and the repository files.

This is a case where a half-backup looks complete and isn’t: restore only the data directory and you get every commit back with none of the issues or pull requests. Test the pair together before you rely on it, which is what the homelab disaster recovery guide walks through for exactly this kind of app-plus-database service.

Updating

cd /opt/gitea
docker compose pull
docker compose up -d

Gitea handles database migrations automatically on startup. Check the release notes before major version updates. They occasionally include manual steps for significant migrations.