15 min read

Choosing a Host for My Open Repositories

Table of Contents

I have settled how the repositories are laid out. Each area gets one repository where the knowledge and the code live together, because they are written together and separating them at the source would only mean maintaining two things that must agree. That repository is public, and it is where I actually work.

From there the knowledge is extracted automatically into a second, private repository that builds the public site β€” which lets the site carry the pages, framing, and presentation that belong to a website rather than to the formal open material.

I had assumed the private half was already settled: those site repositories sat on GitHub because Cloudflare Pages could build straight from them. Commit, push, site rebuilds. But that convenience was the only thing holding them there, and it is not a real constraint β€” Wrangler deploys to Cloudflare from any CI runner with an API token, no Git integration involved.

So neither half is settled, and one decision covers both. The one that matters is the public repository, because that is where I work every day.

The Shape of the Problem

It is worth being precise about what is being hosted, because it sets the stakes.

The public repository is not a publication target. It is the working repository: where history is authored, where commits land as I make them, and where the private site repository pulls from. There is no private original sitting behind it.

Three consequences follow, and together they make this a larger decision than choosing a place to publish would be.

Migration would be expensive. Moving a mirror means changing a remote. Moving a working repository means carrying history, tags, releases, whatever issues have accumulated, and every inbound link and clone that points at it. This is a decision I would rather make once β€” or make cheap to unmake.

I need most of what a forge sells. The code is built where it lives, so CI matters. Contributions are CLA-gated rather than absent, so issues and pull requests need somewhere to arrive. Dated releases need somewhere to be published.

The host sits upstream of my site. The private site repository is fed from the public one, and the build that publishes the site starts there too. A host that is slow, unavailable, or awkward to automate against does not merely inconvenience me β€” it stalls publishing.

What I Need β€” and What I Don’t

Requirement Rationale
Clonable without an account AGPL obliges me to make source available to anyone using the software. A host that requires a signup to read code makes me a worse licensor.
Good enough to work in daily This is not a mirror I push to occasionally. If the interface is slow or the host is unreliable, I feel it every day.
CI and release hosting The code is built where it lives, and releases are dated artifacts that need somewhere to sit.
Automation-friendly The extraction into the private site repository and the deploy to Cloudflare both run from here. Tokens, runners, and scheduled jobs have to be straightforward.
Stable, citable URL The license text, the site, and the writing will all point here. This is the canonical location of the work, not a copy of it β€” so the address matters as much as the storage.
Movable as a whole, independent of the forge or the host If the software underneath changes, or the platform running it does, the repository, CI, and releases should move together under the same address β€” not scattered across separate migrations tied to whichever model or platform happened to be running it.
Discoverable The open material exists partly to build credibility. A repository nobody can find fails at its actual job.
Bounded operations I am one person shipping several times a day. Anything I run myself has to be one service with a dull upgrade path and a backup I have actually restored from β€” otherwise it is a second job.
Honest fit with the host’s terms I should not be a burden a host has explicitly said it does not want to carry. This is what eliminates the option I wanted.

What I do not need is the collaboration surface built for teams: organisation management, seats, role hierarchies, review assignment, project boards. There is one of me, plus whoever comes through the CLA gate β€” a trickle by design, not a team. That trims the field less than I would like: every serious option brings the machinery along whether I use it or not.

The Codeberg Question

Codeberg was where I expected to land before I read their reasoning properly. It is a non-profit, it runs on hardware it owns, it is based in the EU β€” which matters to me for the same reasons it mattered when I chose a registrar β€” and it develops Forgejo rather than renting someone else’s platform. On paper it is the principled choice.

Then they published Protecting our FLOSS commons from LLMs, and the principled choice became a question about me rather than about them.

Their argument has several strands, and only one of them decides anything for me. The most-discussed is cost: training-data crawlers read every page a forge can generate rather than cloning it, which becomes database load, sysadmin time, and defences that degrade the experience for everyone else. That is a real problem and I am part of the demand behind it. What I cannot change by choosing a host is whether the crawlers come; they arrive wherever public code is served. What I can change is whose infrastructure absorbs them.

The strand that does decide something is about the kind of repository a forge is prepared to carry. They call it the development team of none: a lone developer with an LLM can generate activity, CI load, and release artifacts at the scale of a large community project while having no community at all. Their position is blunt β€” they do not think it is reasonable to spend donation money hosting what they call large ghost projects.

Running alongside it is a concern about trust: review burden from low-effort generated contributions, growing uncertainty about which projects have meaningful human oversight, and copyleft code losing its reciprocity requirements by being regenerated out of training data.

Their Terms of Use turn the repository question into specifics. Among the kinds that may no longer be welcome:

  • Projects created by LLM agents in autonomous ways
  • Projects written and maintained with heavy use of LLMs
  • Projects whose resource usage is significantly larger than the people involved could have produced by hand
  • Projects heavily tied to the LLM ecosystem

I am not going to pretend about which list I am on. My work is being built with heavy LLM assistance, by one person, at a cadence that would not be possible without it. That is the second bullet, described accurately, without much room for interpretation.

The third bullet applies too, and it is the one I would have missed if I had thought of the public repository as a mirror. This is where I work, which means CI runs here, releases accumulate here, and history grows here β€” at a rate one person could not produce by hand. That is precisely the disproportion they are describing.

There is one distinction I can fairly claim, and it does not rescue me. Codeberg’s sharpest worry is single-use software that is generated, dumped, and never looked at again. That is not what these are: they are meant to be maintained for years, and there is human judgement on every commit. But the bullet that disqualifies me does not ask whether the result is maintained. It asks how it was built.

So the question is not whether I agree with Codeberg. It is whether I qualify β€” and the answer is no.

What is more interesting is that agreeing with them and being excluded by them are not in tension. Their core objection is about who pays for what a project like mine consumes: do not externalise your costs onto donation-funded civic infrastructure. That is a principle I hold in other contexts and cannot selectively abandon because it now points at me. If I read their terms, recognise myself on the discouraged list, and sign up anyway on the reasoning that enforcement is unlikely, I am not making a hosting decision. I am free-riding on a commons while its maintainers explain what it costs them.

Taking that seriously leaves two answers rather than one. Put the load on a company large enough to have priced it in, or carry it myself. Both respect the principle; they differ in who does the work.

And their point about license laundering cuts against my own interests, which is the part I find hardest to dismiss. My commercial model rests on AGPL reciprocity: use the code freely, but run it as a service and you publish your changes or you buy a licence. License laundering β€” copyleft stripped by regeneration β€” attacks precisely that leverage. I am a beneficiary of LLM-assisted development and simultaneously exposed to the specific harm they name. I do not get to pick only the convenient half of that. No host fixes it, either, which is worth saying before the options table implies one might.

The Options

Option Assessment
Self-hosted static, suckless-style suckless publishes through stagit: static HTML generated from the repository, with patches arriving by mail. No accounts, no database, nothing to keep patched. Admirable, and not applicable β€” a static browser is not a working repository. No CI, nowhere for a pull request to arrive, nowhere for a release to sit. It solves the operational problem by removing the features I need.
Self-hosted Forgejo A real forge on my own infrastructure at an EU host β€” one instance per area, with its own address on that area’s domain; whether that is a subdomain or a path is a separate decision. The same software Codeberg develops, under terms I set, with the load my workflow generates landing on the party generating it. Full features, including Actions for CI and somewhere for releases and CLA-gated pull requests to arrive. The price is not small: a stateful, internet-facing application with a database, an upgrade treadmill, backups, and an attack surface I own β€” on the critical path of both my daily work and publishing.
Codeberg Non-profit, EU-based, owns its hardware, develops Forgejo. The best values fit on paper and the one I wanted. Ruled out by their own terms, for reasons I think are correct β€” and ruled out more firmly because this would be where I work rather than something I occasionally push.
SourceHut Paid, deliberately minimal, no JavaScript, email-driven patches, with its own CI. Functionally it would do the job. But it is run by someone who has argued the externalised-cost case more forcefully than Codeberg has, so the same mismatch applies β€” and mailing patches is real friction for the occasional CLA-gated contributor who has never sent one. Being paid rather than donation-funded is a genuine point in its favour.
GitLab.com A capable forge with a usable free tier and solid CI. But it brings nothing over GitHub: another US-listed company, so the sovereignty argument does not land either, with less reach, no existing footprint of mine to build on, and an even larger feature surface I would not touch. If the decision is to accept a commercial host, this is the same compromise with fewer benefits.
GitHub Maximum reach, mature CI, zero operations, and a parent company that created the crawling demand, monetises it, and absorbs the cost out of revenue rather than donations. The pipeline argument used to sit here too β€” until Wrangler removed it. What remains is reach, weighed against Microsoft ownership, US jurisdiction against my stated EU preference, and putting the canonical copy of an AGPL project inside the company selling the tool that regenerates copyleft without its conditions.

Decision

Self-hosted Forgejo on an EU host, one instance per area. Both halves move there, and GitHub drops out entirely β€” the exact address each instance answers to, subdomain or path, is a separate decision.

Four reasons, then a fifth that is not really one.

Cost. My workflow generates exactly the load Codeberg is asking people not to externalise onto donation-funded infrastructure. Self-hosting means paying for what I actually consume, rather than routing it to a commons that has already said it does not want it.

Terms. It is the only option with none to satisfy β€” no repository-type list to be excluded from, no cadence that is anyone else’s problem.

Sovereignty. The same argument I made choosing a registrar: EU jurisdiction, and the registrar, the forge, and the site publisher held by separate parties rather than one company.

Address. Whatever form it takes, it is a record I own rather than a namespace someone else administers β€” if the host disappoints me, I move a service and repoint an address, not migrate a URL everyone else has to relearn. That is also why each area gets its own instance rather than sharing one at the studio level: under a shared address, an area that needs to move independently would break that address for everyone else too. Separate instances mean that risk is already paid for.

And a fifth, honestly: I want to. The first four treat this as a cost paid for a principle. But running the infrastructure the work is built on is the same kind of problem the DSLC Model exists to address, and there is a real difference between prescribing that discipline to other people’s operations and running it on my own. It also opens doors a hosted account keeps shut: automation on my own schedule, not someone else’s API roadmap.

Wrangler is what makes this possible at all β€” deployment no longer requires the repository to live where Cloudflare can see it.

Reach is the loss I am not hedging β€” no forge-level search, no stars, no social graph. I am betting the site and the writing do that work instead.

Whether the site itself should also move, and what it actually takes to run any of this, is the follow-up, not this post: Self-Hosting My Repositories and Sites.

Where This Contradicts Me

I wrote bounded operations, then chose the only option that puts a stateful service on my critical path β€” once per area. What survives is a weaker form of that instinct: not the count, but the shape β€” dull upgrades, restorable backups, shared infrastructure underneath.

I wrote discoverable, then chose the least discoverable option on the list. The only mitigation, a GitHub mirror, reintroduces the company I just removed. This one stands unhedged.

The AGPL contradiction survives entirely. Self-hosting settles who pays for the crawl; it does nothing about license laundering. The defences that would help β€” rate limits, proof-of-work walls, login gates β€” cut against my obligation to make source available to anyone, without an account. Accepted, not solved.

I agree with Codeberg’s diagnosis and keep working in the way that produces it. Moving to my own infrastructure changes who is billed. It does not make me a different kind of project than the one they were describing.

What I get in exchange: a decision that needs no qualification. The load is paid for by me, the jurisdiction is the one I said I wanted, and the URL is mine. More work, less reach β€” cheaper than reasoning my way around a position I hold.


πŸ’¬

If you run your own forge, I would like to know what it actually costs you a month in attention β€” and if you think self-hosting is the wrong answer here, say why. Leave a comment below, or get in touch. Follow my RSS feed for the rest of this series as the decisions land.