Von GitHub zu selbst­gehostetem Forgejo

TOC

1. Übersicht

GitHub verursacht für unsere Entwicklung Frustration, hohe Kosten und Ausfälle.
Eine Analyse der “ehrlicheren Statusdaten” (Februar–April 2026) zeigt:
An unseren vier genutzten Diensten lag die kombinierte Verfügbarkeit bei nur 93,4 % – im Schnitt ~11 Stunden pro Woche mit mindestens einem beeinträchtigten Dienst.
Dem sei dazu gesagt, dass dies lediglich die von Microsoft “bestätigten” Werte sind.
Ähnlich dem deutschen Bahn Trick messe ich in meinen Daten seit Oktober 2025 eine durchschnittliche Verfügbarkeit von gerade einmal 83%.
Die vier gemessenen Dienste sind hierbei:

  • Github Actions
  • Git Operations
  • Pull Requests
  • Pages

Die Lösung zu diesen Problemen ist ein selbst gehostetes Forgejo auf einem eigenen Server im Haus.
Das beseitigt die Geschwindigkeits-, Rate-Limit- und Datenhoheits-Probleme an der Wurzel, schaltet fehlende Funktionen - wie etwa Fast-Forward-Merges oder ArtefaktHandling - frei und macht zB Stakeholder-Accounts für das Produktmanagement kostenlos.
Ich möchte an dieser Stelle verdeutlichen, dass der administrative Aufwand für diesen Quellcode und BuildServer nur ein Bruchteil des Aufwands ist, der von mir Gegenwärtig auf das Github System aufgebracht werden muss.
Der grösste Pain-Point sind gegenwärtig die Github Actions,
welche für uns gleichzeitig die wichtigste Komponente des ganzen Systems ist, und welche der Produktivität jedes einzelnen Entwcklers mehrmals pro Woche einen Dämpfer verpasst.
Aus diesem Grund ist die Folgende Entscheidungsfindung bedeutend von dieser Thematik geprägt.

Eine Auswertung unserer realen CI-Last unter WarpBuild ergibt einen gemessenen Spitzenbedarf von 104 vCPU und 416 GB RAM bei maximal 13 gleichzeitig laufenden (windows) Agents. Konsektutiv ergeben sich drei Server-Konstellationen als unsere Empfehlung:

VarianteHardwareKerne / RAMPreis (indikativ)
★ Empfehlung: Vorkonfektionierter Silent-TowerLS ComputerSysteme EPYC 9555P128 vCPU / 768 GB DDR5-6400€ 35.288,00 €
Vorkonfektionierter Silent-Tower 2Thomas-Krenn TA1506, EPYC 9555P128 vCPU / 768 GB DDR5-6400€ 50.758,00 €
DIY lastgenLeiser Eigenbau-Tower, 2× EPYC 7763128 vCPU / 1 TB DDR4-3200~35.000 CHF
RefurbishedRefurbished Dell R6525 (1U), 2× EPYC 7763128 vCPU / 1 TB DDR4-3200~CHF 25.000
Metal Host (Cloud)zB cloudscale128 vcpu + 512g~7.000 CHF / Monat

Entscheidung: vorkonfektionierter Silent-Tower-Server (1× EPYC 9555P, 768 GB DDR5-6400).
Ausschlaggebend war die Verfügbarkeit:

  • fertig konfiguriert
  • Fertig gebaut
  • Bis zu 5 Jahre Garantie
  • In wenigen Tagen lieferbar

Also ohne Sourcing- oder Bauaufwand und ohne Kühlerproblem (keine 1U/2U SchubladenTurbine).
64 schnelle Zen-5-Kerne (128 Threads) decken die gemessene 104-vCPU-Spitze.
Die auf den ersten Blick überproportionierte Arbeitsspeicher Kapazität liegt hier tatsächlich nicht an der benötigten Kapazität,
sondern der Anzahl der einzelnen Module um die für C# am wichtigsten benötigte Ressource zu liefern,
nämlich eine Maximierung der zur Verfügung stehenden Speicher-Bandbreite.
Zusätzlich erscheinen die Alternativen durch die geringe Preisdifferenz weniger Attraktiv.

Der Lastgen Tower wäre eine 30-40% Performance einbusse gegenüber der empfohlenen Variante.
Beim Dell R6525 gestaltet sich das Bild sehr ähnlich.
Zudem ist hier auch die Verfügbarkeit, Garantie und Zustand ein weiterer Punkt, den es zu betrachten gilt.
Ebenfalls haben diese 1U Server keine guten Modifikationsalternativen.
Hierdurch wären keine Fanmods möglich, wodurch diese “Turbine” enormen Larm und Hitze erzeugt.
Diese Server versperren den Zugang zu BIOS funktionen und besitzen lediglich 40mm Lüfter.
Dadurch befinden sich damit dort kleine, heulende Lüfter, die 24/7 auf 15.000 Umdrehungen pro Minute rotieren.

Die Cloudhosted alternative fungiert hier lediglich als Referenz und ist nicht als Vorschlag zu betrachten.
Der Preis ist hier angenähert, da solch grosse Server oft nur als Offerte eingeholt werden können.
Es besteht allerdings die Möglichkeit, einzelne Server für einzelne Runner anzumieten.

Github kostet uns gegenwärtig je nach Auslastung jährlich 50.000 USD - 55.000 USD.


2. Ausgangslage: Warum weg von GitHub?

SchmerzpunktAuswirkung heuteLösung mit selbst gehostetem Forgejo
LangsamLatenz bei Clone, PR, UI – verstärkt durch USA-AnbindungServer im eigenen Haus → LAN-Latenz statt Transatlantik
Teuer50-55k USD, tendenz steigendKeine weiteren kosten
AusfälleTägliche Ausfälle (nicht immmer gleich schwerwiegend)99.9% uptime möglich
Kein Einfluss auf RunnerImagescmi-metatool kann nicht auf .NET 10 Pakete gehoben werden, da diese erst mit MSBuild 18 unterstützt sind. .NET 8 verliert LTS im November 2026RunnerImage im eigenen Zugriff
API-Rate-LimitAutomatisierungen/Bots werden gedrosseltEigene Instanz, Limits frei konfigurierbar
Keine kostenlosen Stakeholder-AccountsPM zahlt pro Sitz oder hat keinen ZugangForgejo: unbegrenzte Nutzer kostenlos
Dediziertes AccountmanagementJeder Entwickler braucht einen eigenen AccountForgejo: Oidc/Ldap -> EntraID Account
Fehlende Funktionenz. B. Fast-Forward-Merge fehltIn Forgejo nativ vorhanden (FF-only, Rebase, Squash)
USA-BindungDatenhoheit, rechtliche AbhängigkeitDaten bleiben in der Schweiz, im eigenen Haus
Tägliche Störungen~17 h/Woche Beeinträchtigung (Kapitel 3)Wir kontrollieren Verfügbarkeit und Wartung selbst
Verdeckte KostenAusgelaufene Buildartefakte werden Berechnet und können nur aufwändig gelöscht werdenKeine (Open Source)
KontaktGithub Mitarbeiter reagieren meist gar nichtOpen Source Code ermöglicht forks, Antworten aus dem Team bisher nach spät. 1 Tag
LeitungExistiert seit Sommer 2025 nicht mehr.Codeberg und mehrere direkte Teams, Antworten binnen Tagen auf Mails
VertrauenHacks durch eigene Mitarbeiter, Leaks, etc.CVEs klar kommuniziert. Keine kritischen Lücken in privaten Instanzen vorhanden

Ein sehr grosser Indikator für die Githubsche Dekadenz liegt in dem Fehlen eines Kopfes.
Github ist ein Schiff ohne Kapitän.
Das kann zB im Verge nachgelesen werden.
Der CEO Posten wurde wurde im Sommer 2025 von Thomas Dohmke aufgegeben und das Team wurde direkt dem CoreAI Team unterstellt.
Diesem fehlt objektiv Betrachtet die Kompetenz, dieses Produkt in die Zukunft zu führen.

3. Beleg: GitHub-Ausfälle Februar–April 2026

Die offizielle Statusseite (githubstatus.com) meldet reale Ausfälle seit geraumer Zeit nicht mehr verlässlich.
Wir nutzen daher die ehrlichere, aus dem Atom-Feed rekonstruierte Auswertung von mrshu.
Da Microsoft den Atom-Feed seit Mai 2026 nur noch unregelmässig aktualisiert, werten wir bewusst das saubere Fenster Februar bis April 2026 (89 Tage) aus.
Betrachtet man mit den Erkenntnissen aus Kapitel 2 die Daten vor 2025,
so ergibt sich ein weit stabileres Bild von nur sehr wenigen, grösseren Ausfällen.
Generell herrscht hier im Schnitt eine Verfügbarkeit von >98%.
Hingegen im April 2026 erreichen wir einen gemessenen, zugegebenen Wert von 78,33%.
In meinen persönlichen Messungen - also eine Berechnung der Zeitfenster eines 8h Arbeitstages, in denen mindestens einer der vier verwendeten Dienste nicht Verfügbar ist - komme ich sogar lediglich auf 71%.

Sollten wir jemals gezwungen sein so schnell wie Möglich einen Fix herauszugeben,
weil wir zum Beispiel opfer einer aktiv ausgenutzten Sicherhitslücke sind,
dann ist so ein Bild einfach nicht tragbar. waitingForgithub

In den folgenden Abschnitten werden nur die offiziellen, von Microsoft herausgegebenen Ausfalldaten analysiert.
Dem sei jedoch vorangestellt, dass die Dunkelziffer hier weit höher ist.
Meine Datenerhebung ergibt sich aus der Analyse unsere Github Jobs für Actions,
Health Pings für unsere Pages und generelle Automatisierungen, die Aufgrund der Verfügbarkeit fehlschlagen und deshalb gelogged werden.
Gerade in den Git Operations komme ich im Monat Mai auf 84 Stunden, in denen git Operations so eingeschränkt nutzbar waren,
dass ein einfacher Branchwechsel über Github bis zu 12(!) Minuten dauert.
Ich werte ausserdem die Zeitfenster aus und komme am 21.04. zu einem Aufallfenster der Github Actions von 16 Stunden.

3.1 Unsere vier genutzten Dienste

DienstVorfälledavon majordavon criticalAusfallzeit
Pull Requests164198,2 h
Actions206250,0 h
Git Operations93022,1 h
Pages5409,7 h

3.2 Kombinierte Sicht (das, was wir täglich spüren)

  • 35 Vorfälle betrafen mindestens einen unserer vier Dienste.
  • 140,9 h kombinierte Beeinträchtigung in 31 getrennten Zeitfenstern über 89 Tage.
  • Kombinierte Verfügbarkeit unserer Arbeitsfläche: 93,40 %.
  • ⇒ Im Schnitt ~11,1 Stunden pro Woche mit mindestens einem gestörten Dienst.
  • Gesamtbild GitHub (alle Komponenten): 96 Vorfälle im Fenster (Feb 37 · Mär 32 · Apr 27).

93,4 % Verfügbarkeit entsprechen keinem marktüblichen SLA (üblich sind 99,9% - und dafür zahlen wir enorme Summen).

Methodik

  • Vorfälle nach started_at gefiltert
  • Wartungsfenster exkludiert
  • duration_minutes je Komponente aufsummiert;
  • Union über Zeitfenster mit Ausfällen, um Duplikate zu vermeiden

3.3 Ablehung der rechtsmässigen Rückerstattung

Verstärkt wird diese Entscheidung zusätzlich durch die Ablehung der Rückerstattung.
Wir bezahlen für eine vertraglich zugesicherte SLA von 99.9%,
die Microsoft seit mindestens Oktober 2025 - der Zeitpunkt, zu dem ich mein aktives Monitoring gestartet habe - jeden Monat bricht.

Diese Anfrage wurde bereits am 8. Mai eingereicht:

sla1 sla2

Nach mehrmaligen Rückfragen meldete sich der Github Support gestern (09.06.2026):

Hello Lukas,

Thank you for reaching out to GitHub support and I apologize for the miscommunication earlier. We understand that these outages are impactful to your business. Our public documentation indicates that service credit requests should be submitted within 30 days after the end of the current quarter. The first quarter 2026 ended in March, any request for SLA credits was to be processed after the end of the quarter (all through April) but this request came in on the 8th of May which is outside the time when such requests should be made. Regarding the request for SLA credits for Q2 2026 or FYQ4 (April to June) cannot be processed currently due to the fact that we are currently outside of the processing window as this request should be submitted sometime in July. You can see our current and previous uptime performance on the GitHub Uptime status for each service.

I’ll go ahead and mark this ticket as Solved, at this time.

Cheers, Anthony. GitHub Support.

Wir können also damit festhalten, dass das SLA Versprechen von Microsoft wertlos ist.


4. Was Forgejo konkret löst

Geschwindigkeit

Git-Operationen über das eigene LAN statt über den Atlantik.
Generell liefert Forgejo eine bessere Performance als Github.
Meine Private Instanz, die in etwas 350 Km Entfernung gehostet wird, und die Ich mit 20 anderen Entwicklern teile, liefert folgende Werte in der Statusleiste:

Powered by Forgejo
Version: 15.0.2
Page: 16ms
Template: 2ms

Die Actions haben im Schnitt eine Wartezeit von weniger als 2 Sekunden (Konfigurierbar!).
Im Vergleich hierzu warten Jobs in Github des Öfteren bis zu 30 Minuten,
bis diese Ausgeführt werden.

Hinzu kommen noch diverse, in Ops genutzte Automatisierungsskripte.
Diese haben mit der instabilen und langsamen github api zu kämpfen.

Dieses Skript benötigte hierbei 58 Sekunden für 336 parallelisierte(!) Abfragen.

~/coding/CMI 
at 13:10:55 ❯ /home/crashdummy/coding/CMI/cleanup-expired-artifacts.sh -y CMInformatik/cmi-metatool
Fetching artifacts for CMInformatik/cmi-metatool ...
Found 335 expired artifacts, 198.35 GB

Pruning 12 artifacts in parallel
  💣 300 ok, 0 fail 💣
✅: 335 deleted, 0 failed

~/coding/CMI took 58s 
at 13:11:53 ❯

Zusätzlich ist gerade der Disk IO der Github hosted Runner nicht performant,
wodurch der reine CI Overhead einen grossen Anteil der berechneten BuildMinuten frisst.
Spitzenreiter sind hier pro Run:

  • NuGet restore (~2min 30s)
  • Upload-Artifact (~1min)
  • Download-Artifact (~50s (x5|x7))

Diese können mit lokalen Runnern auf wenige Sekunden reduziert werden.
Weiterhin können wir davon ausgehen, dass sämtliche andere Schritte weit weniger Zeit in Anspruch nehmen werden.

Schattenkosten

Generell benötigt es stets enormen Aufwand, um herauszufinden, was hier tatsächlich die Kosten dieses SCM sind.
Auf die versteckten Kosten zB der Artefakte - auf das ich mit dem in Geschwindigkeit erwähnten Skript reagiere -
stösst man erst, wenn man versteht, wie github hier intern arbeitet.
Gemäss Dokumentation erzeugen diese Artefakte keine “weiteren” kosten.
Allerdings liegen diese - nicht mehr Nutzbaren - Artefakte auf Microsoft’s Cloud Speicher und verursachen Lagerkosten.
Es ist bezeichnend, dass Microsoft’s Scott Hanselman sogar einen Analyzer geschrieben hat,
um solche Kosten aufzudecken.

Ausfälle

Wird diese Forderung angenommen existieren nur wenige Ausfallmöglichkeiten.
Bis auf die IP und etwaige NAT regeln, liegt es an uns, diese zu verhindern.

RisikoEintrittswahrscheinlichkeitMöglicher WorkaroundImpact
Server DefektgeringBackup git nach DNS gerouted, 3-4 CMI Laptops als temporäre RunnerServer muss ersetzt werden
Netzwerkstörungeher gering (UMB)Dezentrales Arbeiten mit Git, keine PipelinesWartezeit, bis um UMB das Problem löst
Runner veraltetnahezu unmöglichImage wird aktualisiertwenige Minuten keine “neuen” Builds
Konfigurations Problemsehr unwahrscheinlichWiederherstellung der alten KonfigurationWenige kein Zugriff

Keine Fremdem Raten Limits

Das ist gegenwärtig ein sehr akkutes Problem im DevOps Bereich.
Es existieren diverse Automatisierungsmechanismen über terraform, spacelift etc.
Weiterhin nutzen Claude Skills, MCPs oder andere Benutzer-Skripte ebenfalls die Github Api.
Hierbei spürt man oft sehr geringe Rate Limits.
Damit in dem Moment die Pipelines nicht in Fehler laufen, prüft mein privater Server im Sekundentakt auf Ratelimits,
und wechselt temporär die Github tokens von Benutzern mit erhöhten Rechten ein.

Eine eigene API ist davon nicht mehr betroffen

Stakeholder Accounts

CMI-Kunden und das PM teilen sich aktuell einen einzelnen ServiceAccount.
Neben dem offensichtlichen Identifizierungs-Problem und den zuvor genannten Ratelimits - das hier geteilt werden muss -,
ist es so auch schwieriger, Zugriffe feingranularer zu steuern.

CWS Entwickler Accounts

Ein sehr grosses Problem bildet aktuell die CWS Entwicklung ab.
Diese wird nicht nur von CMI Mitarbeitern ausgeführt, sondern auch von einigen Kunden selbst.
Gegenwärtig muss ihnen ein Zugriffsschlüssel zugesandt werden, mit dem Sie an die NuGet Pakete kommen,
die für die CWS Entwicklung relevant sind.
Dies bringt folgende Probleme mit sich:

  • Zu viel Zugriff
  • Keine eindeutige Möglichkeit der Identifizierung
  • Keine Möglichkeit einzelne Kunden zu revoken

Durch die eigene Instanz können den Kunden eigene,
sehr eingeschränkte Accounts zugewiesen werden.

Fehlende Features

Neben dem Fehlen der DownloadZahlen für github Packages,
wodurch sich nicht ermitteln lässt, welche veralteten Pakete gelöscht werden können. Auf meine Github Diskussion wurde hier nicht reagiert.

Ein weitere PainPoint ist das Fehlen des sog. Fast-Forward-Merge.
In Github ist das nicht möglich, in Forgejo allerdings schon.
Damit erspare ich mir einen rebase nach jedem Release jedes einzelnen Microservices.

Datenhoheit

Unabhängig von dem offensichtlichen Verlust der Seriosität durch Hacks der eigenen Mitarbeiter,
sowie diverser grösserer Sicherheitslückenauf Github,
stellt sich die Frage, ob digitale Souveränität für uns ein relevantes Ziel ist.
Es erweckt auch nicht den anschein, als würde sich das in nächster Zeit änddern Ganz abgesehen davon, dass es nicht abzusehen ist, wie sich der Markt in den USA weiter entwickeln wird.
Es ist zusätzlich auch ein Verkaufsargument gegenüber unseren Kunden,
dass weder Daten, noch Code, Schwerzenbach verlassen.

Wartungsfenster

Abgesehen von den Ausfällen durch Bugs und Infrastruktur-Problemen,
gibt es auch geplante Wartungsfenster von Microsoft.
Das letzte Wartungsfesnter war dieses hier:

EU Network Maintenance This incident has been resolved. Thank you for your patience and understanding as we addressed this issue. A detailed root cause analysis will be shared as soon as it is available. Jun 6, 15:31 - 18:49 UTC ( GithubStatus )

Glücklicherweise ist das ein Samstag gewesen, allerdings war Github hier für 7(!) Stunden nahezu unerreichbar.

4.1 Was forgejo nicht direkt löst

Ganz Aufwandsfrei ist die Migration allerdings nicht. Während aufgrund der (fast) identischen Api (Kapitel 5)
bei den meisten Requests lediglich die BasisUrl verändert werden muss,
gestalten sich manche Integrationen etwas schwieriger.

Infrastrucutre-over-terraform

Wir verwalten Github gegenwärtig über ein Infrastruktur Repository.
Hierzu existiert ein forgejo-provider,
der hier ähnlich, aber nicht identisch ist.

Spacelift

Spacelift unterstützt nativ lediglich Github, Gitlab, Bitbucket und Azure Devops.
Hier muss leider etwas erfinderisch gearbeitet werden.
Allerdings unterstützt Spacelift Raw Git und besitzt eine cli.
Der Migrationsaufwand sollte damit überschaubar sein.

Dependabot

Das Projekt Dependabot ist integriert, um in unseren Repositories nach Sicherheitslucken zu suchen.
Allerdings existieren diverse altenativen, die den gleichen Effekt erzielen.
Die bekannteste Integration ist Renovate. Hierzu muss lediglich ein ServiceUser erzeugt werden.
Die Renovate-Cli wird bspw. über Systemd-Timer mit so einer Config gestartet:

module.exports = {
    platform: 'forgejo',
    endpoint: 'https://git.cmi.ch/api/v1/',
    token: process.env.RENOVATE_TOKEN,
    gitAuthor: 'Renovate Bot <renovate@cmi.ch>',
    autodiscover: true,
    osvVulnerabilityAlerts: true,
    dependencyDashboard: true
  };

Hiermit liefert renovate die gleiche Funktionalität wie Dependabot:

renovate

Eine Einrichtungsanleitung lääst sich hier

5. Warum Forgejo

Von Gitlab, zu Bitbucket, über SourceForge und Gogs,
sowie exotischen und proprietären Lösung wie visual Source Safe oder Team Foundation Server.

Ich habe in den letzten Jahren jedes nennenswerte ALM System als Poweruser bedient wenn nicht sogar verwaltet.
Lässt man die Projektplanungsmöglichkeiten ausser Acht - diese werden von uns gegenwärtig über Youtrack abgebildet -,
so kann ich voller Überzeugung sagen, dass mit Blick auf Performance, Stabilität, Administrations-Aufwand und Benutzerfreundlichkeit,
Forgejo das beste System ist, das zur Verfügung steht.

Das ausschlaggebende Kriterium ist hier allerdings nicht meine persönliche Einschätzung.
Die Migration sollte weitestgehend nahtlos erfolgen und kein Schulung erfordern.
Aus diesem Grund sollte ein System gewählt werden,
dessen Abläufe kongruent zu Githubs Abläufen sind.

Forgejo erfüllt diese Anforderungen wie folgt:

Benutzer Oberfläche

Die Benutzer Oberfläche gestaltet sich nahezu identisch zu Github.
overview

prdiff

action

release

Integrationen

Wir haben bereits einige Integrationen im Einsatz.
Neben der Möglichkeit composite Actions direkt aus Github.com zu beziehen,
Können auch die meisten Integrationen in Forgejo genutzt werden,
Wie zB Claude-Code PR Reviews

CI-CD Pipelines

Den grössten Vorteil liefert hier die Tatsache, dass die Forgejo-Actions
nahezu die identische Syntax zu den Github Actions haben.
Der Migrationsaufwand ist damit sehr minimal.und ist weitestgehend gewollte Veränderungen, um für eine bessere Performance zu sorgen.

API Kompatibilität

Der Grund, warum Integrationen usw. so gut funktionieren ist der,
dass sich forgejo hier sehr stark an die Vorgaben der Github API hält.
Forgejo besitzt einen Swagger gegenüber dem sich die aktuell verwendeten Abfragen verifizieren lassen.

Migration

Forgejo hat eine Migration direkt verbaut.
Hierdurch verlieren wir keine Releases, Pull Requests oder Milestones.

migration

Cli

Neben den Actions verwenden auch einige Entwickler die Github cli aufgrund ihrer bequemlichkeit.
Für forgejo existieren fgj und fj,
die die gleiche Funktionalität bei (fast) gleicher Syntax erlaubt.
claude-code ist übrigens ebenfalls sehr gut in der Lage, mit seinen Toolcalls mit fgj umzugehen.

6. CI-Lastanalyse (Basis der Server-Dimensionierung)

6.1 Datengrundlage

Auswertung des CI-Abrechnungs-Logs der WarpBuilds (2 207 Job-Läufe, 1.–31. Mai 2026, ~30 Tage).
Das Log enthält pro Lauf:

  • einen Startzeitpunkt (timestamp)
  • Die Laufzeit (execution_time)
  • Den Runner-Typ.

Wichtige Erkenntnis: 100 % der gemessenen Last sind Windows-Runner (warp-windows-*). Der .NET-Framework-Stack erzwingt Windows. Linux-CI existiert, ist aber sehr klein (s. u.).

6.2 Runner-Typen (WarpBuild Cloud)

Runner-LabelvCPURAMLäufe (Mai)
warp-windows-latest-x64-2x27 GB678
warp-windows-latest-x64-8x832 GB1 122
warp-windows-latest-x64-16x1664 GB407

(„Nx” = Anzahl vCPU; 2x ist bei WarpBuild abgekündigt und fällt auf 4x/16 GB zurück.)

6.3 Maximal gleichzeitig laufende Agents (gemessen)

KategorieLäufeSpitze gleichzeitigZeitpunkt
…-8x (8 vCPU)1 1221319. Mai, 13:54
…-2x (2 vCPU)678421. Mai, 08:23
…-16x (16 vCPU)407319. Mai, 13:41
Gesamt (alle Typen)2 2071319. Mai, 13:54

Nach Job-Art:

JobLäufePeaks gleichzeitig
ci-server / ci_build8445
Execute bdd tests / bdd-tests6995
integration-large-runner (CMIAXIOMARechte)3324
integration-large-runner (MEHRMANDANTEN_2)3324

6.4 Ressourcen-Peaks (das, was der Server tragen muss)

Da ein 16x-Agent das Achtfache eines 2x-Agents an CPU braucht, zählt nicht die reine Anzahl, sondern die gewichtete Spitze:

MetrikGemessene SpitzeZeitpunkt
Gleichzeitige Agents1319. Mai, 13:54
vCPU-Bedarf104 vCPU19. Mai, 13:54
RAM-Bedarf416 GB19. Mai, 13:54
Theoretisches Worst-Case (alle Kategorie-Spitzen gleichzeitig – nie beobachtet)160 vCPU / 636 GB

Zur Spitze waren faktisch alle 13 gleichzeitigen Agents 8x-Runner (13 × 8 vCPU = 104, 13 × 32 GB = 416 GB).
Zudem ist der aktuell teilweise aktivierte 16x-Agent nur testweise aktiv und liefert einen marginalen Performanceboost.

Zweite Erkenntnis aus dem Job-Report: Die CPU-Auslastung der 16x-Agents war moderat::

  • ci_build -> 67 %,
  • tests 18–45 % Der RAM lief jedoch heiss (92–96 %). ⇒ RAM ist die harte Grenze

Zahlen können allerdings durch SqlServer etc. verfälscht sein


7. Server-Dimensionierung

7.1 Modell und Annahmen

AnnahmeWertBegründung
DimensionierungszielReale Spitze + ReserveHeutige Last soll nie in die Warteschlange laufen
CPU-Überbuchung1,2 : 1 (vCPU : Kern)Agents lasten selten alle Kerne gleichzeitig voll aus. Ggf ist hier durch selfhost noch Optimierung zu erzielen
RAM-Überbuchung1 : 1 (keine)RAM ist die harte Grenze (92–96 % gemessen)
Windows-RunnerKVM/QEMU, Pool + BurstFirecracker kann kein Windows (siehe Kapitel 8)
Linux-RunnerFirecracker-microVMsSehr klein: ~6 vCPU / 40 GB Spitze

7.2 Ableitung des Grundbedarfs

KomponentevCPU/KerneRAM
Windows-Runner~72 Kerne432 GB
Linux-Firecracker~10 Kerne40 GB
Zwischensumme Runner-Last~82 Kerne472 GB

7.3 Die drei Dimensionierungs-Stufen

Auf die Runner-Last kommt eine Reserve für Forgejo + Datenbank + einige Microservices + OS. Wir zeigen bewusst drei Stufen für die Argumentation:

StufeZweck+ ReserveTotal KerneTotal RAM
A – „Was wir wirklich brauchen”Heutiger Betrieb8 C / 32 GB~84 Kerne~488 GB
B – „Für geplante Erweiterungen”Mehr Microservices/Wachstum12 C / 56 GB~88 Kerne~512 GB
C – „Sicherheitspuffer”Grosszügig, sorgenfrei24 C / 128 GB~100 Kerne~584 GB
  • Stufe A genügt möglicherweise heute.
  • Stufe B deckt absehbare Erweiterungen,
  • Stufe C ist reiner Komfortpuffer.

8. Architektur

┌──────────────────────────────────────────────────────────────┐
│  Bare-Metal-Server (Linux-Host)                              │
│                                                              │
│  ┌──────────────┐   ┌───────────────────────────────────┐    │
│  │ Forgejo +    │   │ Windows-Runner (KVM/QEMU)         │    │
│  │ DB +         │   │  • kleiner Warm-Pool (~6-8 VMs)   │    │
│  │ Microservices│   │  • Burst aus Golden-Snapshot      │    │
│  │              │   │  • Snapshot-Revert nach jedem Job │    │
│  └──────────────┘   └───────────────────────────────────┘    │
│  ┌───────────────────────────────────┐                       │
│  │ Linux-Runner (Firecracker microVM)│  ← klein, ephemer     │
│  └───────────────────────────────────┘                       │
└──────────────────────────────────────────────────────────────┘

8.1 Linux-Runner: Firecracker

Linux-Runner müssen nicht “warmgehalten” werden.
Mittels Firecracker können sekundenschnell ephemere microVMs gestartet werden.
Dies liefert saubere Umgebung pro Job.
Bedarf heute minimal (~6 vCPU / 40 GB). Kapazität wird vorgehalten, aber nur klein reserviert.
Mit der dotnet Migration sollten fast Alle Windows Runner in den nächsten Jahren abgeschafft werden können.

8.2 Windows-Runner: KVM/QEMU

Firecracker unterstützt kein Windows (minimaler VMM ohne ACPI/PCI-Gerätemodell, nur Linux-Gäste).
Windows-Gäste laufen daher unter KVM/QEMU (oder Cloud Hypervisor).
Ein vollständig automatisiertes Setup inklusive Compilerchain steht hier schon bereit.

Es werden hier also 6 VMs warm gehalten.
Weitere VMs können ebenfalls on-demand gestartet werden.


9. Server-Empfehlungen & Preise

CPU

Vergleicht man etwa einen 128-Kern-9754 (Zen 4c, langsame 2,25/3,1 GHz) mit dem schnelleren 64-Kern 9555P (Zen 5, 3,2/4,4 GHz),
sieht man genau, warum hier auf weniger, allerdings schneller Kerne gesetzt wird.

Die Last ist nicht CPU-, sondern RAM-gebunden, und 64 schnelle Kerne/128 Threads decken die 104-vCPU-Spitze – schnelle Kerne verkürzen die langen Build-/Test-Jobs (BDD ~27 min).
Ein grösserer Prozessor wurde ausserdem aufgrund des höheren Strombezugs und der damit verbundenen Abwärme und Lautstärke nicht gewählt.
Zusätzlich würde dieser höhere Kosten mit sich bringen, während nur ein marginaler Vorteil zu erwarten wäre.

Als gutes Mittelmass wurde hier der Epyc 9555P gewählt:

  • 64 Kerne (128 Threads)
  • 3,2 GHz Basistakt
  • 4,4 GHz Maximale Boost-Taktung
  • 4,2 GHz Maximale Boot-Taktung auf allen Kernen
  • 256Mb L3 Cache
  • 320-360W TDP

RAM

Aufgrund des AI Booms, in dem Sam Altman 25% des weltweit verfügbaren Speichers erwirbt,
liefert der Arbeitsspeicher den mit Abstand grössten Kostenpunkt in der Beschaffung (siehe Preisliste)
Ebenfalls bleibt die Auswahl hier sehr eingeschränkt,
da es Server Prozessoren nur wenige Arbeitsspeicher unterstützen.

Für die GC-/bandbreitenlastige C#-Last (Roslyn/MSBuild + viele vstest-Hosts) ist die volle 12-Kanal-Bestückung empfohlen! Genaueres dazu findet sich im Kapitel 10: GC-Tuning. Das 768-GB-Sparpaket bleibt möglich (−€ 9 600), gibt aber ~⅓ Speicherbandbreite auf. (Volle 12 Kanäle gibt es bei TK nur als 12×96 = 1,15 TB; 768 GB at 12 Kanälen wäre das 12×64-Samsung-Modul für ~€ 34 000 – nicht sinnvoll.)

9.1 Lärm & leise Kühlung

Das Thema Lärm und Kühlung betrifft lediglich die selbst gebauten/refurbishten Optionen (1/4/5).
Die gewählte Option wird vom Hersteller leise gekühlt (< 30 dB) – dort entfällt dieses Thema.

Ein 1U/2U-Rackserver ist laut („Düsentriebwerk”).
Der naheliegende Gedanke - die Lüfter gegen leise Noctua-Lüfter tausche - scheitert beim 1U-Refurb an mehreren Punkten:

Hürde beim 1U-Rack-ModKonsequenz
1U bietet nur Platz für 40-mm-Hochdrehzahl-LüfterKein Platz für leise 80/120-mm-Lüfter
~360W AbwärmeHoher Luftdurchsatz zwingend nötig
iDRAC9 sperrt in neueren Firmware die manuelle LüftersteuerungNur per Firmware-Downgrade umgehbar – Garantie erlischt mglw.
Netzteillüfter sind nicht regelbarLaufen immer auf Maximum und sind dementsprechend laut
Proprietärer Dell-LüftersteckerJeder Lüfter muss umgelötet werden; Garantie erlischt

Bekannte „Silent-Dell”-Umbauten gelingen – aber stets an grösseren, kühleren Geräten (z. B. 2U/4U mit Niedrig-TDP-CPU), nicht an einem 1U. Fanmod Beispiele:

Damit Schwerzenbach nicht zum Flughafengelände wird, bestehen folgende Optionen:

  • Weg A – Leiser Tower-Eigenbau (Option 4): Sockel SP3 (EPYC 7763) wird von Noctua direkt unterstützt – NH-U14S / NH-U12S TR4-SP3 (von Phoronix auf EPYC getestet). Standard-PWM, keine Firmware-Tricks, kein lautes 1U-Netzteil. Der ältere 7763 ist hier sogar im Vorteil: Für SP5 (9654) gibt es keinen Noctua-Kühler.

  • Weg B – Rack behalten, Lärm über den Standort lösen: Refurb-Rack unangetastet in einen separaten Technikraum oder ein schallgedämmtes Akustik-Rack stellen. Günstigste Hardware, kein Thermo-Risiko, Garantie bleibt.

10. Performance-Tuning: .NET & Garbage Collector (Runner)

Build (MSBuild/Roslyn) und Tests (vstest.console / testhost) laufen bei .NET Framework 4.8 auf der .NET-Framework-CLR.
Deren GC wird über app.config/machine.config (<runtime>) bzw. COMPlus_*-Umgebungsvariablen konfiguriert –
nicht über die DOTNET_*/runtimeconfig-Knobs von .NET 5+.
Da die Last allokations- und GC-lastig ist (Roslyn erzeugt enorme Gen0-Churn, dazu viele parallele Testhosts),
beeinflusst die GC-Konfiguration Build-/Testzeiten und den Speicherbandbreitenbedarf direkt.

Pro Windows-Runner-VM empfohlen:

  • Server GC aktivieren<runtime><gcServer enabled="true"/></runtime> (bzw. COMPlus_gcServer=1). Sammelt parallel über mehrere Heaps → höherer Durchsatz unter Last.
  • GCHeapCount = vCPUs der VM<runtime><GCHeapCount>N</GCHeapCount> (oder COMPlus_GCHeapCount=0xN, Hex). Server GC legt sonst ein Heap + GC-Thread pro logischem Kern an; in der VM auf die vCPU-Zahl fixieren, damit die GC-Parallelität der VM-Größe entspricht und nicht „über-threadet” – spart Bandbreite und Kontextwechsel.
  • Concurrent/Background GC bewusst wählen<gcConcurrent enabled="false"/> (COMPlus_gcConcurrent=0) erhöht bei reinen Batch-Läufen oft den Gesamtdurchsatz (keine Hintergrund-GC-Threads, die Bandbreite kosten); für latenz-/interaktiv eher an lassen. Pro Job-Typ messen.
  • Heap-Obergrenze: Ein hartes GCHeapHardLimit gibt es nur in .NET 5+/Core, nicht in .NET Framework. Für die Framework-Hosts ist daher die pro-VM zugeteilte RAM-Menge die effektive Obergrenze – Runner-VMs streng nach Größe (2x/8x/16x) dimensionieren, damit ein „Ausreißer”-Testlauf nicht den Host gefährdet. (Künftige .NET-5+/Linux-Runner: DOTNET_GCHeapHardLimit.)
  • Test-Parallelität dosierenvstest.console … /Parallel startet je Test-Assembly einen testhost-Prozess (jeder mit eigener GC). Parallelität bzw. RunSettingsMaxCpuCount so wählen, dass Hosts × Threads die VM-vCPUs nicht massiv überbuchen.
  • MSBuild-Parallelitätmsbuild /m:<n> an die VM-vCPUs koppeln; den Roslyn-Compilerserver (VBCSCompiler.exe) je VM wiederverwenden, bei Snapshot-Revert aber sauber beenden.

Warum das hier zählt: Diese Stellschrauben begrenzen und glätten den Speicherverkehr je VM. Zusammen mit der vollen 12-Kanal-RAM-Bestückung (Kapitel 9) sind sie der entscheidende Hebel gegen GC-bedingte Bandbreiten-Engpässe, wenn ~13 C#-Build-/Test-VMs gleichzeitig sammeln.


11. On-Prem-Readiness-Checkliste

Der Standort im Haus ist noch offen. Vor der Inbetriebnahme zu klären:

  • Strom: Gewählter Single-Socket-Server (EPYC 9555P, 360 W TDP) zieht ~400–650 W Ein eigener 230V/16A Stromkreis (3,6 kW) sollte für Server und Netzwerk bereitgestellt werden.
    Grosszügig geschätzt sollten wir in richtung 1.15 kVA kommen
  • Kühlung: ~1500–2500 BTU/h Abwärme falls einer der 1U Server gewählt wird.
    Der Silent-Tower (empfohlen) ist bürotauglich und kann in einen leeren Raum gestellt werden. Die Rack-Alternativen brauchen einen eigenen Technikraum.
  • Lärm: (siehe Kühlung)
  • Netzwerk: Gigabit/10G ins LAN;
    Reverse-Proxy + TLS für externen Zugriff wird von Ops verwaltet.
  • Storage: Forgejo-Daten + Artefakte + Caches auf RAID (Ausfallsicherheit); schnelles NVMe-Scratch für Runner. Wachstum einplanen.
  • Backups: Tägliche, off-box gesicherte Backups (Forgejo-DB + Repos + Konfiguration);
    Backup auf S3 möglich.
    Forgejo liefert mittels forgejo dump -c /etc/forgejo/app.ini ein zip.
    Postgresql lässt sich über pg_dump sichern.
    Optional Mirror auf Backup Instanz
  • Cold-Spare: Ersatzteile bzw. dokumentierter Wiederaufbau-Pfad (Infrastructure-as-Code), damit ein Hardware-Defekt nicht zum mehrtägigen Ausfall wird.
  • Hardware-Monitoring: IPMI/BMC, Temperatur-, Strom- und Dienst-Überwachung mit Alarmierung.
  • Software-Monitoring: Grafana Dashboard Einbindung

12. Risiken

ThemaRisikoMassnahme
Windows-LizenzierungWindows Server wird pro Kern lizenziert; viele Windows-VMs könnten sonst teuer werden.Windows VMs können ggf. Reduziert werden (mglw. Laufen Tests auch unter Linux)
Einzelner ServerHardware-Defekt = Ausfall der Dev-PlattformRedundante PSU (konfigurierbar), RAID, ECC; off-box-Backups; Cold-Spare; späteres HA-Upgrade möglich
MigrationsaufwandGitHub Actions → Forgejo Actions, Repos/PRs/Issues importierenForgejo-Migrationstools nutzen; Workflows sind weitgehend kompatibel; Pilot mit einem Repo
.NET-Framework-BindungErzwingt Windows-Runner dauerhaftBewusst eingeplant (KVM-Pool); Linux/Firecracker für Neues vorbereitet
BetriebsverantwortungWir betreiben jetzt selbst (Updates, Verfügbarkeit)Monitoring, Wartungsfenster, dokumentierte Runbooks

13. Fazit mit retrospektiv betrachteten, administrativen Aufwand

Ein Cloudprovider wie Github mag auf den ersten Blick sehr attraktiv wirrken.
Allerdings ist der administrative Aufwand damit nicht vollständig abgedeckt.

Wir befinden uns erst seit 8 Jahren auf Github.
Trotzdem sind wir sehr oft zu irgendwelchen - eigentlich überflüssigen - Workarounds gezwungen.
Beispiele sind hierbei:

  • Tricks in Actions, weil ein Job nicht “korrekt funktioniert”
  • Custom CodeOwners action, da nicht feingranular auf Dateiebene konfigurierbar. Zusätzlich E-Mail Flood.
  • Hunderte Stunden an Analysearbeit, um der Ursache von Ausfällen, fehlenden Triggern,
    abgebrochenen Github Action usw. nachzugehen

Retrospektiv betrachtet ist der administrative Aufwand für unser Github höher, als für alle anderen ALM Systeme, die ich betreue, zusammengenommen(!).