← 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.

Installation

Gitea needs a database. PostgreSQL is the recommended choice for anything beyond minimal use.

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 — 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.

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.