Intro
As the title states, I am leaving Gitea. I started looking for alternatives after CVE-2026-277711, something that allowed people to pull private container images from the built in container registry without any authentication. It existed for years, and did affect Gitea as-well as Forgejo.2
While that issue alone wasn’t enough to make me migrate, it did make me start looking at alternative options. Combined with the disclosure of CVE-2026-20896 and a number of governance concerns (specifically its less than open source company environment) that have accumulated over the past few years, I’ve decided it’s time to move elsewhere.3
My destination is Forgejo. Although it inherited the registry vulnerability due to its shared codebase, I like its community driven governance, non-profit setup, transparent development process, and focus on remaining an independent, open-source forge rather than a commercially directed product. It is something I agree with more, and especially considering I do not want to use GitHub anymore due to the many- many flaws it has.
Not as smooth as I had hoped
A lesson in research
Unfortunately, as Forgejo is a bit newer, not everything was as polished as I had hoped.
As this migration came with a few new decisions, specifically the following:
- I wanted to run this new source control at home instead of on a VPS, for improved compute performance, and improved storage options.
- I wanted to keep “actions”-like workflows, coming originally from GitHub Actions, to Gitea Actions, to now Forgejo Actions.
This, unfortunately was not as easy as I had initially planned for, and this is due to multiple technical limitations I had overlooked when I had initially sketched out the plan in my head, notably those being:
- I do not have a public IPv4- nor IPv6 address.
- I use Git LFS, with files larger than 50MiB4.
- I do not trust the integrity of the VPS.
- I want Git SSH to work.
So this changes most of the approach, I cannot easily self host it and use my own IPv4, nor IPv6 for making the instance reachable.
This leaves two options, either Cloudflare Tunnels and ignore SSH, or route from the VPS to my own instance at home. Luckily for this there are many options, none of them specifically correct.
I ended up opting for option two, to somehow route from the VPS to my own home instance, this offers a few benefits and a few negatives, benefits being that I have full control over the connection, negatives being if the VPS goes down, my git goes down. I am however fine with that.
Actual solutions
To make it so that Git SSH works, and so that the site is accessible, I opted to use a very simple solution, that being a single systemd service, and forwarding the ports over SSH, with autossh:
[Unit]
Description=Reverse SSH tunnel
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
Environment="AUTOSSH_GATETIME=0"
ExecStart=/usr/bin/autossh \
-M 0 \
-N \
-o "ServerAliveInterval=30" \
-o "ServerAliveCountMax=3" \
-o "ExitOnForwardFailure=yes" \
-R 0.0.0.0:22:localhost:3322 \
-R 127.0.0.1:<port>:localhost:<localport> \
<vps>
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
I opted against using Tailscale, Wireguard or similar solutions, as this is a one off system, this is also by far the easiest solution with the least other complications added.
Now yippee hooray! My git is accessible over ssh and over http(s). My runners keep running, after making some small adjustments on my back end, and I get to keep my functionality.
NoScope disclosure of CVE-2026-27771: https://www.noscope.com/blog/gitea-instances-exposing-private-container ↩︎
Gitea 1.26.2 release notes (fix for CVE-2026-27771): https://blog.gitea.com/release-of-1.26.2/ ↩︎
CVE-2026-20896 advisory. ↩︎
This means that options like CloudFlare Tunnels are largely not an option, unless if I find a way around it, or pay. ↩︎