Forgejo: self-hosted Git forge with Docker Compose

Install Forgejo with Docker Compose, then see how this Git forge compares with Gitea, GitLab CE, Gogs and OneDev and which one fits a home server or a small team.

Forgejo is a lightweight, self-hosted software forge: Git repositories with a web interface, pull requests, issues, a wiki, packages and CI. It looks and feels like GitHub, runs from a single container and needs no external services in its simplest setup. The project is developed by a community under Codeberg e.V., a non-profit, and describes itself as exclusively free software.

Forgejo started in October 2022 as a fork of Gitea. Since early 2024 it is a hard fork with its own codebase. If you only want a place for your own repositories, the two are close in daily use, and the comparison below is meant to help you pick.

What you need

  • A server with Docker and the Compose plugin
  • A domain or subdomain and a reverse proxy with HTTPS if the forge will be reachable from the internet
  • Free ports 3000 for the web interface and 222 for Git over SSH, or other ports of your choice

If you do not want to host it yourself, Codeberg runs a public Forgejo instance where anyone can create an account.

Install

Create a folder and give the container user ownership of the data directory. The Forgejo documentation warns that the container may not start otherwise:

mkdir -p forgejo-app/forgejo
cd forgejo-app
sudo chown 1000:1000 forgejo

Create docker-compose.yml in that folder. This is the example from the Forgejo documentation for the current stable release, which stores data in SQLite:

networks:
  forgejo:
    external: false

services:
  server:
    image: codeberg.org/forgejo/forgejo:17
    container_name: forgejo
    environment:
      - USER_UID=1000
      - USER_GID=1000
    restart: always
    networks:
      - forgejo
    volumes:
      - ./forgejo:/data
      - /etc/localtime:/etc/localtime:ro
    ports:
      - '3000:3000'
      - '222:22'
  • USER_UID and USER_GID must match the owner of the ./forgejo folder.
  • 222:22 publishes Git over SSH on port 222, so it does not clash with the SSH daemon of the host.
  • If a reverse proxy runs on the same server, change the first port line to '127.0.0.1:3000:3000' so that the web interface is reachable only through the proxy.
  • If codeberg.org is not reachable from your server, use the project’s mirror: replace codeberg.org with data.forgejo.org in the image name.

Start it:

docker compose up -d

Set your address and SSH port

Forgejo builds the clone links from its own settings. Behind a domain and with SSH on port 222, tell it so by adding three variables to the environment block:

      - FORGEJO__server__ROOT_URL=https://git.example.com/
      - FORGEJO__server__SSH_DOMAIN=git.example.com
      - FORGEJO__server__SSH_PORT=222

Any app.ini setting can be set this way. The pattern is FORGEJO__<section>__<KEY>, so [server] ROOT_URL becomes FORGEJO__server__ROOT_URL. Environment variables can add or change values, not remove them. After editing run docker compose up -d again.

First run

Open http://<host>:3000. With no database configured Forgejo uses SQLite, which the documentation recommends for an instance with low or moderate activity. Finish the onboarding page and register the first user: that account becomes the administrator.

Then close registration, otherwise anyone who finds the address can create an account. Add this variable and apply it with docker compose up -d:

      - FORGEJO__service__DISABLE_REGISTRATION=true

After that only an administrator can create users. To test SSH, add your public key in the account settings and run ssh -F /dev/null git@git.example.com -p 222, the check the Forgejo documentation suggests. It should authenticate with your key and not ask for a password.

The project keeps a page of recommended settings for different instance sizes, for example a size-limited cache for small servers and committer as the signature trust model if people contribute to each other’s repositories.

Use PostgreSQL instead of SQLite

SQLite needs no maintenance and is fine for one person or a small team. For many users or heavy use the documentation recommends PostgreSQL or MySQL. Moving an existing instance to another database later is not trivial, so decide before you fill it with data.

The official example uses PostgreSQL 14. Forgejo needs 14 or newer, and 14 reaches the end of its community support in November 2026, so this version uses 17:

networks:
  forgejo:
    external: false

services:
  server:
    image: codeberg.org/forgejo/forgejo:17
    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=change-me
    restart: always
    networks:
      - forgejo
    volumes:
      - ./forgejo:/data
      - /etc/localtime:/etc/localtime:ro
    ports:
      - '3000:3000'
      - '222:22'
    depends_on:
      - db

  db:
    image: postgres:17
    restart: always
    environment:
      - POSTGRES_USER=forgejo
      - POSTGRES_PASSWORD=change-me
      - POSTGRES_DB=forgejo
    networks:
      - forgejo
    volumes:
      - ./postgres:/var/lib/postgresql/data

Use the same password in both places. The database is not published outside the Docker network.

CI with Forgejo Actions

Forgejo Actions runs continuous integration from workflow files in the .forgejo/workflows folder of a repository, in a format close to GitHub Actions. It is enabled by default, but Forgejo itself does not run the jobs. A separate program, Forgejo Runner, fetches jobs from your instance and executes them. It can run as a binary, as a Docker container or from a distribution package, and one runner can serve several instances.

The steps are in the documentation: install the runner, register it with your instance, then choose its labels in the runner configuration. Read the page on securing Actions deployments first: a runner executes code from your repositories, so run it on a separate machine or in an isolated environment, not next to the forge and its data. Building container images in workflows needs extra Docker access configuration, described in the same documentation.

Backup

The documentation advises stopping Forgejo during a backup, because data lives in several places that cannot easily be copied consistently while it runs. With the SQLite setup above, everything is under ./forgejo:

docker compose stop
tar czf forgejo-backup.tar.gz forgejo
docker compose start

With PostgreSQL also dump the database (pg_dump, or the tool of your database engine). In either case keep the app.ini file: it contains SECRET_KEY and JWT_SECRET. Without them a restored instance cannot read some encrypted values and the integrations that use OAuth have to be set up again.

Updating

For minor and patch updates under the same tag:

docker compose pull && docker compose up -d

Moving to a new major version (for example from 17 to 18) is a separate task. The upgrade guide asks for a full backup first, reading the release notes for breaking changes, emptying the job queues with forgejo manager flush-queues and, after the update, running forgejo doctor check --all inside the container and checking the main workflows in the web interface. Then change the image tag in docker-compose.yml and run the commands above.

Forgejo follows semantic versioning since 7.0: breaking changes appear only when the first number changes. To hear about security releases in advance, watch the security announcements repository on Codeberg.

Moving from Gitea

Forgejo supports an in-place upgrade from Gitea only up to Gitea 1.22. The upgrade goes through Forgejo 10, and from there to any newer version. The project announced that newer Gitea versions can no longer be upgraded this way, because the two codebases have diverged. If you run a recent Gitea, move repositories one by one with the built-in migration tool, which keeps working as long as the Gitea API stays stable.

Forgejo compared with other self-hosted forges

All of these host Git repositories on your own server. They differ in weight, in how much of the DevOps cycle they cover and in who controls the project. Facts below come from each project’s own documentation and repository on 13 November 2026.

License Built-in CI Footprint Fits
Forgejo GPL-3.0-or-later (MIT up to v8) Forgejo Actions with a separate runner Light, single container Home server, small team, free-software focus
Gitea MIT Gitea Actions Light, single container Same as Forgejo, company-backed project
GitLab CE MIT for the Community Edition; the paid edition’s code in ee/ has its own licence GitLab CI/CD Heavy: 8 vCPU and 16 GB RAM baseline, at least 8 GB Larger organizations that want one platform
Gogs MIT Not in its feature list Very light: 512 MB RAM and 2 cores for a team A minimal Git service on a Raspberry Pi
OneDev MIT Built-in CI/CD with a GUI job editor Java, at least 2 GB of memory CI-centric teams, code search and navigation
Harness Open Source Apache-2.0 Pipelines, the successor of Drone Its quick start mounts the Docker socket Pipelines, dev environments and package registries in one tool

Forgejo and Gitea

Both come from Gogs and share the same history, so the interface, the concepts and the Git behaviour are similar. The differences are mostly about governance and licence.

  • Governance. Forgejo is under Codeberg e.V., a non-profit. By Forgejo’s account, Gitea is controlled by a for-profit company through its domain and trademark, and Forgejo was created in October 2022 after those were transferred to it.
  • License. Forgejo has been GPL v3 or later since version 9. Gitea is MIT. For running your own instance the difference does not matter. It matters if you modify the code and distribute it, or if you want a permissive licence on principle.
  • Free software only. Forgejo says it is developed and released with free software only, using Forgejo itself and Forgejo Actions. It describes Gitea as open core, with some software not published under a free licence, and developed on GitHub. This is Forgejo’s own account from its comparison page; Gitea’s side is not covered here.
  • Releases. Forgejo publishes a stable release every three months and an LTS every year, with semantic versioning. Gitea has its own release cycle.
  • Federation. Forgejo works on forge federation based on ForgeFed. The project calls it experimental and reserves the right to break it without notice, so do not build on it yet.
  • Compatibility. The two are no longer interchangeable. A switch from a modern Gitea is a manual migration.

The others

  • GitLab CE is a complete DevOps platform: CI/CD, container registry, issue boards and more in one product. The price is resources. The official requirements for a single node are 8 vCPU and 16 GB of RAM, with 8 GB as the floor for a memory-constrained installation. For one person or a handful of repositories it is far too much.
  • Gogs is the project both Gitea and Forgejo descend from. It does one thing: Git hosting with issues, pull requests and a wiki, on very modest hardware. It has no CI in its feature list, so pair it with an external CI tool.
  • OneDev is a Java application with CI/CD built in (jobs can be created in a GUI or as code), code search and navigation, issue boards and a service desk. It suits teams for whom the pipeline is the centre of the work. It asks for at least 2 GB of memory, more than Gogs.
  • Harness Open Source combines code hosting, pipelines, hosted development environments and artifact registries. Its pipeline part continues Drone. It is more of a platform than a lightweight forge.

Which one to choose

  • For a personal server or a small team, Forgejo or Gitea. There is no large technical gap in everyday use, so choose by principle: take Forgejo if non-profit governance, a copyleft licence and a free-software-only project matter to you, and Gitea if you prefer MIT and a company-backed roadmap or already run it.
  • If memory is tight, for example a Raspberry Pi with little RAM, Gogs.
  • If you want a large platform with built-in CI/CD and have the hardware, GitLab CE.
  • If CI/CD is the main goal, look at OneDev, or run Forgejo with Forgejo Actions.

Whichever you pick, decide before you migrate everything: moving between these forges later means moving repositories one at a time.