Forgejo with Docker: your own Git server with Actions (Linux, Windows, Mac)
Before you start
- 21 min read
Boxes marked Run in terminal are what you type; plain text explains why. Check what you need first

What you get in one minute#
Forgejo is a free, self-hosted Git forge: repositories, issues, pull requests, a package registry and CI ("Actions") in one small program that you run on your own machine.
Logo: the official Forgejo project (codeberg.org/forgejo/forgejo, assets/logo.svg at v17.0.1)
Use it to keep private code off third-party platforms, to run a Git server for family, friends or a small team, or to mirror projects you depend on. The project says it runs on "nearly every machine", including a Raspberry Pi. A fresh instance with SQLite used about 115 MiB of RAM in our test.
| What | Value (official docs and releases, read October 2026) |
|---|---|
| Current version | Forgejo 17.0.1, released October 2026 (latest stable). Image tag 17.0.1 |
| Licence | GPL 3.0 or any later version (versions before 9.0 were MIT) |
| Time needed | About 15 minutes for the server; 15 more for an Actions runner (our estimate) |
| RAM and size | About 115 MiB RAM idle and a 291 MB image, measured by us on Windows with Docker Desktop and SQLite |
| Ports | 3000/TCP web (we keep it local until HTTPS), 2222/TCP Git over SSH (our choice), 80 and 443 for HTTPS |
| Official docs | forgejo.org/docs and the repository |
At a glance:
- What it is: a hard fork of Gitea, run by a community under the non-profit Codeberg e.V. (see the next section).
- SSH clash solved: the host already uses port 22 for its own SSH, so Forgejo's SSH goes to host port 2222.
- LTS or latest: Forgejo ships a stable release every three months and an LTS release once a year. You pick one before the first start (table below).
- Actions: CI that reads
.forgejo/workflows. Forgejo does not run the jobs; a separate runner does. - Platforms: the server runs in Docker on Linux (best), Windows or Mac. The runner is supported on Linux only.
- Privacy: the update checker is on by default and asks
release.forgejo.org. You can switch it off.
Where it came from, in one honest line#
Forgejo started in December 2022, after former Gitea maintainers objected to control of Gitea moving to the for-profit company Gitea Ltd; it was a soft fork in 2023 and a hard fork from 2024, and Gitea 1.22 is the last version you can upgrade straight to Forgejo.
Stable or LTS?#
| Stable (this guide: 17.0.1) | LTS (15.0.11) | |
|---|---|---|
| Support | Three months, plus two weeks after the next stable | Critical bug and security fixes for one year and three months |
| Ends | 28 January 2027 | 15 July 2027 |
| Upgrade work | A manual step with a backup every quarter | One big step per year; the next LTS is 19.0 in April 2027 |
| Tag | 17.0.1 | 15.0.11 |
The database refuses to start on an older Forgejo, so you cannot go back. Choose before you create your first repository. Everything below works with either tag.
How it fits together#
You reach Forgejo in a browser or with Git over HTTPS through a proxy, or with Git over SSH on port 2222. Everything is stored in one data folder. The runner is optional.
Drawn for this guide from the official docs. Dashed boxes are optional.
Before you start#
Linux: Docker Engine and Docker Compose, any x86_64 or arm64 machine, curl and tar. Windows and Mac: Docker Desktop. Check:
docker --version docker compose version
Checklist:
- [ ] Docker and Docker Compose work (the upgrade notes ask for Docker 20.10.6 or newer)
- [ ] Host port 2222 and local port 3000 are free (
ss -ltnon Linux) - [ ] You decided: stable (17.0.1) or LTS (15.0.11)
- [ ] For the HTTPS section only: a DNS record for the server, and ports 80 and 443 free
Tested on October 2026: Linux = not run, Windows = Docker Desktop (container, install wizard, SSH, CLI, backup and restore), Mac = not run. HTTPS and the runner were not run on any system. The rest comes from the official docs and release files read in October 2026.
Step 1: Create the data folder#
Forgejo keeps everything in one folder. We use ~/docker_volumes/forgejo, as all DIY Lab Hub guides do.
Linux#
mkdir -p ~/docker_volumes/forgejo/data sudo chown -R 1000:1000 ~/docker_volumes/forgejo/data cd ~/docker_volumes/forgejo
The image runs Forgejo as user and group 1000 and the docs say the folder must belong to that ID. If you do not have sudo, run the first and third lines and check id -u shows 1000.
Windows (PowerShell)#
New-Item -ItemType Directory -Force "$HOME\docker_volumes\forgejo\data" | Out-Null Set-Location "$HOME\docker_volumes\forgejo"
Mac (Terminal)#
mkdir -p ~/docker_volumes/forgejo/data cd ~/docker_volumes/forgejo
Check it worked. The folder exists: ls -ld data (Linux, Mac) or Get-Item data (PowerShell).
Tip: Install Docker from the official Docker documentation (docs.docker.com/engine/install). Forgejo's own docs link to it.
Step 2: Write the Compose file and start Forgejo#
This is the official example with four changes: a pinned image, the web port on 127.0.0.1 only, the SSH port moved to 2222, and restart: unless-stopped. FORGEJO__server__SSH_PORT makes the clone URLs show port 2222.
Linux#
cat > docker-compose.yml << 'EOF'
services:
forgejo:
image: codeberg.org/forgejo/forgejo:17.0.1
container_name: forgejo
restart: unless-stopped
environment:
- USER_UID=1000
- USER_GID=1000
- FORGEJO__server__SSH_PORT=2222
volumes:
- ./data:/data
- /etc/localtime:/etc/localtime:ro
ports:
- "127.0.0.1:3000:3000"
- "2222:22"
EOF
docker compose up -d
docker compose ps
Windows (PowerShell)#
@'
services:
forgejo:
image: codeberg.org/forgejo/forgejo:17.0.1
container_name: forgejo
restart: unless-stopped
environment:
- USER_UID=1000
- USER_GID=1000
- FORGEJO__server__SSH_PORT=2222
volumes:
- ./data:/data
- /etc/localtime:/etc/localtime:ro
ports:
- "127.0.0.1:3000:3000"
- "2222:22"
'@ | Set-Content -Encoding ascii docker-compose.yml
docker compose up -d
docker compose ps
Mac (Terminal)#
Same commands as Linux. If Docker complains about the /etc/localtime line, delete that line; the container then shows UTC times.
Check it worked. After a few seconds the web server answers. Real output from our test (Docker Desktop, 17.0.1, with other host ports):
curl -s http://127.0.0.1:3000/api/healthz
{
"status": "pass",
"description": "Forgejo: Beyond coding. We forge."
}
Before the setup wizard has run, the page at / is the installation form.
Tip: Want to reach Forgejo from other PCs at home before HTTPS? Change
127.0.0.1:3000:3000to3000:3000. Never forward that port on your router.
Step 3: Run the setup wizard#
Open http://localhost:3000 on the machine that runs Docker. For a remote server, open an SSH tunnel from your PC first and then use the same address.
Linux#
ssh -N -L 3000:127.0.0.1:3000 <your-user>@<your-server-address>
Windows (PowerShell)#
ssh -N -L 3000:127.0.0.1:3000 <your-user>@<your-server-address>
Mac (Terminal)#
Same command as Linux. Leave the window open, then browse to http://localhost:3000.
On the form, SQLite is already chosen: it is the docs' recommendation for low to moderate activity. Check these fields:
| Field | Set it to |
|---|---|
| Server domain | localhost for now (the HTTPS section changes it) |
| SSH server port | 2222 (already filled in from the Compose file) |
| Forgejo base URL | http://localhost:3000/ for now |
| Administrator account | Open this block and create your admin user here |
In our 17.0.1 test, "Disable self-registration", the update checker, offline mode and "Disable Gravatar" were ticked by default. Keep self-registration disabled for a private server. Untick the update checker if you do not want the weekly version lookup.
Check it worked. You can sign in, and the API reports the version. Real output from our test:
{"version":"17.0.1+gitea-1.22.0"}
Tip: If you skip the admin block, the docs say the first user you register becomes the administrator. Do it yourself right away; do not leave an open registration page on the internet.
Step 4: Push your first repository over SSH#
Git over SSH goes to host port 2222, not 22. Create a key if you have none, add the public key under Settings, SSH keys, and create a repository.
Linux#
ssh-keygen -t ed25519 -C "forgejo" cat ~/.ssh/id_ed25519.pub ssh -p 2222 git@<your-server-address> git clone ssh://git@<your-server-address>:2222/<user>/<repo>.git
Windows (PowerShell)#
ssh-keygen -t ed25519 -C "forgejo" Get-Content "$HOME\.ssh\id_ed25519.pub" ssh -p 2222 git@<your-server-address> git clone ssh://git@<your-server-address>:2222/<user>/<repo>.git
The OpenSSH client ships with Windows 10 and 11. Git for Windows provides git.
Mac (Terminal)#
Same commands as Linux.
Check it worked. The ssh -p 2222 test prints a greeting and closes. Real output from our test:
Hi there, doctest! You've successfully authenticated with the key named t, but Forgejo does not provide shell access.
Your user name and key name replace doctest and t. The clone URL on the repository page shows the same :2222 form.
Tip:
Permission denied (publickey)almost always means the public key is not saved in Forgejo for that user, orsshoffered another key. Add-i ~/.ssh/id_ed25519 -o IdentitiesOnly=yesto the test.
Put it behind HTTPS (with or without Traefik)#
For a server with a domain, put the web interface behind HTTPS so it is reached at https://git.<your-domain> and needs no web port on the host. Home-only users can keep localhost:3000 and skip this step. Git over SSH stays on port 2222 directly: a proxy for web traffic does not carry it. Both routes need a DNS record for the domain.
First tell Forgejo its public address. Add these lines under environment: in docker-compose.yml and remove the 127.0.0.1:3000:3000 port line:
- FORGEJO__server__DOMAIN=git.<your-domain>
- FORGEJO__server__SSH_DOMAIN=git.<your-domain>
- FORGEJO__server__ROOT_URL=https://git.<your-domain>/
The docs' reverse proxy page warns that the links Forgejo generates break when ROOT_URL is wrong. The image's default config trusts one proxy in front of it (REVERSE_PROXY_LIMIT = 1). Note that environment variables can add and change values in app.ini but not remove them.
With Traefik#
On a server that already runs Traefik v3 with the Docker provider, add the proxy network and labels. Forgejo's docs have no Traefik page; these are standard Traefik labels, with an entrypoint named https as in our other guides. Create the network once:
docker network create proxy
Add this to the Forgejo service, and this block at the end of the file:
networks:
- proxy
labels:
- "traefik.enable=true"
- "traefik.docker.network=proxy"
- "traefik.http.routers.forgejo.rule=Host(`git.<your-domain>`)"
- "traefik.http.routers.forgejo.entrypoints=https"
- "traefik.http.routers.forgejo.tls=true"
- "traefik.http.services.forgejo.loadbalancer.server.port=3000"
networks:
proxy:
external: true
Then run docker compose up -d. Check it worked. curl -I https://git.<your-domain>/ returns an HTTP status line over HTTPS and the page opens with a valid certificate.
Without Traefik: Caddy#
Choose this if you have no Traefik. Caddy gets and renews its own certificates. The Forgejo docs show this Caddyfile for a public domain: git.example.com { reverse_proxy 127.0.0.1:3000 }, and say Caddy gets certificates for the domain by itself.
| Case | What to do |
|---|---|
| Public domain | A DNS A record to the server, ports 80 and 443 open. Caddy uses Let's Encrypt |
| Home only, no domain | tls internal: Caddy's own local certificate. Trust its root on each device |
Put Forgejo on the shared proxy network (the networks lines from the Traefik block, without the labels), then run Caddy in Docker:
docker network create proxy
mkdir -p ~/docker_volumes/caddy/{data,config}
cd ~/docker_volumes/caddy
Save as ~/docker_volumes/caddy/docker-compose.yml (the image is caddy:2.11.7, the latest Caddy release in October 2026):
services:
caddy:
image: caddy:2.11.7
container_name: caddy
restart: unless-stopped
ports:
- "80:80/tcp"
- "443:443/tcp"
- "443:443/udp"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- ./data:/data
- ./config:/config
networks:
- proxy
networks:
proxy:
external: true
Save as ~/docker_volumes/caddy/Caddyfile for a public domain:
git.example.com {
reverse_proxy forgejo:3000
}
For a home-only name, use tls internal:
git.home.arpa {
tls internal
reverse_proxy forgejo:3000
}
Start both stacks, Caddy first:
cd ~/docker_volumes/caddy && docker compose up -d cd ~/docker_volumes/forgejo && docker compose up -d
For the home-only certificate, copy Caddy's root out of its data folder and install it as a trusted root on each device:
docker exec caddy find /data -name root.crt docker cp caddy:<path-from-find> ./caddy-root.crt
On Windows import it into "Trusted Root Certification Authorities", on macOS add it in Keychain Access and choose "Always Trust", on Linux use your distribution's CA store. These device steps are standard system settings, not from the Forgejo or Caddy docs.
Check it worked. curl -I https://git.example.com/ returns an HTTP status line. For a home-only name the browser shows a padlock only after the root is trusted on that device. Windows and Mac are only clients here; the Caddy commands run on the server.
Tip: After you switch to a domain, the Forgejo base URL must match what you type in the browser. If it still says
localhost, clone URLs and links point to the wrong place.
Step 5: Add a runner for Actions (optional)#
Actions are on by default. A workflow in .forgejo/workflows needs a runner, a separate program that fetches jobs from Forgejo, so it needs no open port. The runner runs other people's code, so the docs ask you to read their security page first. Our layout follows the official Docker page: the runner plus a Docker-in-Docker daemon, so jobs never touch the host's Docker.
The official runner is supported and tested on Linux (amd64 and arm64). We did not run this step on any system.
Linux#
Make the folder and generate the config. The runner image runs as an unprivileged user, so the folder must belong to ID 1001:
mkdir -p ~/docker_volumes/forgejo-runner/data/.cache cd ~/docker_volumes/forgejo-runner docker run --rm data.forgejo.org/forgejo/runner:13.2.1 forgejo-runner generate-config > data/runner-config.yml sudo chown -R 1001:1001 data chmod 775 data/.cache chmod g+s data/.cache
In Forgejo, sign in as admin and open /admin/actions/runners, choose Create new runner, and copy the UUID and token. Edit data/runner-config.yml (with sudo, or as 1001): put them in the server section, and set a label under runner:
server:
connections:
forgejo:
url: https://git.<your-domain>/
uuid: <UUID-from-Forgejo>
token: <TOKEN-from-Forgejo>
runner:
labels:
- docker:docker://node:20-bookworm
The label has the form <name>:docker://<image>. A job with runs-on: docker runs in that image. Docker images are not updated once downloaded, and the docs advise pinning them. Then write the Compose file (the official one, pinned, without the old version: line):
cat > docker-compose.yml << 'EOF'
services:
docker-in-docker:
image: docker:29.9.2-dind
container_name: forgejo-dind
privileged: true
command: ['dockerd', '-H', 'tcp://0.0.0.0:2375', '--tls=false']
restart: unless-stopped
runner:
image: data.forgejo.org/forgejo/runner:13.2.1
container_name: forgejo-runner
links:
- docker-in-docker
depends_on:
docker-in-docker:
condition: service_started
environment:
DOCKER_HOST: tcp://docker-in-docker:2375
user: 1001:1001
volumes:
- ./data:/data
restart: unless-stopped
command: 'forgejo-runner daemon --config runner-config.yml'
EOF
docker compose up -d
docker compose logs --tail=20 runner
Port 2375 has no TLS and is never published to the host, so only the runner can reach it.
Windows (PowerShell)#
Not covered. The runner is documented for Linux, and the Docker-in-Docker container needs privileged: true. Run this step on a Linux machine and keep using Windows as a client.
Mac (Terminal)#
Not covered, for the same reason.
Check it worked. The runner appears as online in the runner list. Then add this file to a repository as .forgejo/workflows/demo.yaml (from the official quick start) and push it:
on: [push]
jobs:
test:
runs-on: docker
steps:
- run: echo All good!
The Actions tab shows a run with the output "All good!". If no run starts, the label in runs-on does not match the runner's label.
Tip: The docs warn that handing jobs the Docker socket of the same daemon that runs Forgejo lets an Action shut down the instance or create an admin account. Do not mount
/var/run/docker.sockinto the runner for code you do not trust.
Tip: Jobs run in separate containers, so
localhostinside a job is the job itself. Use the same public HTTPS address in the runnerurlas in the Forgejo base URL. This is our reading of how job containers behave; the docs name the instance URL for workflows inFORGEJO_SERVER_URL.
Security and testing#
| Control | How |
|---|---|
| Registration | Keep self-registration disabled on a private server |
| Web port | 127.0.0.1 until HTTPS, then no host port. Never forward 3000 |
| SSH port | Only 2222 is public. Use keys; the container gives no shell |
| Secrets | data/gitea/conf/app.ini holds SECRET_KEY. Keep it private and in every backup |
| Backups | chmod 600; they contain keys and all repositories |
| Runner | Treat it as running remote code. Pin image labels and set resource limits (container.options such as --memory=1g, from the docs' security page) |
| Updates | Read the release notes; watch the security announcements |
Quick tests on Linux:
cd ~/docker_volumes/forgejo docker compose ps docker compose logs --tail=100 forgejo curl -s http://127.0.0.1:3000/api/healthz docker compose exec -u git forgejo forgejo doctor check --all
The last command is the docs' health check; ours ended with All done (checks: 27). Windows and Mac run the same docker compose lines in PowerShell or Terminal.
What leaves the machine: Git traffic you send, and the update check if you left it on. It reads a DNS record at release.forgejo.org every 168 hours by default.
Common mistakes#
These come from the official docs, the project's issue tracker and our own test.
| Mistake | Why it happens | Do this instead |
|---|---|---|
| Mapping host port 22 to the container | The host's SSH already owns 22. Docker answers Bind for ... failed: port is already allocated (our test) | Publish 2222:22 and set FORGEJO__server__SSH_PORT=2222 so clone URLs match |
| Copying an install command without checking the tag | Issue #14887 (closed October 2026): the v17 docs page showed v16 images | Read the tag in the release list; pin the exact version |
Leaving the base URL on localhost after adding a domain | The wizard saved http://localhost:3000/ and links and clone URLs follow it | Set FORGEJO__server__DOMAIN, SSH_DOMAIN and ROOT_URL to your HTTPS address |
| Running admin commands as root | The image refuses: Forgejo is not supposed to be run as root. Sorry. | Use docker compose exec -u git forgejo forgejo ... |
| Resetting a password and then finding the account locked | change-password forces a new password at next login by default (our API call answered You must change your password.) | Sign in on the web once and set your own password, or add --must-change-password=false to the command (we tested it) |
| Backing up while Forgejo runs | The docs warn that an inconsistent backup can lose data | docker compose down, archive data, then up -d |
| Updating a major version without a backup | The database cannot go back; X to X+1 needs manual verification | Back up, read the release notes, then change the tag |
| Letting the runner update itself unseen | Issue #1725: runner 13.0 to 13.1 broke jobs that ran docker run -it in host mode | Pin the runner tag and read its release notes |
| Using Docker-in-Docker with TLS and no cert mount | Discussion #380: job containers could not find the certificates, and the user lost hours | Use the docs' internal tcp://...:2375 example, or install the runner next to the Docker daemon |
AI assistants: forgejo:latest, act_runner register and version: "3" | Assistants copy Gitea-era examples. The registry returned 404 for a latest tag; the runner docs use forgejo-runner and mark register deprecated | Use 17.0.1 (or 17), the forgejo-runner image, config-file registration and a Compose file without version: |
Tip: Before you paste any install snippet, check three things against the docs: the image tag, the port mapping and the runner name. They cause most failed setups.
Tip: After every change, read
docker compose logs --tail=100 forgejo. Port, permission and URL problems print there with exact text.
Tip: Write down your admin password and keep a copy of
app.inioutside the server. WithoutSECRET_KEYa restored instance cannot read its 2FA settings or Actions secrets.
Troubleshooting#
| Problem | Solution |
|---|---|
Container will not start after up -d | docker compose logs --tail=100 forgejo. Check that data belongs to 1000:1000 (Linux) and that ports 3000 and 2222 are free |
Bind for ... failed: port is already allocated | Another program or container uses that host port. Change the left side of the mapping, e.g. 2223:22 |
Permission denied (publickey) | Add your public key in Forgejo, then test with ssh -p 2222 -i <key> -o IdentitiesOnly=yes git@<server> |
Clone URLs show port 22 or localhost | Set FORGEJO__server__SSH_PORT, DOMAIN and ROOT_URL, then docker compose up -d |
Log shows Your ROOT_URL in app.ini is "http://localhost:3000/", it's unlikely matching the site you are visiting. | The base URL is still localhost. Set ROOT_URL to the address you actually use |
Forgejo is not supposed to be run as root. Sorry. | Add -u git to docker compose exec |
Job log: Cannot connect to the Docker daemon at unix:///var/run/docker.sock | The job container has no Docker. Follow the docs page on Docker access in Actions |
| Run says no matching runner is online | runs-on does not match a runner label; the runner list shows the labels |
| HTTPS certificate error | The name in Traefik or the Caddyfile differs from DNS, or ports 80 and 443 do not reach the server |
Forgot the admin password#
On the server, set a new one. The command works only as the git user:
cd ~/docker_volumes/forgejo docker compose exec -u git forgejo forgejo admin user change-password --username <admin-name> --password '<new-password>'
Real output from our test: doctest's password has been successfully updated!
Known bugs (open, October 2026)#
- Issue #15086: pushes to the built-in Docker registry randomly fail, reported on 17.0.1.
- Issue #15075: an Actions artifact with
retention-days: 1is stored with zero days and expires at the next cleanup. - Issue #15059:
forgejo dumpon SQLite is very slow. Use the folder backup below. - Runner issue #1770: runner 13.2.0 fails
actions/checkout@v4with rootless Podman. This guide uses Docker.
Updates and backups#
Back up before every update. The docs say to shut Forgejo down first. With SQLite and the defaults, the data folder holds the database, repositories, storage, queues, indexes and app.ini.
Linux#
cd ~/docker_volumes/forgejo docker compose down mkdir -p backups tar -czf "backups/forgejo-$(date +%F).tar.gz" data chmod 600 backups/forgejo-*.tar.gz docker compose up -d
Nightly at 03:00, add this with crontab -e (the % must be escaped):
0 3 * * * cd ~/docker_volumes/forgejo && docker compose down && tar -czf "backups/forgejo-$(date +\%F).tar.gz" data && docker compose up -d
The service is down for a few seconds. Keep a copy on another machine; our restic guide shows one way.
Windows (PowerShell)#
Set-Location "$HOME\docker_volumes\forgejo" docker compose down New-Item -ItemType Directory -Force backups | Out-Null tar -czf "backups\forgejo-$(Get-Date -Format yyyy-MM-dd).tar.gz" data docker compose up -d
tar ships with Windows 10 and 11. To schedule it, save the lines as a .ps1 file and add a daily task in Task Scheduler.
Mac (Terminal)#
Same commands as Linux. Use launchd or cron to schedule them.
Update. Pick the new tag from the release list, then:
cd ~/docker_volumes/forgejo docker compose exec -u git forgejo forgejo manager flush-queues docker compose down # back up as above, then change the image tag in docker-compose.yml docker compose pull docker compose up -d docker compose exec -u git forgejo forgejo doctor check --all
The docs ask you to flush the queues first, make a full backup, and click through your normal tasks in the web interface afterwards.
Restore test. Unpack one archive into an empty folder, never over the live one, and look for the config and the database:
mkdir -p /tmp/restore-test && tar -xzf backups/forgejo-<date>.tar.gz -C /tmp/restore-test ls /tmp/restore-test/data/gitea
In our test the 54 KB archive contained conf, gitea.db and the repositories, and a second container started on the unpacked copy served the same user.
Performance and resources#
The docs give no minimum RAM or CPU, so measure your own server:
- Resources:
docker stats forgejo. In our test an idle instance used about 115 MiB. - Database: SQLite is fine for low and moderate activity; with heavy use the docs recommend MySQL or PostgreSQL. Moving later is not trivial.
- Cache: for a small instance the docs suggest
[cache].ADAPTER = twoqueuewithHOST = {"size":100, "recent_ratio":0.25, "ghost_ratio":0.5}. - Actions storage: job logs are kept 365 days and artifacts 90 days by default (
LOG_RETENTION_DAYS,ARTIFACT_RETENTION_DAYS). - Runner capacity: one runner can run several jobs at once; limit job memory and CPU with
container.options. - Health:
/api/healthzreports the database and cache.
FAQ#
Is Forgejo free? Yes. It is GPL 3.0 or later. Forgejo Runner uses the same licence.
Do I need a GPU? No. It is a Go program with a web interface.
Can I run it on a Raspberry Pi? The README says yes. The runner is tested on amd64 and arm64. Docker on a Pi sometimes has trouble with bind-mount permissions; the docs show a named-volume workaround on their Docker page.
Does it send my data to the project? The update checker is the only built-in lookup we found. It reads a DNS record at release.forgejo.org and is configurable.
Can I move over from Gitea? Up to Gitea 1.22, in two steps through Forgejo 10.0.x, as the upgrade guide describes. Newer Gitea instances can migrate repositories one at a time with the in-app migration tool.
Can I log in with LDAP or another directory? The docs cover LDAP, PAM and FreeIPA sign-in. We did not test them.
Sources#
- Forgejo releases, release v17.0.1, README, Dockerfile and first-start config template - read October 2026
- Forgejo docs: installation with Docker, installation, release schedule, upgrade guide, backups, recommended settings, reverse proxy, configuration cheat sheet and command line - read October 2026
- Actions: administrator guide, runner in Docker, registration, configuration, security, Docker access, quick start, Forgejo Runner v13.2.1 - read October 2026
- Project history: Hello Forgejo (2022) and Gitea compatibility (2024) - read October 2026
- Caddy release v2.11.7, Caddy automatic HTTPS and Caddy tls directive - read October 2026
- Issues and discussions: #14887, #15086, #15075, #15059, discussion #380, runner #1725, runner #1770 - read October 2026
- Our related guides: restic backups, wg-easy VPN (reach a home server from outside without opening ports for Forgejo) and Vaultwarden with HTTPS
Checked against the official docs on 2026-10-31.