Self-Hosted Version Control
IntermediateYour team's Git hosting on your own server, with Gitea or Forgejo running in Docker.
Published 16 October 2026
About Self-Hosted Version Control
Gitea and Forgejo are lightweight Git platforms you run yourself. Each gives a team repositories, pull requests with code review, issues, project boards, wikis, and a package registry in one Go program, in a web interface laid out like GitHub's. Forgejo began as a fork of Gitea in 2022 and has been a hard fork since 2024, so the two look alike but no longer swap in place, and moving between them later is a migration, not a change of image tag. Gitea is MIT licensed and backed by a company that sells an Enterprise edition; Forgejo is GPL licensed and owned by a non-profit.
The container setup is small. The Git server runs in one container with a data folder: the web interface on port 3000, a built-in SSH server on port 22 inside the container, and a /data volume holding the repositories, the app.ini configuration, large-file objects, attachments, and packages. The metadata lives in a database, PostgreSQL by default, with SQLite for a handful of people and MySQL if you already run it. The core is that container, the database, Docker, and a server of a couple of gigabytes.
Web and SSH take different routes. The web interface goes behind a reverse proxy or a deploy platform that adds HTTPS, and the public URL in the configuration must match it so that clone links and webhooks are right. Git over SSH is a plain TCP connection that an HTTP proxy cannot carry, so either publish the SSH port on a host port such as 222 or 2222, because the host's own SSH daemon already holds 22, or have users clone over HTTPS. Turn open registration off before the address is public, since sign-up forms attract spam accounts quickly.
CI is built in, with a separate runner. Gitea Actions and Forgejo Actions run workflow files committed to a repository, but the server only schedules the jobs: a runner program that you install and register with a token picks them up and runs them, usually in Docker containers. Keep the runner on another machine when you can, since it runs your code and needs access to Docker. Gitea's workflows are mostly compatible with GitHub Actions, and Forgejo's are familiar to its users but not designed to be, so pipelines moved over may need edits.
Key Features
- ✓Gitea or Forgejo in Docker, from the project's own container image
- ✓Pull requests, code review, issues, project boards, and wikis in one lightweight program
- ✓PostgreSQL by default for the metadata, with SQLite or MySQL as alternatives
- ✓A web interface plus a built-in SSH server, so Git works over HTTPS or SSH
- ✓A package registry for container images, npm, PyPI, and more
- ✓Built-in Actions CI that runs on a separate runner you install
- ✓Repository migration from GitHub, GitLab, and other forges, with issues and pull requests
- ✓A server of a couple of gigabytes is enough for a small team
When to Use Self-Hosted Version Control
- →A private home for a company's or agency's code without per-seat hosting fees
- →Keeping source code on infrastructure in a chosen country or network for compliance
- →A lightweight Git server for a homelab or an internal team
- →Mirroring repositories from GitHub as a backup or a fallback
- →A self-managed forge for a school, a community, or an open-source group
Pros
- Free and open source, with every core feature included
- Light on resources: a small server serves a whole team
- A familiar GitHub-style workflow, with importers for GitHub and GitLab repositories
- One container and one database, so backups and upgrades stay simple
Cons
- Updates, backups, uptime, and spam control are yours to run
- Git over SSH needs its own published port, which an HTTP proxy cannot carry
- CI needs a separate runner that you install and secure, and workflows may need edits when moved from GitHub
- A smaller ecosystem of integrations than GitHub or GitLab, and the two projects are no longer interchangeable
Database Options for Self-Hosted Version Control
The default, and the engine both projects' Docker guides show as their database example. It holds users, repository metadata, issues, pull requests, comments, and Actions run records, but not the Git repositories themselves, which are files in the data folder. Gitea needs PostgreSQL 12 or newer and Forgejo 14 or newer. It is the usual choice once more than a handful of people push at once, and the project's dump command bundles its contents with the repositories.
The simplest start: one file in the data folder and nothing else to run, so the whole instance is a single folder to back up. Gitea's own docs say SQLite does not scale well for a growing instance, and it suits a few people better than a team. Moving to PostgreSQL later means migrating the data, not flipping a setting, so choose it knowing the instance may stay small. Forgejo's official binary includes SQLite support.
Supported by both projects with the InnoDB engine: MySQL 8.0 or newer for Gitea and 8.4 or newer for Forgejo. It holds the same metadata as PostgreSQL, with no advantage for a new install, so pick it when MySQL already runs on the server and you would rather not add a second engine. Take its dump together with the data folder, since a restore needs both.
These are highlighted picks. To see all the tools, check the Databases category.
Hosting Options for Self-Hosted Version Control
The default. A shared-vCPU server with 2 vCPUs and 4 GB of RAM costs about €19 a month, which is more than a small team's Git server needs and leaves room for PostgreSQL, package storage, and a few mirrors on the same box. Install Docker, run the Compose file with a real database password, and allow SSH for administration, HTTPS, and the host port you publish for Git over SSH. Repositories and the database live on the server's disk, so snapshots and dumps are your job.
The budget entry. The KVM 2 plan has 2 vCPUs, 8 GB of RAM, and 100 GB of NVMe at $8.99 a month on a two-year term, $14.99 at the standard rate, a comfortable size for a team Git server with room for packages and large files to grow. Root access is full and the panel adds weekly backups; still take your own dumps with the project's dump command, and set up HTTPS, the Git SSH port, and updates yourself.
A cloud VPS billed per second up to a monthly cap. A 2 GB Droplet is about $12 a month, with snapshots and a cloud firewall in the panel. Managed PostgreSQL, from about $15 a month, can take the metadata database off the Droplet with automated backups, though the repositories stay on the Droplet's disk, so the server is not stateless. Add a block-storage volume when repositories, large files, or packages outgrow the disk.
Your own hardware, a classic home-lab Git server for a small group. Gitea and Forgejo publish arm64 images and are light enough for a Pi 4 or 5 with 4 GB; a Pi 5 costs about $110 once, plus a few dollars of electricity a month. Keep the repositories and database on a USB SSD and not the SD card, since constant writes wear cards out. A home connection sits behind NAT, so pair it with the Tailscale or Cloudflare Tunnel addition to reach it from outside, and run CI on a stronger machine.
These are highlighted picks. To see all the tools, check the Hosting & Cloud category.
Reverse Proxy Options for Self-Hosted Version Control
The family default: it discovers the Git server container from Docker labels and renews certificates itself, with one router for port 3000. It only carries HTTP, so Git over SSH needs the container's SSH port published separately, or a TCP entry point on Traefik. Set the server's public URL to the HTTPS address so clone links and webhooks use it. Traefik has no request-size limit by default, so large pushes over HTTPS go through.
Automatic HTTPS from a short site block that forwards to port 3000, the simplest fit for one Git server container. Caddy has no default request-size limit, so big pushes over HTTPS work without extra settings. It proxies HTTP only: Git over SSH still needs its own published port, and Caddy has no TCP proxy without an add-on. Set the public URL in the Git server to the HTTPS address.
The most familiar proxy, with TLS through Certbot. Raise client_max_body_size well above its 1 MB default, which rejects large pushes and uploads over HTTPS, and lengthen the proxy timeouts for big clones. Pass the Host and X-Forwarded-Proto headers so the server builds HTTPS links. NGINX's stream module can proxy the SSH port as plain TCP if you want Git over SSH on port 22 of a separate address.
Self-Hosted PaaS Options for Self-Hosted Version Control
A free, self-hosted deploy platform with Gitea and Forgejo in its service library, each in versions with PostgreSQL, MySQL, MariaDB, or SQLite, and variants that add a runner. The Gitea template tracks the latest image and publishes the container's SSH on host port 22222, while the Forgejo template pins version 15, behind the current 16, so check the tag before the first start. HTTPS through Coolify's bundled proxy covers the web interface only; Git over SSH uses that published port directly.
Free and self-hosted, with templates for Gitea on PostgreSQL (a generated database password and large-file storage switched on), Gitea on SQLite, and Forgejo on PostgreSQL 17, served on your domain with HTTPS through its bundled Traefik. The Forgejo template ships with the database password set to forgejo in the file, so change it before the first start. The templates expose the web port only and do not publish SSH, so Git over SSH needs a port mapping you add. Check the pinned image tags.
Free and self-hosted, with no template: create the app, deploy the project's official image with git:from-image, link the official PostgreSQL plugin, and mount storage at /data. Dokku uses the server's SSH port for its own git push, so publish the Git server's SSH on another host port with docker-options and put that port in the clone URLs. HTTPS comes from the Let's Encrypt plugin; Dokku's built-in nginx proxies HTTP only. A fit for people who like a command line over a dashboard.
Git Server Options for Self-Hosted Version Control
The default and the larger project, with most of the guides, templates, and one-click catalogs written for it. It is MIT licensed and run by Gitea Ltd, which sells an Enterprise edition with SAML single sign-on, audit logs, and support at $9.50 to $19 per user a month on a one-year commitment; everything else is free. The project publishes its own container images, in a standard and a rootless variant that are not interchangeable, with the web interface on port 3000 and SSH on 22 inside the container. Gitea Actions workflows are mostly compatible with GitHub Actions, so existing .github/workflows files often run once a runner is registered. Pin a version tag rather than latest.
The community-governed alternative: owned by the non-profit Codeberg e.V. and licensed under the GPL, with no commercial edition behind it and no paid tier to be steered toward. Codeberg e.V. also runs Codeberg, the free hosting service built on Forgejo, and its own container registry is where the project's images are published, not Docker Hub, in a standard and a rootless variant. It started as a Gitea fork and has been a hard fork since 2024, so the two cannot be swapped by changing the image tag. Forgejo releases quarterly with a long-term-support version each year, is building federation (ForgeFed) between servers, and keeps workflows in .forgejo/workflows, which its docs call familiar to GitHub Actions users but not designed to be compatible.
Self-Hosted Version Control Add-ons
Each addition below extends this stack with a capability the base stack works fine without. None are required: include the ones your product actually needs when building this stack, and skip the rest.
Tunnel Add-ons
Add a tunnel when you're self-hosting without a static IP or can't open inbound ports — a home server, a VPS behind restrictive network policies, or anywhere a reverse proxy alone can't reach the internet.
The private route, and the best fit for a team forge. Everyone who needs the server installs Tailscale, and both the web interface and Git over SSH are reachable at the server's tailnet address with nothing open to the internet, which also sidesteps the SSH port-mapping question for users on the network. Set the Git server's public URL to the tailnet name so clone links work. Contributors outside your tailnet cannot reach it, so it suits an internal forge more than a public one. The Personal plan is free.
A public HTTPS address through an outbound-only connection, so a Git server behind a home or office connection can be reached with no inbound port open and no static IP. Free, with Cloudflare Access in front if sign-in should sit behind your company login. It carries the web interface and Git over HTTPS; Git over SSH through a tunnel needs the cloudflared client on each user's machine, so most teams tell users to clone over HTTPS. Point it at port 3000 only.
Frequently Asked Questions about Self-Hosted Version Control
Why self-host Gitea or Forgejo instead of using GitHub or GitLab.com?
Mostly for control, not price. GitHub's free plan already includes unlimited private repositories, so a small team rarely saves money. What self-hosting buys is your code and history on a server you choose, in a country or network you choose, with no per-seat billing and no dependence on another company's outages or terms. It also lets a school, agency, or public body run an internal forge. What it costs is operations: you run updates, backups, uptime, and spam control, and you give up GitHub's network and its marketplace of Actions and add-ons. If you want a self-hosted forge with built-in pipelines, registries, and security scanning, the GitLab Self-Hosted stack is the heavier route. Both projects here also have a hosted option: Gitea Cloud is managed Gitea, and Codeberg runs Forgejo for open-source projects.
What size server does a Git server need?
Neither project publishes a hard minimum in its install guide, so treat this as an estimate: about 2 GB of RAM covers Gitea or Forgejo with PostgreSQL on one box for a small team, and both are light enough that a Raspberry Pi serves a small group. Disk is the part that grows. Repositories, large-file objects, and packages all live in the data folder, so size the volume for them and watch it. CI is separate: jobs run on a runner, and a runner that builds containers needs far more CPU and memory than the Git server, which is why it belongs on its own machine. A 2 GB server costs about $12 a month at a cloud provider and less on a long-term VPS plan.
Where does state live, and what needs backing up?
Three places. The data folder holds the Git repositories, large-file objects, attachments, avatars, and packages. The database holds users, issues, pull requests, comments, and Actions run history. The app.ini file holds the secret keys that protect stored credentials, so back it up with the data and keep it private. Both projects have a dump command, gitea dump and forgejo dump, that bundles the repositories, the config, and a database dump into one archive, so run it on a schedule and copy the archive off the server. With SQLite the database is a file in the data folder, which makes that folder nearly everything. Restore onto a test server now and then, because a backup nobody has restored is a guess.
Should I choose Gitea or Forgejo?
They share most features: repositories, pull requests, issues, packages, and a similar interface. The differences are about governance and direction. Gitea is MIT licensed and run by a company that sells an Enterprise edition with single sign-on and audit logs, has the larger community and the most guides and templates, and its Actions are mostly compatible with GitHub Actions. Forgejo is GPL licensed and owned by a non-profit, has no commercial edition, releases on a fixed quarterly and annual long-term-support schedule, and is working on federation between servers, but its Actions are not designed to match GitHub's. Since the 2024 hard fork you cannot swap one for the other by changing the image tag, so decide before the data builds up. Gitea is the safer default; pick Forgejo when licence and governance matter to you.
How do I run CI, and do I need a separate CI server?
Not to start: both projects have CI built in. Gitea Actions reads workflow files from .gitea/workflows or .github/workflows, and Forgejo Actions from .forgejo/workflows with .github/workflows as a fallback. The server only schedules jobs; a separate runner program, registered with a token, picks them up and runs them, usually in Docker containers. Install the runner on another machine when you can, because it runs your code and needs Docker access. Gitea calls its workflows mostly compatible with GitHub Actions, while Forgejo calls its Actions familiar but not designed to be compatible, so expect some edits when moving pipelines from GitHub. A team that prefers a standalone CI server can point it at the repositories with webhooks instead.
Stacks Related to Self-Hosted Version Control
GitLab Self-Hosted
InfrastructureSelf-hosted GitLab with Docker: your code, your CI, your infrastructure.
Strapi Self-Hosted
InfrastructureSelf-hosted Strapi: an open-source headless CMS with PostgreSQL, on a server you control.
Umami Self-Hosted
InfrastructureSelf-hosted Umami: cookie-free, privacy-first website analytics on a server you run.
Sentry Self-Hosted
InfrastructureSelf-hosted Sentry error tracking on your own infrastructure, with PostgreSQL, Redis, ClickHouse, and Kafka under the hood.
Scores
Popularity3/5
Gitea is well known among developers who run their own servers and appears in most self-hosting guides and catalogs, and Forgejo is increasingly recommended there. Outside that circle, GitHub and GitLab are the names developers know.
Learning Curve2/5
A container and a database get a Git server running in an afternoon, and the interface follows GitHub's. The work that takes learning is around it: publishing Git over SSH next to an HTTPS proxy, setting the public URL, switching off open registration, and installing a runner for CI.
Flexibility3/5
Repositories, packages, and Actions cover most team needs, the database is a choice of three engines, and the hosting and exposure layers are open. The integration and extension ecosystem is smaller than GitHub's or GitLab's, and the two projects are no longer interchangeable.
Performance4/5
A Go program that serves a team from a couple of gigabytes of memory, so one small server is enough. CI load sits on separate runners, and very large instances eventually want PostgreSQL and tuning, but few self-hosting teams reach that point.
Portability5/5
Standard Git, MIT or GPL licensed software, and importers for GitHub, GitLab, and other forges mean the code and its history move in and out freely. Only the CI workflow files and issue history need conversion when switching platforms.
Tools in the Self-Hosted Version Control Stack
Self-Hosted Version Control Pricing
Gitea and Forgejo are free, so the fixed cost is a server: about 2 GB of RAM serves a small team, from around $9 a month on a long-term VPS plan. CI runners are a second machine only if you run heavy builds. Nothing is metered. For comparison, Gitea's optional Enterprise edition adds single sign-on and support from $9.50 per user a month.
A small team's Git server needs about 2 GB of RAM: $8.99 a month for an 8 GB plan at Hostinger on a two-year term, about $12 for a 2 GB Droplet at DigitalOcean, and about €19 for a 4 GB shared server at Hetzner. Disk is the part that grows with repositories, large files, and packages.
Gitea and Forgejo include every core feature at no cost, with no user limit. Gitea Enterprise is optional and costs $9.50 to $19 per user a month on a one-year commitment.
The reverse proxies, deploy platforms, and tunnels here are free, open-source software or free tiers, and TLS certificates come from Let's Encrypt.
Self-Hosted Version Control System Requirements
- CPU
- 2 vCPUs
- RAM
- 2 GB
- Disk
- Grows with repositories, large-file objects, and packages
- OS
- Linux with Docker, on amd64 or arm64
No official requirements published — tekyous guidance based on the bundle's services.
An estimate, not a vendor figure: the Gitea and Forgejo install guides state no minimum. Both are single Go programs described as light enough for small hardware, so 2 GB of RAM covers the Git server and PostgreSQL for a small team. CI runners are not included and need their own, larger machine when builds are heavy.