Codeberg

Sep 15, 2025 14:31 ยท 1139 words ยท 6 minute read

GitHub’s enshittification has gotten entirely out of hand. Not only are they so obviously and unethically exfiltrating all of my code into their drain-lake-give-wrong-answer box, but they’re simultaneously forcing the business they’ve illegally built on it down my throat in every part of the UI that still functions, which is becoming fewer and fewer these days.

Along with everyone, I saw this coming since the Microsoft acquisition, but I’ve so far procrastinated on jumping ship. I saw little hope of anyone coming remotely close on functionality without being equally unethical (e.g. GitLab). But I’ve finally tested out Codeberg, and I have renewed hope.

Mastodon & ActivityPub ๐Ÿ”—

In case you’re not familiar, it’s worth taking a small detour for the context into which Codeberg fits. Mastodon is an application built on, and the first implementation of, the ActivityPub protocol, which it uses to communicate with other such apps, forming a federated social network known as the Fediverse. It’s where a lot of folks (myself included) jumped as Twitter fell apart.

The mechanics of federation sound heady and weird, but it’s really just like email:

Email Fediverse
You configure an application Outlook, Thunderbird, web interface, etc Mastodon, Pixelfed, etc
To use a hosting provider Fastmail, Gmail, your own server or laptop, etc mastodon.social, functional.cafe, your own server or laptop, etc
And communicate with anyone using a standardized protocol SMTP, IMAP, etc ActivityPub
To do the thing you want Send and receive email Follow, post, favorite, boost, reply

The decentralization is a big deal. (And no, Bluesky is not decentralized.1 2) It means there is no corporate owner of the Fediverse. There is no one that can enshittify the experience in pursuit of share-holder profit. No one can buy it and fill it with Nazis. My feed is in chronological order and free of ads. It’s not without it’s problems, but it’s one of the few Good Things happening in internet technology these days.

And it gets better. The ActivityPub protocol is extensible enough to support other kinds of social interactions. Beyond statuses, replies, and likes, ActivityPub could also support federating commit events, Issues, and Pull Requests. If there were a GitHub-like service built on ActivityPub, not only would we see pretty interesting ergonomics (I could presumably “follow” a project repository from Mastodon and see its git activity as statuses in my feed that I could favorite or boost), but I would be confident that anything I build on top of it will last. I can use a hosted solution now, knowing the option to self-host is guaranteed by design.

Gitea, Forgejo, & Codeberg ๐Ÿ”—

And this is exactly what Gitea (and others) are doing through the ForgeFed project: a self-hosted Git solution, with GitHub-like features, that supports ActivityPub federation.

Unfortunately, the landscape in this space is a little fragmented. There is Gitea, then there is Forgejo, a fork thereof. Both offer cloud-hosted instances that are free to join (with various restrictions), and there are various other communities running hosted instances you can join too. This is a feature (not a bug) of decentralization. It reminds me of navigating the jump to Mastodon.

Due mostly to popularity and visibility (I only really looked into the history after the fact), I landed on codeberg.org, a hosted Forgejo instance operated by the EU-based non-profit that created it. You might wonder, doesn’t everyone moving to a single popular instance defeat the purpose of decentralization? Yes and no. Yes, it’s a form of centralization, but that’s mitigated by the federated nature of the platform (migration and self-hosting are always guaranteed options). In exchange, we get the benefit of network effects and a smoother off-ramp from GitHub as a way to jump-start mass migration. There was and is much of the same debate around the largest Mastodon instance, mastodon.social, too. The sky hasn’t yet fallen.

I think any of these hosted offerings are worth considering. The basic GitHub functionalities were implemented well in Gitea and inherited by Forgejo and others. For me, the most important feature however is Actions.

Actions ๐Ÿ”—

I’ll say it: Actions is good. Really, really good. As someone who designs systems and platforms, I am truly in awe of how well GitHub designed Actions.

The unit of composition, the action, is simple and isolated: a process with environment variables as input and standard streams as output. It’s downright Unix. This makes it extensible and easy to author, share, and orchestrate. This design led directly to an explosion of community-provided actions, and enables alternative orchestration tools like nektos/act.

This design is why Actions won; not because of vendor-lock-in, but in spite of its absence. Receive some webhooks, sprinkle a little docker, carefully craft a GitHub-like ENV, and you’ve got yourself a GitHub Actions Runner. In fact, GitHub has to continue to provide that flexibility so that it can run the same actions on GitHub hosted vs enterprise. It has a vested interest in ensuring actions can run unchanged in any environment that quacks like a GitHub. How convenient.

Building on act, that’s exactly what Forgejo Actions does. I love how much Forgejo Actions has leaned into quacking like a GitHub. I understand the urge to “improve” or “differentiate”, but it’s been so much better to be able to take workflows and actions that work for GitHub and just use them. Things I’d never expect to work just do. Things like caching, artifacts, and semantic-release, all just worked.3 Forgejo sets all the same environment variables and its API is very similar to GitHub. I know they are tweaking things here and there (“familiar, not compatible”) but it’s felt quite compatible so far.

Self-Hosted Runner ๐Ÿ”—

My experience with Forgejo Actions has been so great partly because I went the self-hosted route for that. There are hosted runner options, but I wanted to be able to run workflows without worrying about being a bad neighbor. I also wanted to make things faster and minimize cache eviction by having beefier specs. I can start up a big instance when I’m working, then stop it when I’m done to save cost.

I deployed this setup using Terraform, which means it should be pretty easy for you to replicate. All you need is an AWS account (though I’d love to move to Hetzner eventually). If you’re interested in self-hosting Forgejo Actions, you can find my Terraform module and supporting files here.

Conclusion ๐Ÿ”—

I have to admit, I’m not sure what the goal of this post is. Am I convincing you to jump ship from GitHub? To try Codeberg? To self-host your own Forgejo instance? I don’t know, maybe. This post feels more diary and less call-to-action. It’s been so long since I’ve seen a Good Thing happening in technology, I just have to share it.

โœŒ๏ธ


  1. https://dustycloud.org/blog/how-decentralized-is-bluesky/ ↩︎

  2. https://rys.io/en/167.html ↩︎

  3. To be fair, semantic-release needed a little help. But the bug was fixed quickly. ↩︎