Git hosting, code review, issues, packages and CI in one service, run in Switzerland, the EU or your own datacentre, with CI runners on machines of their own. Pilae runs it on your own servers, or in Zurich, Switzerland, and eleven other Pilae Cloud regions.
- Licence
- GPL-3.0-or-later
- Runs on
- Your own hardware, or any of twelve Pilae regions — six of them in Switzerland and the EU
- Upgrades
- Pinned, tested against your configuration, applied in your window
- Upstream
- forgejo.org
Running Forgejo in production: what it takes
Deploy the server on PostgreSQL
A pinned Forgejo build we have run, on PostgreSQL, with repositories on local disk and LFS, packages and attachments in an S3-compatible bucket from the first day.
Sign in through OIDC, offboard in Forgejo too
OpenID Connect through Keycloak or Microsoft Entra ID, accounts created on first sign-in, and directory groups mapped to organisation teams at each sign-in. The directory does not reach SSH keys and access tokens, so offboarding also disables the Forgejo account.
Run CI on isolated runners
Forgejo Runner on machines of its own, jobs in unprivileged containers, ephemeral runners where the risk warrants it, and actions fetched from mirrors on your instance rather than from the internet.
Capture all three at one moment
Database, repositories and bucket are captured together, daily, encrypted, to an offsite location in your chosen country. Once a month we restore the set into a scratch instance and clone a repository from it.
Upgrade, then run forgejo doctor
Forgejo refuses to start an older release on a database a newer one has migrated, so the rollback is the backup taken just before. The Pilae Agent tests each upgrade on a copy, waits for your approval, applies it in your window, checks it with forgejo doctor and records it in the console.
What Forgejo is, and who runs it
Self-hosted Forgejo for Git, code review and CI
Forgejo is a software forge: Git hosting with pull requests and code review, issues and project boards, a wiki, releases, a package registry and CI through Forgejo Actions. The registry takes more than twenty formats, container images, npm, Maven and PyPI among them; where images also need vulnerability scanning, a Docker Hub proxy cache or replication between sites, Harbor sits beside it. Forgejo is a single Go program, light enough that the machine is rarely the constraint, and it covers what most teams use GitHub or GitLab for day to day.
The project began in 2022 as a fork of Gitea, after Gitea’s domains and trademark were transferred to a for-profit company. It has been a hard fork since early 2024. It is governed by its contributors, under the umbrella of Codeberg e.V., a non-profit association registered in Berlin that holds its domains. A Gitea instance up to 1.22 upgrades to Forgejo in place; newer ones move across through the migration tool.
Forgejo runs on a dedicated machine on your own hardware or in a Pilae Cloud region, Zurich or one of five in the EU among the 12 we run, and answers only on your private network. Source code, its history and the secrets CI uses to deploy it are often the most sensitive things an engineering team holds, and they stay in the jurisdiction you picked.
Forgejo in production: CI runners, backups and upgrades
CI is the part that needs care. Whoever can change a workflow can run code on the runner, so runners go on machines of their own, jobs run in unprivileged containers, and actions resolve from mirrors on your instance. Sign-in goes through Keycloak or Entra ID over OpenID Connect, with directory groups mapped to teams, and self-registration stays off. Probes check the instance every 60 seconds and alert an engineer.
Forgejo’s documentation is candid about backups. A consistent one needs the database, the repositories and the bucket captured at the same point in time, and the database copy inside its all-in-one dump has long-standing bugs. So the nightly backup stops Forgejo while it runs, at an hour you choose, takes all three with their own tools, and sends them encrypted to an offsite location in your chosen country. Every month we restore the set into a scratch instance. Upgrades go through the Pilae Agent, tested on a copy, approved by you and applied in your window, with the pre-upgrade backup as the rollback.
Forgejo licence: GPL, with no paid edition
Forgejo and Forgejo Runner are both GPL-3.0-or-later. Releases before October 2024 were MIT, and files inherited from Gitea keep their MIT headers inside the GPL whole. Every feature ships in the one release: there is no paid edition and no enterprise folder, and the project has registered no trademarks. The GPL’s obligations attach when you distribute the software, and running it for your own organisation triggers none of them. If you need the wider scope GitLab bundles, we operate GitLab as well. Pricing for our operation is on request. Talk to us about the repositories you want to move off GitHub.
Forgejo system requirements
Before anything is deployed, this is what has to exist. We size it with you in the first session, and we say so when your own hardware is already enough.
- CPU and memory
- 2 vCPU · 4 GBOur starting size for the Forgejo server. Upstream sets no minimum. Large repositories and many mirrors are what grow it, and runners are sized separately.
- Database
- PostgreSQL 14+Upstream also supports MySQL 8.4+, MariaDB 10.6+ and SQLite, which it suggests for low to moderate activity. Moving to another database later is, in its own words, not a trivial task, so we start on PostgreSQL.
- Storage
- Local disk + S3 bucketGit repositories live on a filesystem. LFS objects, packages, attachments and Actions logs and artifacts go to an S3-compatible bucket. Code search across repositories needs about six times the repository size on disk, so it is sized before it is switched on.
- CI runners
- Forgejo Runner, separate machineA runner executes whatever a workflow tells it to, and upstream says plainly that this is remote code execution. Runners sit on machines of their own, with no privileged containers and no route to anything they do not need.
- Network
- HTTPS 443 · SSH 2222The web interface and Git over HTTPS go through the Pilae gate if you publish them. Git over SSH answers on the private network only, on a port apart from the machine's own SSH.
Migrating from GitHub to Forgejo
Forgejo's migration tool reads a GitHub repository through the API and brings across the code, issues, pull requests with their reviews, labels, milestones, releases, the wiki and LFS objects. Comments keep their author's GitHub name, and are tied to a Forgejo account only where that person has linked a GitHub login. Actions secrets stay behind, because GitHub never lets them be read back, and so do Discussions, Projects, branch protection rules, webhooks and access permissions. CI is the long part. Forgejo runs the workflows in .github/workflows as it finds them, and many fail on the first run. Forgejo Actions is designed to be familiar rather than compatible, and most runners default to a small Debian image with Node.js where GitHub offers a much larger Ubuntu one.
List what does not travel
Per repository: Actions secrets, webhooks, deploy keys, branch protection and app integrations. None of it comes across in the import, so each item gets an owner and a line in the runbook before anything moves.
Prove the workflows on a trial import
Runners with the labels your workflows ask for go up first. A few representative repositories are imported and their workflows run on Forgejo, and we fix what breaks while GitHub is still where people work.
Import in batches
Each repository comes across in one import, history, issues and pull requests together. The GitHub API rate limit sets the pace for a large organisation, so we move repositories in batches and freeze each batch on GitHub as it goes.
Switch remotes, archive GitHub
Developers add their SSH keys to Forgejo and point their remotes at it. The GitHub repositories are archived read-only, and old links keep resolving until you decide to delete them.
Forgejo configuration: storage, sign-in and CI
; /etc/forgejo/app.ini (excerpt), acme, zur1 [server] DOMAIN = git.acme.internal ROOT_URL = https://git.acme.internal/ SSH_DOMAIN = git.acme.internal SSH_PORT = 2222 LFS_START_SERVER = true [database] DB_TYPE = postgres HOST = db-01.internal:5432 NAME = forgejo USER = forgejo SSL_MODE = require [repository] ROOT = /srv/forgejo/repositories [storage] STORAGE_TYPE = minio MINIO_ENDPOINT = s3.zur1.internal MINIO_BUCKET = acme-forgejo MINIO_USE_SSL = true [security] INSTALL_LOCK = true SECRET_KEY_URI = file:/run/secrets/forgejo_secret_key [service] REQUIRE_SIGNIN_VIEW = true ENABLE_INTERNAL_SIGNIN = false ALLOW_ONLY_EXTERNAL_REGISTRATION = true [oauth2_client] ENABLE_AUTO_REGISTRATION = true USERNAME = preferred_username [actions] ENABLED = true ; uses: actions/checkout resolves to a mirror on this instance DEFAULT_ACTIONS_URL = https://git.acme.internal [migrations] ; during the move from GitHub only; release assets and LFS come from githubusercontent.com ALLOWED_DOMAINS = github.com, *.github.com, *.githubusercontent.com
What Pilae is responsible for
A pinned version
A version we have run, not whatever latest resolves to that day.
A runbook
What it depends on, how it fails, what to do about it. In your repository.
A restore drill
Backups restored on a schedule. A backup nobody has restored is a file.
A patch window
Security updates in a window you agreed, with a rollback ready.
Someone watching
Every endpoint probed on the minute. An alert reaches a person, not a dashboard nobody opens.
- Where it runs
- zur1, fra1, fal1, gra1, ams1, hel1, lon1, ash1, hil1, sin1, tok1, syd1, on-premZurich, Frankfurt, Falkenstein, Gravelines, Amsterdam, Helsinki, London, Ashburn, Hillsboro, Singapore, Tokyo, Sydney, Your own hardware
- Who holds the credentials
- You do. Ours are separate, named, logged and revocable with one command. We ask before anything changes outside an agreed window.
- If you leave
- The machine, the data, the compose files and the runbook are already yours. Nothing stops when our access does.
What drives the price of running Forgejo
Pricing is on request: a fixed price for onboarding, then a monthly price for Forgejo, quoted in writing within five business days. The plans set what every deployment includes; these are the inputs the quote is built from.
- Instance size
- The CPU, memory and, where a model runs, the GPUs the app needs for your users and your data.
- High availability
- One machine with tested restores, or a replicated setup that keeps serving when a node fails.
- Storage and backups
- How much data it holds, how long backups are kept, and point-in-time recovery for its database.
- Plan and support
- Essential, Business or Enterprise: support hours, response times in the contract and how often we review the service with you.
- Region
- Your own hardware, where the infrastructure is already yours, or a Pilae Cloud region, where it is passed through at cost plus a fixed margin.
- Sign-on and integrations
- Single sign-on, directory sync, mail relays and the other systems the app has to reach.
Forgejo: common questions
Is Forgejo open source?
Will our GitHub Actions workflows run on Forgejo?
Where do our repositories live?
Can we sign in with Microsoft Entra ID or Keycloak?
How does Forgejo compare with GitLab?
Also in engineering and security
GitLab
Git repositories, merge requests, CI/CD pipelines and registries in one application, run on your own hardware or in Swiss and EU regions, with runners on machines you place.
Replaces GitHub Enterprise Cloud, GitLab.com, Azure DevOps
Harbor
A private container registry that scans and replicates your images and caches Docker Hub, run in Switzerland, the EU or your own datacentre.
Replaces Docker Hub, Amazon ECR, Azure Container Registry
OpenBao
Secrets, certificates and encryption keys for your applications, run on your own hardware or in a Pilae region, with the unseal keys held by you rather than by us.
Replaces HashiCorp Vault, HCP Vault Dedicated, AWS Secrets Manager
Bring us your Forgejo. We will tell you what it takes.
Thirty minutes on the deployment you already have, or the one you are about to start.