Software & Configuration

Gitea / Forgejo

Self-hosted Git service with web interface, install Gitea or Forgejo on your VPS with Docker

Gitea and Forgejo are lightweight, self-hosted Git services with a web interface. Forgejo is a community-maintained fork of Gitea. Both provide pull requests, issue tracking, wiki, and integrated CI/CD without the overhead of GitLab.


What is Gitea/Forgejo?

A self-hosted alternative to GitHub and GitLab for teams and personal projects. Runs efficiently on minimal resources, supports unlimited repositories, users, and collaborators. Forgejo is the recommended community continuation.


Docker Compose Installation

MySQL Database Setup

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

version: '3.8'

services:
  db:
    image: mysql:8.0
    container_name: gitea_db
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      MYSQL_DATABASE: gitea
      MYSQL_USER: gitea
      MYSQL_PASSWORD: ${DB_PASSWORD}
    volumes:
      - gitea_db:/var/lib/mysql
    command: --default-authentication-plugin=mysql_native_password

  gitea:
    image: codeberg.org/forgejo/forgejo:latest
    container_name: gitea
    restart: always
    depends_on:
      - db
    ports:
      - "3000:3000"
      - "222:22"
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - GITEA__database__DB_TYPE=mysql
      - GITEA__database__HOST=db:3306
      - GITEA__database__NAME=gitea
      - GITEA__database__USER=gitea
      - GITEA__database__PASSWD=${DB_PASSWORD}
      - 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=222
      - GITEA__service__DISABLE_REGISTRATION=false
    volumes:
      - gitea_data:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro

volumes:
  gitea_db:
  gitea_data:

Create .env file:

DB_ROOT_PASSWORD=your_secure_root_password
DB_PASSWORD=your_secure_gitea_password

Deploy:

cd /etc/docker/compose/gitea
docker compose up -d
docker compose logs -f gitea

PostgreSQL Alternative

For PostgreSQL instead of MySQL:

db:
  image: postgres:15
  container_name: gitea_db
  restart: always
  environment:
    POSTGRES_DB: gitea
    POSTGRES_USER: gitea
    POSTGRES_PASSWORD: ${DB_PASSWORD}
  volumes:
    - gitea_db:/var/lib/postgresql/data

Update environment variables:

environment:
  - GITEA__database__DB_TYPE=postgres
  - GITEA__database__HOST=db:5432
  - GITEA__database__NAME=gitea
  - GITEA__database__USER=gitea
  - GITEA__database__PASSWD=${DB_PASSWORD}

Initial Configuration

Access Gitea at http://your-ip:3000:

  1. Database configuration is auto-detected from environment variables
  2. Create admin account (username and password)
  3. Basic settings are applied
  4. Redirect to homepage and login

The web setup wizard should be skipped if all environment variables are set correctly.


SSH Configuration

SSH runs on port 222 to avoid conflict with system SSH on port 22.

For client SSH access, create ~/.ssh/config:

Host git.example.com
    Hostname git.example.com
    Port 222
    User git

Clone repositories:

git clone git@git.example.com:username/repo.git

Nginx Reverse Proxy

Configure Nginx to proxy Gitea:

server {
    listen 80;
    server_name git.example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name git.example.com;

    ssl_certificate /etc/letsencrypt/live/git.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/git.example.com/privkey.pem;

    client_max_body_size 100M;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $server_name;

        # WebSocket support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        proxy_redirect off;
    }
}

Test and reload:

nginx -t
systemctl reload nginx

Configuration (app.ini)

For Docker, edit the mounted /data volume. Access the container:

docker compose exec gitea bash

Edit /data/gitea/conf/app.ini:

Critical settings:

[server]
DOMAIN = git.example.com
ROOT_URL = https://git.example.com/

[service]
DISABLE_REGISTRATION = false
REQUIRE_SIGNIN_VIEW = false
DEFAULT_KEEP_EMAIL_PRIVATE = true

[mailer]
ENABLED = true
SMTP_ADDR = smtp.example.com
SMTP_PORT = 587
USER = noreply@example.com
FROM = Gitea <noreply@example.com>
PASSWD = your_password

[security]
SECRET_KEY = generate_secure_key_with_openssl
INSTALL_LOCK = true

Restart Gitea after changes:

docker compose restart gitea

Actions (CI/CD)

Gitea includes built-in CI/CD similar to GitHub Actions.

Create .gitea/workflows/test.yml:

name: Test

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Run tests
        run: |
          npm install
          npm test

Workflows execute in Docker containers managed by Gitea. Enable in Dashboard → Admin Panel → Actions.


User and Organization Management

Create organizations for team projects:

# Via web interface: Dashboard → Create Organization

Organizations provide:

  • Team management
  • Repository access control
  • Shared settings
  • Project grouping

Create teams within organizations and assign users.


Backup

Backup Gitea data and database:

docker compose exec gitea /app/gitea/gitea dump -c /data/gitea/conf/app.ini
docker compose cp gitea:/data/gitea-dump-*.zip ./

Backup includes:

  • Repository data
  • Database
  • Attachments
  • Avatars
  • Configuration

Updates

Update Forgejo/Gitea:

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

Verify the update:

docker compose logs -f gitea

Useful Commands

List all users:

docker compose exec gitea /app/gitea/gitea admin user list -c /data/gitea/conf/app.ini

Create admin user:

docker compose exec gitea /app/gitea/gitea admin user create --username admin --password password --email admin@example.com -c /data/gitea/conf/app.ini

For small teams and personal projects, Gitea provides all the features of GitHub: repositories, pull requests, issue tracking, wiki, code review, and CI/CD. Zero cloud dependency, complete data ownership, and minimal resource requirements.


Troubleshooting

If SSH push fails with "connection refused", ensure:

docker compose logs gitea | grep -i ssh
docker compose ps | grep gitea

Port 222 must be exposed and accessible. Verify firewall rules:

ss -tlnp | grep 222

For database connection errors, check environment variables are passed correctly:

docker compose config | grep GITEA__database

On this page