Forgejo Git Hosting Installation

Forgejo is a community-driven, lightweight self-hosted Git platform forked from Gitea, with a focus on openness and federation. This guide covers installing Forgejo on Linux via Docker, setting up Forgejo Actions CI/CD, federation support, and migrating from Gitea.

Prerequisites

  • Ubuntu 20.04+/Debian 11+ or CentOS 8+/Rocky Linux 8+
  • Docker and Docker Compose (for Docker install)
  • A domain name with DNS configured
  • 512 MB RAM minimum (1 GB+ recommended)
  • Root or sudo access

Installing Forgejo with Docker

Docker is the recommended method for easy updates:

mkdir -p /opt/forgejo/{data,config}

cat > /opt/forgejo/docker-compose.yml << 'EOF'
version: '3.8'
services:
  forgejo:
    image: codeberg.org/forgejo/forgejo:7
    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=forgejo_password
    volumes:
      - ./data:/data
    ports:
      - "3000:3000"
      - "2222:22"
    depends_on:
      - db
    restart: unless-stopped

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

cd /opt/forgejo
docker compose up -d
docker compose logs -f forgejo

Binary Installation

For a non-Docker setup:

# Create a dedicated user
sudo adduser --system --no-create-home --group forgejo
sudo mkdir -p /var/lib/forgejo /etc/forgejo
sudo chown forgejo:forgejo /var/lib/forgejo
sudo chmod 750 /var/lib/forgejo

# Download the latest binary from Codeberg
VERSION=$(curl -s https://codeberg.org/api/v1/repos/forgejo/forgejo/releases \
  | python3 -c "import sys,json; releases=json.load(sys.stdin); print(releases[0]['tag_name'])")

wget "https://codeberg.org/forgejo/forgejo/releases/download/${VERSION}/forgejo-${VERSION#v}-linux-amd64" \
  -O /usr/local/bin/forgejo

chmod +x /usr/local/bin/forgejo

# Create systemd service
sudo tee /etc/systemd/system/forgejo.service << 'EOF'
[Unit]
Description=Forgejo
After=network.target postgresql.service

[Service]
Type=simple
User=forgejo
Group=forgejo
WorkingDirectory=/var/lib/forgejo/
ExecStart=/usr/local/bin/forgejo web --config /etc/forgejo/app.ini
Restart=on-failure
Environment=USER=forgejo HOME=/var/lib/forgejo FORGEJO_WORK_DIR=/var/lib/forgejo

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now forgejo

Initial Setup

Navigate to http://your-server:3000 for the web installer.

Key settings to configure:

  • Database: PostgreSQL (recommended) or SQLite for small instances
  • Site URL: Must match your actual domain for clone URLs to work
  • Administrator account: Create the first admin user

Or configure via app.ini before first run:

sudo tee /etc/forgejo/app.ini << 'EOF'
APP_NAME = My Forgejo Instance
RUN_MODE = prod
RUN_USER = forgejo

[server]
DOMAIN           = git.yourdomain.com
HTTP_PORT        = 3000
ROOT_URL         = https://git.yourdomain.com/
SSH_DOMAIN       = git.yourdomain.com
START_SSH_SERVER = false

[database]
DB_TYPE = postgres
HOST    = 127.0.0.1:5432
NAME    = forgejo
USER    = forgejo
PASSWD  = forgejo_password
EOF

Set up Nginx reverse proxy:

server {
    listen 443 ssl;
    server_name git.yourdomain.com;

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

    location / {
        proxy_pass http://127.0.0.1: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;
    }
}

Forgejo Actions CI/CD

Enable Actions in app.ini:

[actions]
ENABLED = true

Install and register a runner:

# Download forgejo-runner
wget https://code.forgejo.org/forgejo/runner/releases/download/v3.4.1/forgejo-runner-3.4.1-linux-amd64 \
  -O /usr/local/bin/forgejo-runner
chmod +x /usr/local/bin/forgejo-runner

# Register (get token from Site Admin > Runners > Create Runner)
forgejo-runner register \
  --instance https://git.yourdomain.com \
  --token RUNNER_TOKEN \
  --name production-runner \
  --labels ubuntu-latest:docker://node:20-bullseye

# Start the runner
forgejo-runner daemon

Example Actions workflow:

# .forgejo/workflows/ci.yaml
on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Build
        run: make build
      - name: Test
        run: make test

Federation Configuration

Forgejo supports ActivityPub federation (experimental), allowing users to follow repositories and stars across instances:

# /etc/forgejo/app.ini
[federation]
ENABLED = true
sudo systemctl restart forgejo

Users on other Forgejo/Gitea instances can follow repositories using the format [email protected]/repo.

Migrating from Gitea

Forgejo is a drop-in replacement for Gitea. Migration is straightforward:

# 1. Stop Gitea
sudo systemctl stop gitea

# 2. Backup Gitea data
sudo -u gitea gitea admin dump --config /etc/gitea/app.ini \
  --file /backup/gitea-backup.zip

# 3. Copy the data directory
sudo cp -r /var/lib/gitea/* /var/lib/forgejo/

# 4. Copy the configuration
sudo cp /etc/gitea/app.ini /etc/forgejo/app.ini

# 5. Run Forgejo migration
sudo -u forgejo forgejo migrate --config /etc/forgejo/app.ini

# 6. Start Forgejo
sudo systemctl start forgejo

All repositories, users, issues, and settings are preserved. Verify by browsing the web UI.

Administration Tasks

# Create an admin user via CLI
forgejo admin user create \
  --username admin \
  --password securepassword \
  --email [email protected] \
  --admin \
  --config /etc/forgejo/app.ini

# Reset a user's password
forgejo admin user change-password \
  --username alice \
  --password newpassword \
  --config /etc/forgejo/app.ini

# Regenerate Git hooks
forgejo admin regenerate hooks --config /etc/forgejo/app.ini

# Clean up old sessions
forgejo admin auth delete-user --username staleuser --config /etc/forgejo/app.ini

Troubleshooting

Cannot push via SSH:

# Verify SSH port is open
ss -tlnp | grep 2222

# Test SSH connection
ssh -T -p 2222 [email protected]

# Check authorized_keys permissions
ls -la /var/lib/forgejo/.ssh/

Actions runner not showing as online:

# Check runner logs
journalctl -u forgejo-runner -f

# Verify the runner token hasn't expired
# Regenerate from Site Admin > Runners

Database connection errors:

# Test database connectivity
psql -h 127.0.0.1 -U forgejo -d forgejo -c '\l'

# Check app.ini database section
sudo -u forgejo forgejo doctor check --config /etc/forgejo/app.ini

Webhook deliveries failing:

Check Site Administration > System Status > Queues for stuck jobs, and review individual webhook delivery logs under the repository settings.

Conclusion

Forgejo provides a lightweight, community-governed Git hosting platform that works as a seamless Gitea replacement. Its built-in Actions runner, federation support, and active community development make it a strong choice for self-hosted Git infrastructure. Updates release regularly, so monitor the Codeberg releases page and update promptly.