Key Highlights:
Summarize the following article into 3-5 concise bullet points in HTML without further information from your side. format:
As the ninth anniversary approaches
of the last
project repository I created on Github, it’s
been so encouraging to see more and more projects migrate away from
Microsoft Github. I love seeing the rise
of Codebergnot the least
because it’s a
democratically-run non-profit which isn’t subject to the whims
of the extractive arm of an unaccountable exploitative mega-corporation.
If you’re currently hosting a project on Github and you recognize
the harm
of Microsoft’s monopoly,
it’s undeniable that Codeberg is your quickest and easiest offramp to an
empowering and pro-user place. But at the same time, I don’t see
Codeberg as the be-all and end-all of Github replacements, for a
couple reasons. Most obviously, putting all your eggs in one basket
isn’t ideal, even if it’s a much better basket than the one we used
to have. We shouldn’t replace Github with one site at all;
we need the strength and resilience that only comes with
diversity1.
But beyond that, I’m reminded me of the way that some dominant
ideas can become so dominant that it becomes difficult to even
imagine alternatives to them. Forgejo (the software behind Codeberg)
is unapologetically a Github clone. For most people in software
development, Github has been synonymous with development workflows
for so long that other ways of thinking have not only languished,
but have started to feel nearly inconceivable. Even for people who
want very much to get away from Microsoft, the design decisions made
for Github follow you around from Gitlab to Bitbucket to
Codeberg/Forgejo2.
This is a pattern you see over and over with open source
alternatives to dominant systems; for a long time GNOME and KDE were
just trying really hard to build the exact same thing as Windows,
but without Microsoft. Mastodon is trying really hard to be Twitter
without Twitter. When a company dominates the market, they capture
not only their own users but even the imaginations of people
actively resisting them. It usually takes a great deal of time and
effort to carve out new patterns of thinking.
If you just want to get off Github, that’s fine; you should do that
first, and you don’t need to tackle the job of learning a new flow
right away. But I want to make space for people to think about
alternatives. What does a post-github world look like? What other
flows could we use to support project development and contribution?
When people talk about moving off Github, the first objection is
always “but everyone has an account there already!” And
this is a fair point; no one wants to create Yet Another
Account. I’m only really willing to consider alternatives that don’t
require creating another account, especially not in a distributed
system where each project might be on its own server.
Let’s start by going back to the basics. Simon Tatham
has written
up a guide describing how he uses Git without any
forge-like software involved. He keeps his repositories on his own
server with nothing but a read-only gitweb rendering
their contents as HTML. If you want to contribute a patch, you can
publish your own clone on your host of choice and let him know (via
email, chat, social media, or whatever) which branch to pull
from. This method works best for projects with a single maintainer
and a small community. It’s a good starting place for most
projects. Then when you have more going on, you might want to add a
little more structure to help keep track of things.
And then there’s projects
like Radicle offer a flow that
manages to work in a peer-to-peer way with no server involved. Being
fully peer-to-peer, your machine gets all the data synced locally,
so it works great when offline too, and you don’t have to create yet
another account on another system. This is a bold vision of how the
future of development might look.
But when I was searching for an alternative
for Fennel I went looking to
the past instead. Back when I was fresh out of university and an
enthusiastic Subversion
user, I set
up an
instance of Trac, a web-based version control, ticket, and wiki
system. I used it for all my projects, but it was mostly just a
personal organization tool as at the time I did not have any
projects that got more than one or two patches from other
contributors. Then in 2007 I switched from Subversion
to Git, and had to drop Trac. A few months later
in a moment
of weaknessI started putting my projects on
Github.
Over the years I lost track of Trac, largely due to the fact that
since it was made by fans of Subversion, it took
them several years
to add support for Gitby which time most people had switched
away from it. But Trac offered something really special. The
individual features around ticket reporting and wiki pages are
impressive, but most of all, I see Trac as the pinnacle of web app
design from the golden age of progressive enhancement.
What does that mean exactly? Well, a few years after Trac dropped
off my radar, we saw the rise of React, GraphQL, and the Single-Page
App (SPA). While there are certain type of sites for which the SPA
interaction style makes sense, these technologies saw mass
adoption across every single kind of web app, regardless of whether
they were a good fit. As the software industry is largely driven by
trends and fashion, React’s “cool factor” led to a mass amnesia
regarding how to make normal, well-designed web apps made of HTML
with a sprinkling of scripting on top and everything became one big
tangled, brittle mass of Javascript that completely keeled over when
scripting wasn’t available. But Trac got it right: the server
generates HTML (quickly3!) and sends
it to you, and in a few cases uses some optional scripting
to get things like live previews.
Anyway, when I set up Fennel’s
TracI was mostly impressed with how easy it was to get
going, but there were a handful of things that were weirdly off. The
most glaring is that even in 2026, the default setup is still to use
Subversion instead of Git. Support for Git is now built-in at least,
but for some reason you still have to enable it in the config. An
easy change, but a strange one.
Secondly,
the format
used for the wiki pages is … somewhat dated. It’s
not bad or anything, but in 2026 using anything other
than Markdown just feels pointlessly
contrarian4. There does
exist a plugin
that lets you write in Markdownbut it only lets you create
Markdown sections of pages that otherwise use the standard
formatting. There’s no way to use Markdown as the default
formatter for wiki pages, issues, and comments. At least, there
wasn’t until I
wrote my own plugin to do it based on the existing plugin.
The third problem is maybe the weirdest: the default setup has no
way to create user accounts!
It delegates
login completely to Apache. In order to add a user, the admin
has to SSH into the machine and edit an htpasswd file in
a text editor. Needless to say, if you’re using this for any kind of
community project, (or if you don’t use Apache) this is borderline
useless. There are some plugins that add workable authentication
systems, but all the existing ones either require all users to sign
up for (you guessed it) Yet Another Account or require you to tie
your logins to a huge company like Google or Github. Neither of
those paths were acceptable to me.
When I set this up, I had just recently been working
on Fedibot cluban unrelated
project. For that, I had implemented a Fediverse-based OAuth
system that allows users to specify their server where they
already have an account, and use that existing
account5 to log in. Rather than
having a fixed set of servers that you’re allowed to authenticate
with, it dynamically registers an OAuth client for any new server
it’s never seen before6. So I took
this exact flow
and ported it
to Trac. Despite somehow not really ever having written any
Python before in my life, I found it surprisingly easy to
implement, using an existing hard-coded OAuth plugin as a
guide. It clocks in at 124 lines of code.
When I’m trying out a new system, sometimes I run into some issues
and think, “OK, I can put some elbow grease into this and get
something working” but I usually expect it’ll be a little slipshod
and require putting up with things getting janky or ongoing tweaks.
I encountered a twofold surprise here: one being simply that the
fixes were so easy for me to make as someone who knows
nothing about either Trac or Python, and the second being that once
those few fixes landed, that pretty much took care of everything,
and the remaining things worked basically flawlessly. It’s a little
disappointing that these things couldn’t be addressed upstream in
the project, but hey, I’ll take the win.
Anyway, whether you end up using Trac or not, I hope you
can find something that works for your project. Good luck!
(1) I’ve seen a lot of my friends
stand up their own little Forgejo servers, and I love this. However,
I believe there’s a big missed opportunity here too. If you don’t
have an account on Alex’s Random Forgejo, you can use OAuth to log
in with an account on another server, which is great.
However, users are limited just to servers where the site’s
admins have manually registered OAuth clients! Alex might allow
users to log in using their Github account, and Alex might allow
users to log in using their Codeberg account, but it’s very unlikely
Alex’s Random Forgejo will allow users to log in with their account
on Mel’s Random Forgejo, so there is still some centralizing gravity
at play. Fortunately this is very easy to
fix! My
implementation of OAuth login using dynamic client registration
clocks in at around a hundred lines of code. If it weren’t for
Forgejo being implemented in Golang, I’d be inclined to give a shot
at implementing it. Perhaps some enterprising reader would be up for
it!
(2) But
not Sourcehut! And I do like
Sourcehut overall; they have the best CI of any system I’ve used,
and page load times are unparalleled. Its email-based contribution
flow can be kind of awkward, but I have to applaud them for trying
something different..
(3) I run my Trac instance on my home
server, which is a Core 2 Duo Thinkpad from 2010. Trac uses about
160MB of RAM, and loads pages in consistently less than 200
milliseconds; dramatically faster than Github. (Your experience
might be slower than this due to more network hops, but outside
extreme cases it should still be a good deal better than Github.)
When I first got it set up, it felt slow due to an attack of scraper
bots from LLM companies, but once I
installed Iocaine
that took care of it.
(4) Don’t get me wrong; I’m not saying
Markdown is good. It’s a lot like English: I’m not using it
because it’s good; I’m using it because it’s both tolerable and
ubiquitous.
(5) As a grudging compromise, I’ve
installed a
Github OAuth plugin for users who don’t have a Fediverse
account, but like … come on, people.
(6) If you’re interested in reading
more about how this works, I’ve got a
fairly
thorough write-up that should be useful to anyone hoping to
build a similar system. It’s easier than it sounds! I’d love to see
more people using this strategy to break away from corporate monopolies.
« older |
2026-04-25T17:08:11Z
๛
License is not valid, please check your API Key!


