Waarom ik GitHub verlaat voor Forgejo

Mijn code verhuist van GitHub naar een zelfgehoste Forgejo. Niet vanwege de uitval, maar vanwege wie eigenaar is van wat erbovenop draait. De Rijksoverheid kwam tot dezelfde conclusie.

Op 27 april 2026 deed het ministerie van Binnenlandse Zaken en Koninkrijksrelaties de soft launch van code.overheid.nl, een zelfgehoste Forgejo voor de broncode van de Rijksoverheid. Projectmanager Boris Van Hoytema lichtte toe dat het platform 'voortkwam uit de eis dat het ministerie zijn broncode wettelijk moet publiceren op een plek die het zelf in beheer heeft', en dat Forgejo bewust is gekozen boven GitLab omdat het volledig open source is en alle vrijheden geeft die nodig zijn voor digitale autonomie.

De week ervoor begon ik mijn eigen code stilletjes dezelfde kant op te verhuizen. Mijn canonieke Git-host is nu code.jorijn.com, met Forgejo v15 LTS op een enkele NUC in een geharde setup. Een deel van mijn repositories staat er al; de rest staat in de wachtrij. Het plan voor de langere termijn is om mijn publieke GitHub-repositories te archiveren zodra de migratie rond is, en elk archief naar de nieuwe plek te laten verwijzen.

De meeste stukken over weggaan bij GitHub openen met de uitval. Uitval is reëel. Het is niet waarom ik vertrek. De uitval, de AI-by-default opt-in en het feit dat GitHub geen eigen CEO meer heeft zijn allemaal symptomen van één onderliggend feit: ik ben hier geen eigenaar. De Rijksoverheid publiceerde net dezelfde conclusie. Dit is dus de lange versie van die redenering, en hoe de overstap er in de praktijk uitziet.

TL;DR

  • GitHub had 257 incidenten van mei 2025 tot april 2026, waarvan 48 major. De CTO bood publiekelijk excuses aan en zei dat de capaciteit 30x moet groeien om de AI-load bij te benen.
  • In augustus 2025 stopte GitHub met een eigen CEO. Het is nu onderdeel van Microsofts CoreAI-divisie, dezelfde groep die Copilot bouwt.
  • Vanaf 24 april 2026 wordt interactiedata van Copilot Free, Pro en Pro+ standaard gebruikt voor AI-training, tenzij je je actief afmeldt. Een opt-out op repositoryniveau bestaat niet.
  • Het Amerikaanse jurisdictierisico onder FISA Section 702 en de CLOUD Act is onopgelost. Microsofts eigen advocaat verklaarde onder ede dat hij niet kan garanderen dat EU-data veilig is voor stille toegang door de Amerikaanse overheid.
  • De Rijksoverheid koos in april 2026 om dezelfde redenen voor Forgejo voor code.overheid.nl. Ik doe hetzelfde voor mijn werk.
  • code.jorijn.com draait Forgejo v15 LTS op één NUC met een KVM-geïsoleerde, wekelijks herbouwde Actions-runner. De publieke GitHub-repositories worden gearchiveerd en verwijzen straks naar de nieuwe plek zodra de migratie rond is.

Waarom de uitval niet de echte reden is

De uitval van april 2026 was het soort dat engineers boos maakt. Op 23 april zette de squash-merge code path van de merge queue stilletjes eerder gemergde commits terug in 658 repositories en 2.092 pull requests, doordat een feature flag onvolledig werd uitgerold. Bedrijven als Modal en Zipline moesten handmatig data terugzetten. Vier dagen later viel een overbelaste Elasticsearch-cluster om en lagen Pull Requests, Issues en Packages er ruim zes uur uit.

Maar pak willekeurig welke maand en het beeld is hetzelfde. Alleen al februari 2026 noteerde 37 incidenten, waaronder een outage van 3 uur en 40 minuten waarbij Actions, de Copilot Coding Agent, Code Review, CodeQL, Dependabot en Pages tegelijk plat lagen. 1 oktober 2025 was een tien uur durende macOS-runner outage. De aggregatie van IncidentHub komt over de periode mei 2025 tot april 2026 uit op 257 incidenten en 48 major outages, met ruim 112 uur totale downtime.

De juiste manier om die lijst te lezen is niet 'GitHub is onbetrouwbaar'. Grote systemen breken nu eenmaal. De juiste lezing is de framing die GitHub er zelf aan gaf. CTO Vlad Fedorov bood op 28 april excuses aan en zei dat de capaciteit 30x moet groeien om de load bij te benen. Hij wijt die load expliciet aan 'agentic AI workflow growth' sinds december 2025. Het uptime-verhaal is een afgeleide van het AI-verhaal. GitHub remt niet af op AI-features. GitHub trapt het gas juist verder in. De uitval is hoe dat doortrappen er in productie uitziet.

The Pragmatic Engineer wees erop dat GitLab, Bitbucket, Vercel, Linear en Sentry niet hetzelfde jaar hadden. Die bedienen ontwikkelaars onder dezelfde algemene vraagdruk. Wat GitHub aan het worstelen is, is iets specifieks van GitHub.

GitHub heeft geen eigen CEO meer

Het grotere feit is ouder dan de excuses en kreeg veel minder aandacht. Op 11 augustus 2025 stapte Thomas Dohmke op als CEO van GitHub. Microsoft benoemde geen opvolger. In plaats daarvan werd GitHub opgenomen in Microsofts CoreAI-divisie, de groep die Satya Nadella in januari 2025 introduceerde met de uitgesproken missie 'het end-to-end Copilot- en AI-platform te bouwen voor zowel first-party als third-party klanten'.

GitHub's omzet, engineering en support rapporteren nu aan Microsofts developer division onder Julia Liuson. De CPO van GitHub rapporteert aan Microsofts AI platform VP. Het merk bestaat nog. De zelfstandige aansturing niet meer.

Dit doet ertoe omdat het oudere argument om bij GitHub te blijven was dat Microsoft het op afstand hield. Van 2018 tot en met 2024 klopte dat ook in de praktijk. Dohmke had een eigen stoel. Productbeslissingen waren zichtbaar van GitHub, niet van Microsoft. Na augustus 2025 houdt dat argument geen stand meer. Als je vandaag code pusht naar github.com, push je naar een onderdeel van Microsofts AI-organisatie. Of je dat een probleem vindt, hangt af van hoeveel vertrouwen je hebt dat Microsofts AI-organisatie dezelfde keuzes maakt voor jouw repository als het oudere GitHub gemaakt zou hebben. Dat vertrouwen heb ik niet meer, en de reden voor dat wantrouwen staat in de volgende sectie.

De training-data default is omgedraaid

Op 25 maart 2026 kondigde GitHub een wijziging in de privacy statement aan, met ingangsdatum 24 april. Vanaf die datum wordt 'interaction data, specifically inputs, outputs, code snippets, and associated context' van Copilot Free-, Pro- en Pro+-gebruikers gebruikt om AI-modellen te trainen, tenzij je je afmeldt.

Drie dingen zijn van belang aan die zin, in volgorde.

Ten eerste: opt-out, geen opt-in. De default is omgedraaid. Wie Copilot gratis gebruikt, of op Pro of Pro+, draagt nu bij aan modeltraining tenzij hij of zij naar de Copilot-instellingen gaat en het uitzet.

Ten tweede: er is geen schakelaar op repositoryniveau. Als maintainer kan ik GitHub niet vertellen 'train niet op interacties in mijn repository'. De opt-out zit per gebruikersaccount, dus elke contributor moet die keuze zelf maken. Mijn codebase wordt feitelijk trainingsmateriaal zodra iemand met Copilot Free, Pro of Pro+ erin werkt, ongeacht onder welke licentie ik het zelf publiceer.

Ten derde: de uitzondering voor private repositories is smaller dan hij klinkt. GitHub zegt geen content uit private repositories 'at rest' te gebruiken voor training, maar het verzamelt wél 'code snippets and interaction context' die ontstaan terwijl Copilot in een private repo wordt gebruikt. De grens tussen de code in rust en de snippets die ontstaan terwijl je hem bewerkt is op zijn vriendelijkst gezegd vaag.

Klanten van Copilot Business en Copilot Enterprise vallen erbuiten omdat zij onder aparte Data Protection Agreements vallen. De splitsing is helder: betaal genoeg en je interacties zijn geen trainingsdata. Anders wel.

Een paar weken geleden schreef ik over agentic GitHub Actions, waar het beveiligingsmodel toen de hoofdmoot was. De training-data flip is de tweede helft van hetzelfde verhaal: het strategische belang van GitHub bij jouw interactiedata is structureel geworden, niet meer optioneel. Ik ga niet op iemand anders' platform discussiëren over de merites van die strategie. Ik ben liever weg van het platform.

En dan is er nog de jurisdictie

Onder dit alles ligt een laag die niet meebeweegt als de privacy statement verandert. GitHub Inc. en Microsoft Corp. zijn Amerikaanse bedrijven. Alles wat zij in handen hebben, valt onder Amerikaans recht, inclusief FISA Section 702 en de CLOUD Act van 2018. Beide gelden ongeacht waar de data fysiek staat.

Section 702 is in april 2024 voor twee jaar verlengd en draait nu op een verlenging van 45 dagen, getekend eind april 2026 terwijl het Congres ruzie maakt over een langere hernieuwing. De wet machtigt Amerikaanse inlichtingenverzameling tegen niet-Amerikanen via in de VS gevestigde communicatiedienstverleners. De CLOUD Act geeft Amerikaanse opsporingsdiensten de bevoegdheid om een in de VS gevestigd bedrijf te dwingen data te leveren, ongeacht waar ter wereld die staat.

GitHub kondigde in oktober 2024 EU data residency voor Enterprise Cloud aan. Dat lost de fysieke locatie op. Niet de jurisdictie. CLOUD Act-blootstelling volgt corporate control, niet geografie.

De eerlijkste verwoording kwam niet van een toezichthouder, maar van Microsofts eigen advocaat, die in juni 2025 onder ede tegen een hoorzitting in de Franse Senaat verklaarde dat hij niet kan garanderen dat Franse data in Europese Microsoft-datacentra veilig is voor stille toegang door de Amerikaanse overheid.

Het bredere juridische plaatje heb ik in mijn eerdere stuk over waarom 'gehost in Frankfurt' niet betekent dat het AVG-proof is behandeld, en de operationele implicaties voor hostingproviders in mijn stuk over NIS2. De details laat ik daar. Het punt dat hier telt is smal: zolang je code op github.com staat, staat je code op Amerikaans rechtsgebied. EU data residency is een troost, geen oplossing.

De keuze van de Rijksoverheid: code.overheid.nl

Hier verdient de keuze van de Rijksoverheid meer aandacht dan ze kreeg. De juridische aanleiding is het Nederlandse Open, tenzij-beleid, dat sinds 2020 van kracht is: software die met publiek geld is ontwikkeld, is open source tenzij beveiliging of vertrouwelijkheid anders eist. Om daaraan te voldoen had het ministerie ergens een plek nodig om code te publiceren waar het zelf controle over had. Code.overheid.nl is het antwoord.

Wat hier even stilstaan verdient, is welke forge ze kozen. De Europese Commissie draait code.europa.eu op zelfgehoste GitLab, live sinds september 2022. Het Duitse openCode is ook GitLab. Het Franse code.gouv.fr is een aggregator die elders gehoste repos indexeert, geen forge op zich.

De keuze van de Rijksoverheid voor Forgejo, en niet voor GitLab, was een bewuste. Zoals het OSOR-artikel het verwoordde, is de motivering dat Forgejo volledig open source is, zonder open-core split, en alle vrijheden geeft die nodig zijn voor digitale autonomie. Van Hoytema voegde toe dat Forgejo's roadmap 'way more aligned' was met die van hen dan de alternatieven. De overheid wilde niet alleen een soevereine forge. Ze wilden een soevereine forge die niet achter een betaalde tier van een commerciële leverancier zat.

Het institutionele patroon doet er dus toe: een nationale overheid met serieuze juristen en een lang geheugen keek naar hetzelfde plaatje, kwam tot dezelfde conclusie en publiceerde de keuze de week voor mij. Dat bewijst niet dat de keuze juist is. Het bewijst, op zijn minst, dat de keuze geen randverschijnsel meer is.

Waarom Forgejo en niet GitLab

GitLab heb ik serieus afgewogen. Zelfgehoste GitLab CE is een bekend product, met een veel groter commercieel ecosysteem en, eerlijk is eerlijk, een wat gepolijstere UI. Twee dingen gaven de doorslag.

Eén: licenties. GitLab is open core. Community Edition staat onder MIT, maar veel van de features die ik in productie écht zou willen, zitten in de Enterprise tiers onder een niet-vrije licentie. Forgejo ging de andere kant op. Vanaf v9.0 in augustus 2024 is het project van MIT naar GPLv3+ overgestapt, met als expliciete reden om copyleft te blijven en commerciële kaping van de codebase in de toekomst tegen te gaan. De fork van Gitea in december 2022 gebeurde precies omdat Gitea Ltd zonder instemming van de community de trademarks en domeinen overnam. De geleerde les zit nu in de licentie.

Twee: governance. Forgejo leeft onder Codeberg e.V., een non-profit die in september 2018 in Berlijn als vereniging is geregistreerd, met een door leden gekozen bestuur, openbare begrotingen en meer dan 300.000 repositories op de gehoste instance. Leden stemmen jaarlijks over de begroting; die voor 2025 is aangenomen met 88 voor, 0 tegen en 1 onthouding. Dat is geen marketingclaim over community governance. Dat is een Duitse Verein die doet wat Vereine doen.

Forgejo v15.0 LTS verscheen op 16 april 2026. Het is de honderdste release van het project. Long-term support loopt tot 15 juli 2027. Forgejo Actions is in v15 op het volwassenheidsniveau dat ik nodig had: ephemeral runners, OpenID Connect en expansion van reusable workflows. De releases sinds de fork komen gestaag binnen, met actieve maandelijkse rapportages.

De eerlijke kanttekening: het commerciële Forgejo-ecosysteem is reëel maar dun. Het schoonste commerciële aanbod op dit moment is Codey van VSHN, een Zwitsers gehoste managed Forgejo vanaf 19 CHF per maand, in maart 2025 op Servala gelanceerd. Een enterprise support subscription in de stijl van Red Hat is er niet. Wie 24/7 telefonische support en een leverancier nodig heeft om naar te wijzen, zal dat zelf moeten bouwen of even moeten wachten.

Wat ik heb gebouwd, en waarom het er zo uitziet

Code.jorijn.com draait op één Intel NUC met 64 GB RAM in mijn werkkamer. Forgejo v15 LTS, Postgres 17 en Traefik draaien in Docker. Daarnaast staat een door Incus beheerde KVM virtuele machine die mijn Forgejo Actions runner host. Dat is het hele platform.

Architectuuroverzicht: één NUC waarop Forgejo, Postgres en Traefik in Docker draaien, met een aparte KVM virtuele machine die de Actions runner host. De runner bereikt Forgejo via de publieke hostname, via de hairpin NAT van de router, zodat het pad identiek is aan dat van een externe client.

De interessante beslissing zit niet in het Forgejo-deployment. Forgejo plus Postgres plus een reverse proxy is niet bijzonder. De beslissing die het meeste denkwerk kostte, is de runner.

Waar het gevaar werkelijk zit

Als je een forge zelf host, is de forge zelf het makkelijke deel. Het lastige deel is wat de CI-jobs draait. Mijn runner moet npm install, composer install en pip install uitvoeren op een dagelijks Renovate-schema, op lockfiles die door mijn eigen repositories zijn gegenereerd. Dat betekent dat hij lifecycle scripts uitvoert. Het betekent dat elke job potentieel untrusted code draait, van het soort dat recente npm-worm- en axios-supply-chain-aanvallen gebruikten om mee te liften op dependency bots die binnen het uur auto-mergden.

De taak van de runner is, met andere woorden, niet om code te draaien. De taak van de runner is om de code in te dammen terwijl hij draait. Alles in de runner-architectuur bestaat om die reden. Dezelfde redenering die ik in mijn stuk over slecht onderhouden dependencies beschreef, geldt hier ook: ga ervan uit dat elke laag kan falen, en ontwerp zo dat de volgende laag het opvangt.

De verdediging, van zacht naar hard

De runner gebruikt vijf lagen, in volgorde van zacht naar hard.

Isolatielagen van de runner: van buiten naar binnen een nftables egress filter, een KVM virtuele machine, gVisor als default Docker runtime en de jobcontainer zelf, met de wekelijkse destructieve rebuild en scope-bound runner tokens als doorsnijdende controles.

  1. Een persistente KVM virtuele machine. De runner leeft in een eigen VM, niet in een container op de host. De kernel van de host wordt niet gedeeld met de jobomgeving. Een Linux kernel-CVE binnenin de runner moet eerst de KVM-grens breken voordat hij de NUC kan raken.
  2. gVisor als default Docker runtime in die VM. Job containers draaien onder runsc, dat systeemcalls in user space onderschept in plaats van ze door te geven aan de host kernel. Een container-escape moet zowel gVisor als de omliggende KVM breken.
  3. Een wekelijkse destructieve rebuild. Elke maandag om 02:00 UTC wordt de hele VM vernietigd en opnieuw gebouwd vanaf een vers gebakken Ubuntu base image, met nieuwe persistente runner-registraties bij Forgejo. Het base image zelf wordt op zondag herbouwd, dus de nieuwe VM consumeert de apt- en kernel-patches van die week. Persistente staat kan niet langer dan zeven dagen leven.
  4. Een nftables egress filter op de bridge van de runner. De runner mag publieke :443, :80, :22 en :53 bereiken (npm, pypi, ghcr, mijn eigen Forgejo via de publieke hostname door de hairpin NAT van de router). Hij mag niet bij 192.168.0.0/16, 10.0.0.0/8 of 172.16.0.0/12. Een gecompromitteerde job kan mijn LAN niet scannen, het admin-interface van de router niet bereiken, en de andere services op de host niet aanspreken.
  5. Scope-bound runner tokens, nooit admin-scoped. De twee persistente runner-registraties hangen elk aan één user-scope of één org-scope, met write:user,write:organization PAT-scopes voor management. Een gelekt token kan geen runners registreren buiten de eigen scope, en zeker niets admin-scoped doen.

De combinatie is met opzet overlappend. Elke laag is een hek. Samen vormen ze een perimeter met diepte. Niets hiervan is nieuw, in die zin dat alle primitives upstream zijn en goed gedocumenteerd. Wat wel nieuw is, is het samenstel voor een single-user homelab waar het hele platform op één NUC past en netjes terug-rolt als er iets misgaat.

De onderliggende primitives, KVM-isolatie, gVisor, wekelijkse rebuilds en scope-bound runner-registraties, ondersteunen Forgejo en Incus allemaal native. Ik moest ze alleen samen aan de praat krijgen.

Wat ik heb opgegeven

Dit is de sectie die ik moet schrijven, omdat elk 'beide kanten'-artikel dat ik respecteer er een heeft. Dus: wat kost de overstap naar Forgejo me, eerlijk?

Vindbaarheid en de social graph. GitHub is waar contributors me vinden. Als iemand een kleine fix pusht naar een publieke repository, verwacht hij of zij dat te doen op github.com, niet op een domein dat ze nooit eerder hebben gezien. Het plan waar ik naartoe werk is om elke publieke GitHub-repository te archiveren zodra de migratie rond is en de README naar code.jorijn.com te laten verwijzen. Het ontdekkingspad blijft daarmee intact: mensen vinden me nog steeds via GitHub, zien de archive-melding en volgen de link naar de canonieke plek. Zover ben ik nog niet — een paar repositories staan al op code.jorijn.com, de rest staat in de wachtrij. Tot die tijd is het gat reëel, en accepteer ik dat.

Brosheid van het GitHub Actions ecosysteem. Forgejo Actions mikt expliciet op vertrouwdheid, niet op compatibiliteit. Het meeste werkt. Sommige dingen niet. permissions: blokken op workflow-niveau worden stilzwijgend genegeerd. actions/checkout@v6 brak begin 2026 authenticated checkout op niet-GitHub-runners, dus heb ik alles op v5 gepind. actions/upload-artifact@v4 heeft de Forgejo-fork nodig. OIDC werkt, maar gebruikt een andere workflow-key (enable-openid-connect: true) dan permissions: id-token: write op GitHub. Geen van deze dingen is een blocker. Het is allemaal frictie. Als je workflows zwaar leunen op GitHub-specifieke features, is de migratie een project, geen avondklus.

Dependabot. Heeft Forgejo niet. Ik draai Renovate op dezelfde zelfgehoste runner, op een 3-uurs schema. Het doet hetzelfde werk. Het heeft meer configuratie. De setup kostte me een dag.

24/7 leverancierssupport. GitHub Enterprise geeft je een telefoonnummer en een SLA. Forgejo geeft je een issue tracker en een chatkanaal. Voor een eenmanszaak is dat prima. Voor een 200-engineer-organisatie misschien niet, en dat is een serieuze reden om even te wachten.

Wanneer dit het niet waard is

Ik zou niet overstappen op zelfgehoste Forgejo als één van de volgende dingen waar is.

  • Het team heeft geen tijd of zin om infrastructuur te draaien. Een managed Forgejo (Codey, of Codeberg voor FOSS) dekt dat grotendeels af, maar de migratie blijft je eigen werk.
  • Je leunt zwaar op GitHub-specifieke features: GitHub Apps marketplace, Codespaces, Copilot Workspace, Advanced Security. Forgejo is een forge, geen developer-platform-as-a-service.
  • Je contributorbasis ís de GitHub social graph. Als vindbaarheid belangrijker is dan eigenaarschap, blijf waar de contributors zijn. Of accepteer de frictie, archiveer je publieke repositories met een verwijzing naar de nieuwe plek zodra de migratie klaar is, en kom er later op terug.
  • Je hebt geen geloofwaardig operationeel antwoord voor de runner. De runner is het onderdeel waar het serieus wordt. Als je niet bereid bent na te denken over KVM-isolatie, gVisor, nftables en wekelijkse rebuilds, draai je CI-jobs op een managed runner host of blijf op GitHub.

Het patroon van de Rijksoverheid is hier ook het juiste model. Ze migreerden niet alles in één stap. Code.overheid.nl is een soft-launchplatform voor ministeries om open source code te delen, niet een complete vervanging van alles wat ze verder gebruiken. Mijn setup heeft dezelfde vorm: Forgejo is canoniek voor mijn werk, GitHub is een mirror, en die mirror laat ik bewust later opnieuw tegen het licht houden.

Belangrijkste punten

  • GitHub is geen onafhankelijk bedrijf meer met een eigen CEO. Sinds augustus 2025 is het een onderdeel van Microsofts CoreAI-divisie.
  • De uitval van april 2026 en de omgedraaide Copilot training-data default zijn afgeleiden van diezelfde verschuiving. Beide zijn voorspelbaar uit de structuur.
  • Het Amerikaanse jurisdictierisico onder FISA 702 en de CLOUD Act is reëel en niet vanaf de klantkant op te lossen. EU data residency is een troost, geen oplossing.
  • De Rijksoverheid koos in april 2026 om dezelfde redenen voor Forgejo voor code.overheid.nl. Het institutionele patroon vormt zich.
  • Een verdedigbare zelfgehoste Forgejo-deployment is haalbaar op één NUC, maar de runner is het deel dat echt aandacht vraagt: KVM-isolatie, gVisor, wekelijkse rebuilds, scope-bound tokens en een egress filter dat 'nee' zegt tegen je LAN.
  • Migratiefrictie is reëel. Door je publieke GitHub-repositories te archiveren met een verwijzing naar de nieuwe plek blijft het ontdekkingspad intact terwijl je de overstap afmaakt.

Terugkerende server- of deploymentproblemen?

Ik help teams productie betrouwbaar maken met CI/CD, Kubernetes en cloud—zodat fixes blijven en deploys geen stress meer zijn.

Bekijk DevOps consultancy

Doorzoek deze site

Begin met typen om te zoeken, of blader door de kennisbank en blog.