Migreren naar fremforge vanaf GitHub
Deze gids neemt een typisch GitHub-team mee door een migratie naar fremforge. Hij geldt voor GitHub.com, GitHub Enterprise Cloud (GHEC) en GitHub Enterprise Server (GHES). Lees hem van begin tot eind voordat je begint: verrassingen halverwege een migratie zijn duur.
Ben je nog niet klaar om alles in één keer te verhuizen? fremforge naast GitHub gebruiken laat zien hoe je repository’s spiegelt zodat fremforge ze scant, en hoe je SBOM’s uploadt vanuit GitHub Actions, terwijl de verhuizing loopt.
Heb je de checklist voor de migratie nog niet uitgevoerd tegen je huidige GitHub-tenant, doe dat dan eerst. Hij brengt grote repository’s, LFS-gebruik, afhankelijkheden van Marketplace-actions en integraties van derden aan het licht die specifieke aandacht nodig hebben.
Voordat je begint
Wat je zelf nodig hebt:
- Een account met de rol owner in de GitHub-organisatie waarvandaan je migreert.
- Een personal access token op GitHub met de scopes
repo,admin:org,workflowenadmin:public_key(klassieke PAT) of het fine-grained equivalent. - Beheerderstoegang tot de fremforge-organisatie waarnaar je migreert (de organisatie wordt bij de registratie aangemaakt).
- Voor het migreren van Actions: een overzicht van de GitHub Marketplace-actions die je nu gebruikt, met hun versies.
Wat we aanraden:
- Bevries tijdens het migratievenster nieuwe PR’s en merges naar de hoofdbranches die je migreert. Gelijktijdige schrijfacties tijdens de migratie leveren afstemmingsproblemen op die je niet wilt.
- Voer de migratie eerst uit tegen een testorganisatie op fremforge die niet voor productie is, als je twijfelt over hoe je workflows zich aanpassen. De gratis proefperiode van 30 dagen is precies hiervoor bedoeld.
- Migreer één repository van begin tot eind en controleer dat die schoon bouwt voordat je de rest in bulk migreert.
Tijdsinschatting (planningsmarges, geen toezeggingen):
- Eén kleine repository (≤100 MB, geen LFS, eenvoudige Actions): 15-30 minuten handwerk plus CI-verificatie.
- Een middelgrote repository (≤1 GB, wat LFS, gemiddeld complexe Actions): 1-2 uur, inclusief het aanpassen van workflows.
- Een bulkmigratie van 20-50 repository’s: 1-2 engineeringdagen verspreid over een week, waarvan het meeste opgaat aan het aanpassen van Actions en niet aan de repositorymigratie zelf.
Deze marges komen uit een documentatiereview tegen de prestatiekenmerken van upstream Forgejo en 2 interne migraties bij fremverk vóór de lancering; de werkelijke tijden worden onderbouwd met onze eerste 5 klantmigraties. Het zijn hulpmiddelen voor de planning, geen contractuele SLA’s. De werkelijke migratietijd schaalt met: (a) het aantal repository’s en het totale LFS-volume; (b) de complexiteit van Actions en het aantal uses:-verwijzingen dat herschreven moet worden naar de runner-mirror van fremforge; (c) de grootte van het team dat de verificatie kan opvangen. Migreer je meer dan 50 repository’s of gebruik je Actions op een niet-triviale manier, plan dan minstens 2× de bovengrens als buffer en draai eerst een pilot met één repository.
Matrix met functiepariteit
Wat fremforge vandaag levert ten opzichte van GitHub Enterprise Cloud, gericht op het beveiligings- en authenticatievlak waar klanten het meest naar vragen:
fremforge zet nieuwe organisaties standaard op Git-toegang via alleen HTTPS (SSH staat standaard uit sinds 2026-05-22), met de vooraf geregistreerde OAuth-app voor Git Credential Manager: ontwikkelaars krijgen MFA via de IdP van je organisatie bij elke vernieuwing van de push-token. De tabel hieronder laat zien waar elke mogelijkheid staat.
| Mogelijkheid | GHEC | fremforge | Opmerkingen |
|---|---|---|---|
| HTTPS + GCM (interactieve OAuth, MFA via IdP) | ✅ | ✅ Aanbevolen standaard | Vooraf geregistreerde OAuth-app: ontwikkelaars voeren twee git config-regels uit uit de gids voor veilig inloggen. MFA via de IdP van je organisatie volgt bij elke tokenvernieuwing. |
| HTTPS + push met PAT (met scope en vervaldatum) | ✅ | ✅ | Beheerders van fremforge kunnen de geldigheid van PAT’s voor de hele organisatie begrenzen. Gebruik dit voor CI en scripts, niet voor pushes door mensen. |
| Push met SSH-sleutel (elk algoritme) | ✅ | ⚠️ Standaard uit | Schakelaar per organisatie op <org>/_admin/auth-policy/: zet het weer aan als je workflow SSH nodig heeft. Reden: handhaving op bron-IP is bij SSH structureel niet mogelijk (zie hieronder). |
| SSH-certificaatautoriteit | ✅ | ✅ | Eigen beheer-UI op <org>/_admin/auth-policy (subsectie onder “SSH-protocol toestaan”) voor organisaties die SSH weer hebben aangezet: plak de publieke sleutel van de CA, kies een principal-beleid, optioneel “require cert auth”. |
| OIDC-tokens voor workload-identiteit in CI | ✅ | ✅ | De runner-OIDC-uitgever van fremforge, https://frem.sh/_app/runner/oidc (discovery + JWKS), zie Runner-OIDC. Federatie met AWS/Azure/GCP/T Cloud Public werkt vandaag. |
| Verplichte hardwaregebonden SSH-sleutel | ⚠️ Alleen beleid | ✅ Beleid + watchdog | Schakelaar op <org>/_admin/auth-policy/; een watchdog levert elk uur een auditgebeurtenis tenant.auth_policy.hw_key_violation per sleutel die niet hardwaregebonden is. |
| Handhaving van ondertekende commits | ✅ | ✅ | Schakelaar voor de hele organisatie + een actieve propagator die per repository regels voor branchbescherming aanmaakt of PATCHt. |
| Secret-scanning in een pre-receive-hook | ✅ Push protection | ✅ Gitleaks pre-receive | Andere leverancier, dezelfde beveiligingspoort. |
| IP-allowlist per organisatie: web-UI + REST-API | ✅ | ✅ | Eén IP-allowlist op <org>/_admin/security/access/ip-allowlist dekt het webbeheer, de fremforge-API, de webinterface van repository’s en de Forgejo-REST-API. |
| IP-allowlist per organisatie: Git via HTTPS, LFS, pakketten | ✅ | ✅ | Dezelfde lijst dekt Git via HTTPS (push, pull, clone), Git LFS en elke pakketregistry. |
| IP-allowlist per organisatie: push/pull via SSH | ✅ | ❌ Niet gedekt | SSH bereikt fremforge via een load balancer die het bronadres herschrijft naar een clusternode, dus het adres van de ontwikkelaar is niet zichtbaar; fremforge beoordeelt een verbinding niet op een adres waarvan het weet dat het onjuist is. SSH staat standaard uit (ssh_disabled=true); organisaties die IP-filtering op elke Git-bewerking nodig hebben, laten het uit en gebruiken HTTPS, dat de lijst wel dekt. |
| SSH-audittrail (timing + herleiding van fingerprints) | ⚠️ Leverancierspecifiek | ✅ | Een LTS-scraper herleidt fingerprint → gebruiker via de tabel public_key van Forgejo en levert de auditgebeurtenissen git.ssh_pull.ip_allowlist_observed_violation + git.ssh.tenant_disabled_observed. Handig voor alerts over “sleutelgebruik na offboarding”. |
| Voorbeeldmodus voor de IP-allowlist met alleen audit | ❌ | ✅ | Schakelaar “Audit only” die weigeringen die zouden plaatsvinden logt zonder te blokkeren: handig om een allowlist veilig uit te rollen voordat je gaat handhaven. |
| BYOIDC per tenant | ❌ Eén SAML/Entra-organisatie per GHEC-tenant | ✅ Ingebouwd: elke klantorganisatie koppelt een eigen IdP | Belangrijk voor multi-tenant SaaS-hosting op fremforge. |
| OIDC-SSO met meerdere bronnen | ⚠️ Eén SAML/OIDC | ✅ Meerdere bronnen | Meerdere IdP-knoppen op de inlogpagina van de tenant. |
| Dataplane alleen in de EU | ❌ VS | ✅ Ingebouwd (T Cloud Public EU-DE) | Harde eis voor veel gereguleerde klanten in de EU. |
| Prijs per gebruiker | $21/gebruiker/mnd (GHEC) | € 30/gebruiker/mnd (€ 306/gebruiker/jaar bij een jaarlijkse looptijd) | Eén vast tarief voor elke gebruiker, zonder prijsniveaus per gebruiker. Zie Facturatie. |
| Reviewsuggesties toepassen in een PR | ✅ | ✅ | Commit met één klik vanuit een ```suggestion-codeblok in een PR-review; head-SHA + branch worden aan de serverkant geverifieerd. Documentatie voor klanten bij Ontwikkelen → Issues en PR’s → Reviewsuggesties toepassen. Geleverd op 2026-05-24. |
| Publieke documentatiewiki bij private repository’s | ❌ GitHub Pages vereist een publieke repository of de GHEC Pages-add-on | ✅ Ingebouwd, per repository in te schakelen | Anonieme publieke leestoegang tot de repositorywiki op frem.sh/<org>/<repo>/wiki[/...], los van of de onderliggende repository publiek of privé is. Documentatie voor klanten bij Ontwikkelen → Wiki en publieke documentatie. Geleverd op 2026-05-24. |
| Door de klant instelbare auditbewaring | ❌ vast 7 jaar (geen invloed voor de klant) | ✅ Per tenant {90 / 180 / 365 / 730} dagen hot tier + 3 jaar WORM | De beheerder van de tenant stelt het doorzoekbare hot-tiervenster in bij Authenticatiebeleid → Bewaartermijn van het auditlog; het WORM-archief met hashketen van 3 jaar blijft ongewijzigd. Standaard: 90 dagen in het standaardabonnement, 365 dagen in enterprise. Geleverd op 2026-05-24. |
Het strategische verschil met GHEC: fremforge behandelt HTTPS+GCM als de primaire route, omdat MFA bij elke tokenvernieuwing vanzelf via de IdP doorwerkt; SSH is per organisatie in te schakelen, omdat de IP-handhaving daarvan op deze stack structureel zwakker is. Voor de meeste beveiligingseisen van enterprises (“MFA bij elke push”, “beperk via IP waarvandaan ontwikkelaars kunnen pushen”) is de standaard HTTPS+GCM strikt sterker dan de standaard met SSH-sleutels die GHEC uit de geschiedenis van GitHub heeft geërfd.
Stap 1: repository en geschiedenis migreren
fremforge draait upstream Forgejo, dat een ingebouwde importer voor GitHub-repository’s heeft. De importer kopieert de volledige Git-geschiedenis, issues, pull requests, opmerkingen, labels, mijlpalen, wiki-inhoud en releases, niet alleen de standaardbranch.
Met de ingebouwde importer (via de UI)
Vanuit de beheer-UI van fremforge voor je organisatie:
- Klik op + → Nieuwe migratie.
- Kies GitHub als bron.
- Plak de URL van de GitHub-repository (bijv.
https://github.com/acme/backend). - Plak je GitHub personal access token. Het token wordt alleen voor deze import gebruikt en niet bewaard nadat de import klaar is.
- Vink de soorten inhoud aan die je wilt importeren: Wiki, Issues, Pull requests, Releases, Labels, Mijlpalen.
- Kies de doelorganisatie en de repositorynaam op fremforge. De standaardwaarden volgen de GitHub-bron.
- Klik op Migreer repository.
De importer draait op de achtergrond. Voor een typische repository van 100-500 MB met een gemiddelde geschiedenis aan issues en PR’s kun je 2-10 minuten verwachten. Een voortgangsindicator in de beheer-UI toont de huidige fase (Git-geschiedenis klonen, issues importeren, PR’s importeren, releases importeren).
Met de API (via scripts)
Voor bulkmigraties script je de import tegen de fremforge-API. De endpoints voor migraties, repository’s, issues en PR’s zijn het Forgejo-eigen API-oppervlak dat fremforge ongewijzigd beschikbaar stelt op frem.sh/_app/api/v1/...; ze staan niet apart beschreven in de OpenAPI-specificatie van fremforge (die alleen de toevoegingen van het fremforge-controlplane dekt: gebruikers, beleid, bevindingen, exports, mandaten). Voor de actuele referentie van de Forgejo-eigen endpoints, zie docs.frem.sh/api/openapi.yaml of de upstream OpenAPI-documentatie van Forgejo op docs.codeberg.org/api/. fremforge host de Swagger-UI van Forgejo niet in productie (bewust uitgeschakeld, omdat het een bekend verkenningsdoel is). Alle endpoints hieronder zijn standaard-API van Forgejo/Gitea.
# Build the JSON body via jq so the token is JSON-string-escaped safely
# (a token containing `"` or `\` would otherwise break the body or
# corrupt your migration auth).
jq -nc \
--arg clone_addr "https://github.com/acme/backend.git" \
--arg auth_token "$GITHUB_TOKEN" \
--arg repo_owner "acme" \
--arg repo_name "backend" \
'{clone_addr: $clone_addr, auth_token: $auth_token,
service: "github", repo_owner: $repo_owner, repo_name: $repo_name,
wiki: true, issues: true, pull_requests: true,
releases: true, labels: true, milestones: true,
lfs: true}' \
| curl -X POST "https://frem.sh/api/v1/repos/migrate" \
-H "Authorization: Bearer ${FREMFORGE_TOKEN}" \
-H "Content-Type: application/json" \
-d @-Paralleliseer over repository’s met GNU parallel of een klein aansturingsscript. Beperk het tot 3-5 gelijktijdige imports, zodat je noch de PAT-rate-limit van GitHub noch je eigen bandbreedte verzadigt.
Wat de importer wel en niet importeert
Wordt correct geïmporteerd:
- Alle branches en tags, met volledige commitgeschiedenis.
- Issues met titels, inhoud, opmerkingen, labels, mijlpalen en toegewezen personen (gekoppeld via e-mail als de gebruiker op fremforge bestaat).
- Pull requests, inclusief reviewopmerkingen, merge-status en reden van sluiten. Open PR’s worden open PR’s; gesloten PR’s zijn gesloten.
- Releases, inclusief binaire bijlagen (verplaatst naar de LFS-opslag van fremforge in de EU).
- Wikipagina’s.
Wordt niet geïmporteerd:
- De geschiedenis van GitHub Actions-workflowruns. Historische runs blijven op GitHub; nieuwe runs beginnen opnieuw op fremforge.
- Waarden van secrets en omgevingsvariabelen: die voer je opnieuw in (zie stap 2).
- Integraties van derden die op GitHub zijn ingesteld. Die moet je opnieuw koppelen (zie stap 5).
- GitHub Projects (classic of Projects v2). Forgejo heeft geen 1-op-1-equivalent; de basisinhoud van projectborden kun je handmatig opnieuw aanmaken of via de Projects-functie van fremforge (fase 1.5).
- Dependabot-alerts. De dependency-scans van fremforge draaien onafhankelijk op Trivy/osv-scanner en leveren hun eigen bevindingen.
- Beveiligingsadviezen van repository’s. Maak de advisories die je wilt houden opnieuw aan onder Beveiliging › Rapporten › Beveiligingsadviezen (Beveiligingsadviezen), of via de bijbehorende API vanuit
GET /repos/{owner}/{repo}/security-advisoriesvan GitHub; gepubliceerde advisories krijgen een nieuweFFSA--id, dus houd de GHSA-id in de verwijzingen. - GitHub Discussions. Daar heeft Forgejo vandaag geen equivalent voor.
- Meldingsvoorkeuren per gebruiker. Leden abonneren zich opnieuw op fremforge.
Grote repository’s
Is je repository groter dan 2 GB of je LFS-opslag groter dan 5 GB, dan kan de importer in de UI een time-out krijgen. Het Forgejo-endpoint /repos/migrate heeft geen instelbare time-out per aanroep, dus de aanbevolen terugvaloptie is lokaal een directe Git-mirror-clone te maken en die met git push --mirror naar een vooraf aangemaakte lege fremforge-repository te pushen:
# Clone the GitHub repo bare with full history
git clone --mirror https://github.com/acme/backend.git
cd backend.git
# If the repo uses LFS, fetch all LFS content
git lfs fetch --all
# Create an empty repo on fremforge (via admin UI or API), then:
git remote set-url origin https://frem.sh/acme/backend.git
git push --mirror
git lfs push --all originBij deze route worden issues en de PR-geschiedenis niet meegenomen. Importeer die apart via de migrate-API van Forgejo (POST /api/v1/repos/migrate, zie het canonieke curl-voorbeeld bovenaan deze pagina) met "wiki": false, "issues": true, "pull_requests": true, en richt het verzoek op de URL van de al gepushte fremforge-repository, zodat alleen de metadata van GitHub wordt opgehaald.
Secret-scanning in de pre-receive-hook houdt deze push tegen. fremforge voert gitleaks uit als pre-receive-hook van Forgejo bij elke push, ook bij de --mirror-vorm hierboven. Bevatten je historische commits echte secrets (gelekte AWS-sleutels, verlopen Stripe-tokens, ingebedde private sleutels), dan wordt de push geweigerd, met de betreffende commit-SHA’s in de uitvoer, en mislukt de hele mirror-bewerking atomair. Dat is bewust: een secret uit de publieke geschiedenis importeren in fremforge roteert het NIET stilletjes bij de upstream-provider, dus de veilige route is eerst opschonen en dan importeren. Twee herstelopties:
- Schoon eerst de geschiedenis op met
git-filter-repo(aanbevolen) of BFG Repo-Cleaner, en push daarna opnieuw. Laat de eigenaar van het secret weten dat de geschiedenis bij de upstream-provider ook lekt, wat je ook doet op de bestemming: roteer de gelekte inloggegevens bij de bron. - Vraag een eenmalige uitzondering aan bij
support@frem.shvoor secrets in gearchiveerde geschiedenis waarvan bekend is dat ze ingetrokken zijn. De uitzondering wordt gelogd, geaudit en gekoppeld aan een schriftelijke bevestiging dat de secrets al geroteerd zijn.
Land eerst main, zodat de LFS-push zin houdt. Omdat git push --mirror atomair is tegenover gitleaks (alle refs in één transactie; één weigering = lege mirror = de LFS-push heeft niets om naartoe te pushen), loont het om eerst één branch te pushen en de regels te bevestigen voordat je alle refs tegelijk pusht. Tussen git remote set-url en git push --mirror:
git push origin main --force-with-leaseKomt main erdoor, dan komen de overige refs er bijna altijd ook door (de regels van gitleaks kijken naar inhoud, niet naar branches). Wordt main geweigerd, schoon dan op of vraag een uitzondering aan voordat je de mirror opnieuw probeert; het heeft geen zin andere refs te pushen zolang de commit met het secret op main nog bestaat.
De hook gebruikt dezelfde gitleaks-regels die elke fremforge-repository beschermen; het is geen controle die speciaal voor migraties bestaat. Voer pre-migration-check.sh uit voordat je begint; dat brengt dezelfde bevindingen aan het licht die de hook zou vangen, zodat je kunt opschonen voordat het migratievenster opengaat.
LFS-opslagquotum en capaciteit voor grote repository’s
git lfs push --all origin schrijft objecten in het LFS-quotum van je fremforge-tenant. Plan je quota:
| Abonnement | Inbegrepen LFS-opslag | Zachte grens voordat er wordt afgeremd |
|---|---|---|
| Standard (€ 30/gebruiker/mnd) | 5 GB per gebruiker, gebundeld op organisatieniveau | 90% van de pool: uploads geven dan 429 quota_warning terug |
| Enterprise-on-demand | In overleg | Volgens contract |
Onder het quotum van het abonnement liggen twee praktische grenzen:
- Grootte van de kale Git-repository. Is de kale
.gitvan de repository (nagit gc --aggressive) groter dan ongeveer 5 GiB, neem dan vóór de migratie contact op metsupport@frem.sh, zodat we kunnen bevestigen dat er ruimte is voor je repository. - Zeer grote LFS-pushes. Een
git lfs pushvan meer dan ongeveer 100 GiB in één sessie moet je mogelijk opsplitsen in porties van ≤50 GiB om afremming door de rate-limit te voorkomen. De fout ziet eruit als HTTP 503 metX-Reserved: ratelimitin de respons: wacht 60 s en ga verder; LFS kan worden hervat.
Weet je niet zeker hoe groot de LFS-opslag wordt, voer dan git lfs ls-files --size --all | awk '{s+=$2} END {print s/1024/1024/1024 " GiB"}' uit tegen de bronrepository voordat je de mirror-push start.
Stap 2: secrets en omgevingsvariabelen
GitHub bewaart secrets op het niveau van organisatie, omgeving en repository. fremforge gebruikt dezelfde drie niveaus.
Belangrijk: waarden van secrets kun je niet exporteren uit GitHub. De API van GitHub geeft de namen van secrets terug, maar nooit de waarden. Je kent de waarde zelf (roteren bij de migratie, aanbevolen) of je haalt hem uit je bron van waarheid voor secrets (wachtwoordmanager, vault, CI-orkestratie).
Secrets opnieuw invoeren
Bepaal per secret:
- Is dit langlevende inloggegevens die hoe dan ook door OIDC-federatie vervangen zouden moeten worden? Zo ja, stel OIDC-federatie met T Cloud Public in (zie stap 3) en verwijder het secret in plaats van het te migreren.
- Is dit een API-sleutel van een derde partij of inloggegevens voor een dienst zonder OIDC-alternatief? Roteer ze bij de bron en zet de nieuwe waarde in fremforge.
- Is dit een cryptografische sleutel die binnen builds wordt gebruikt? Roteer hem en zet hem daarna in fremforge.
Zet secrets op het juiste niveau in de beheer-UI van fremforge:
- Organisatiesecrets, beschikbaar voor elke repository in de organisatie. In te stellen bij Organisatiebeheer → Secrets (
frem.sh/<org>/_admin/secrets). - Omgevingssecrets, alleen beschikbaar in de genoemde omgeving (bijv.
production,staging). In te stellen bij Organisatiebeheer → Omgevingen →<env>→ Omgevings-secrets. - Repositorysecrets, beperkt tot één repository. In te stellen bij Repository → Instellingen → Actions → Geheimen.
Omgevingsvariabelen (configuratie die niet geheim is)
GitHub Actions ondersteunt env: en vars: op het niveau van workflow, job en stap. fremforge Actions ondersteunt dezelfde syntaxis; voor inline variabelen is geen migratie nodig.
Voor variabelen op organisatie- en repositoryniveau (de vars:-context in GitHub) heeft fremforge dezelfde indeling. In te stellen bij Instellingen → Actions → Variabelen in de Forgejo-instellingen van de organisatie of van de repository.
Stap 3: Actions-workflows aanpassen
Forgejo Actions is grotendeels compatibel met GitHub Actions, maar niet bit voor bit identiek. Een workflow die op GitHub draait, draait meestal op fremforge na twee of drie specifieke aanpassingen. De compatibiliteitsmatrix voor de top 20 Marketplace-actions op docs.frem.sh/marketplace-compat beschrijft welke actions ongewijzigd werken, welke een wrapper nodig hebben en welke geen equivalent op fremforge hebben.
Wijzigingen die voor bijna elke workflow gelden
1. uses:-verwijzingen kunnen voor de belangrijkste GitHub-actions actions/*@version blijven.
De runner van fremforge lost uses:-directives op via de mirrors van fremverk die alleen in de EU staan, op https://frem.sh/<owner>/<repo> (één mirror-organisatie per upstream-uitgever, dus actions/checkout wordt frem.sh/actions/checkout); runner-VM’s maken bij het starten van een job geen directe uitgaande verbinding met github.com (bijlage A.6 bij de verwerkersovereenkomst). Dat werkt voor actions/checkout, actions/setup-node, actions/setup-go, actions/setup-python, actions/setup-java, actions/cache, actions/upload-artifact, actions/download-artifact en de rest van de officiële actions/*-set die al gespiegeld is. Voor gespiegelde actions hoef je je uses:-regels niet te wijzigen; ontbreekt een verwijzing, zie dan Veelvoorkomende valkuilen hieronder.
2. De betekenis van ${{ secrets.GITHUB_TOKEN }} wijkt iets af.
GitHub levert bij elke workflow automatisch een token met rechten die beperkt zijn tot de aanroepende repository. Forgejo levert een equivalent als ${{ secrets.FORGEJO_TOKEN }}, en ${{ secrets.GITHUB_TOKEN }} is een alias voor hetzelfde token, dus de meeste workflows werken gewoon. Gebruik een van die twee namen en niet het oudere ${{ secrets.GITEA_TOKEN }}. Sinds 21 oktober 2026 zetten de gehoste runners (forgejo-runner 13) geen enkele GITEA_*-omgevingsvariabele meer, dus vervang GITEA_ACTIONS door FORGEJO_ACTIONS of GITHUB_ACTIONS, en GITEA_ACTIONS_RUNNER_VERSION door FORGEJO_ACTIONS_RUNNER_VERSION. Verwacht een workflow specifiek GitHub-API-gedrag achter die token (bijv. het aanroepen van de GitHub Checks API), dan moet hij worden aangepast. Voor Forgejo-eigen check runs staat de equivalente API op frem.sh/api/v1/repos/{owner}/{repo}/check-runs.
3. Actions die de REST-API van GitHub rechtstreeks aanroepen, moeten worden aangepast.
Gebruikt een workflow curl https://api.github.com/... of octokit om de REST-API van GitHub rechtstreeks aan te roepen, dan moeten die aanroepen naar https://frem.sh/_app/api/v1/... gaan, met de fremforge-API (op REST-niveau grotendeels compatibel met GitHub). Zie de OpenAPI-specificatie.
4. De standaardshell voor stappen verschilt.
De standaardshell van de Forgejo-runner is bash met POSIX-vlaggen. De standaarden van de GitHub-runner verschillen subtiel tussen Linux en Windows/macOS. Hangt je workflow af van specifiek quotinggedrag van de shell, zet dan expliciet shell: bash (Linux), shell: pwsh (Windows) of shell: sh (alleen POSIX).
Wijzigingen die voor sommige workflows gelden
De context if: github.*.
Forgejo Actions levert github.*-contextvariabelen met dezelfde namen als GitHub Actions. Bijna alle if-expressies werken ongewijzigd. Randgevallen gaan over GitHub-specifieke metadata (bijv. github.event.pull_request.auto_merge), waarvan Forgejo misschien niet precies dezelfde eigenschap beschikbaar stelt.
Marketplace-actions die specifiek voor de GitHub-API zijn.
Voorbeelden: peter-evans/create-pull-request, marocchino/sticky-pull-request-comment, nwtgck/actions-netlify. De meeste werken direct, omdat het REST-oppervlak van fremforge hun API-aanroepen accepteert. Een handvol heeft kleine aanpassingen nodig. De top-20-matrix beschrijft specifieke oplossingen.
Workflows die herschreven moeten worden
Gebruikt je workflow functies die specifiek voor GitHub Enterprise zijn (de API voor organisatierulesets, metrics-endpoints die specifiek voor GHES zijn, de API voor Copilot-extensies, GitHub Packages buiten npm/Docker/Maven), dan moeten die functies worden vervangen. Meestal is de vervanging fremforge-eigen:
- Organisatierulesets → beleid op organisatieniveau in fremforge (Organisatiebeheer → Beveiliging → Beleid → Repositoryregels).
- GitHub Packages → de pakketregistry van fremforge (ondersteunt npm, Maven, Docker, NuGet, PyPI, RubyGems, Composer, Go).
- Copilot Extensions → bewust buiten de scope van fremforge (zie het bericht over onze AI-koers op www.frem.sh).
Stap 4: SSH-sleutels opnieuw registreren
Publieke SSH-sleutels horen bij de gebruiker en worden niet gemigreerd. Elke ontwikkelaar voegt zijn of haar publieke SSH-sleutel toe aan het eigen fremforge-account:
- Log in bij fremforge.
- Instellingen → SSH / GPG sleutels → Sleutel toevoegen.
- Plak de publieke sleutel (
~/.ssh/id_ed25519.pubof vergelijkbaar).
De fingerprints van de hostsleutels voor frem.sh staan op www.frem.sh/ssh-fingerprints. Ontwikkelaars moeten ze bij de eerste SSH-verbinding controleren om een onopgemerkte MITM te voorkomen. De fingerprint verschijnt bij de eerste verbinding; ontwikkelaars vergelijken hem met de trustpagina, bevestigen, en de sleutel wordt vastgepind voor latere verbindingen.
Voor teams die SSH-certificaatautoriteiten gebruiken, ondersteunt fremforge het instellen van vertrouwde CA’s rechtstreeks in de beheer-UI van de organisatie op <your-org>/_admin/auth-policy: het onderdeel SSH CA staat onder de schakelaar “SSH-protocol toestaan” (op 2026-05-26 opgenomen in Authenticatiebeleid; het losse /admin/ssh-ca/ stuurt hierheen door). Plak de publieke OpenSSH-sleutel van je CA, kies een principal-beleid (gebruikersnaam / e-mail / opaque) en dwing optioneel “require cert auth” af, zodat inloggen met een gewone publieke sleutel wordt geweigerd. Zie het onderdeel SSH-certificaatautoriteit in de gids Authenticatiebeleid voor de volledige inrichting, inclusief voorbeelden voor integratie met Smallstep / Vault. Elke gebruiker die zich authenticeert met een certificaat dat de CA uitgeeft, krijgt toegang met de rechten van het bijbehorende fremforge-account.
Voor teams waar SSO verplicht is (sso_required = true op organisatieniveau), valideert SSH-authenticatie bovendien bij elke verbinding een OIDC-refreshtoken tegen de IdP van de tenant (15 minuten in de cache). Wordt een gebruiker aan de kant van de IdP gedeprovisioned, dan is SSH-toegang dus binnen 15 minuten geblokkeerd, ook als de SSH-sleutel nog op fremforge geregistreerd staat. Je hoeft sleutels niet apart op te ruimen.
Stap 5: integraties van derden opnieuw koppelen
Integraties die op GitHub zijn ingesteld (webhooks, CI-meldingen naar Slack/Teams, deploy-hooks naar Vercel/Netlify, synchronisatie met issuetrackers als Jira/Linear, codereviewtools als Sourcegraph of Graphite) worden niet automatisch gemigreerd. Elke integratie moet opnieuw worden gekoppeld.
Webhooks
GitHub-webhooks staan bij Repository → Settings → Webhooks. Webhooks in fremforge staan op dezelfde plek in de beheer-UI. De vorm van de webhook-payload is grotendeels compatibel; de belangrijkste verschillen:
- De header
X-GitHub-Eventvan GitHub heet op fremforgeX-Forgejo-Event(ofX-Gitea-Eventvoor afnemers die Gitea-compatibel zijn). De meeste generieke webhook-ontvangers accepteren beide. - De afleveringsidentificatie is
X-Gitea-Delivery+X-Hook-UUID(de tegenhanger vanX-GitHub-Deliveryvan GitHub). Beide zitten bij elke webhook-aflevering van fremforge; de meeste ontvangers gebruiken een van beide als sleutel. - De gebeurtenistypen zijn een ruime superset van de kerngebeurtenissen van GitHub.
push,pull_request,pull_request_review,issues,issue_comment,release,create,delete,forkenstarzijn er allemaal. - De signatuurheader is
X-Forgejo-Signature(HMAC-SHA256 met je webhook-secret).
Voor ontvangers die tegen de API van GitHub zijn geschreven (integraties met Slack, Discord, PagerDuty) zijn er twee opties:
- Stel de ontvanger opnieuw in op zijn Forgejo-eigen integratie. De Forgejo-integratie van Slack, het Forgejo-webhookdoel van Discord enzovoort bestaan meestal en zijn de nettere route.
- Pas de webhook aan de kant van de ontvanger aan. Is de ontvanger een eigen interne dienst, voeg dan naast de afhandeling van GitHub-gebeurtenissen afhandeling van Forgejo-gebeurtenissen toe. Meestal een kleine wijziging.
CI-integraties (CircleCI, TravisCI, Jenkins)
Draai je CI buiten de forge (CircleCI, externe Jenkins, Buildkite), dan is de migratie eenvoudig: richt die CI-systemen op fremforge-repository’s in plaats van GitHub-repository’s. De meeste externe CI-systemen ondersteunen Forgejo/Gitea als bron; de configuratiewijziging zit in het CI-systeem, niet in fremforge.
De meeste teams die naar fremforge migreren, grijpen de gelegenheid aan om over te stappen op de gehoste runners van fremforge en de externe CI uit te faseren. Runnerminuten zitten in de vaste prijs per gebruiker. Zie het TCO-bericht op de blog van fremverk voor de berekening.
Deploydoelen (Vercel, Netlify, Cloudflare Pages)
Elke dienst koppelt opnieuw aan fremforge via ingebouwde ondersteuning (Vercel en Netlify hebben integraties met Forgejo/Gitea als Git-bron) of via een generieke deploy-hook op Git-push. Leg je nieuwe webhook-URL’s vast en werk ze bij in het dashboard van elke dienst.
Synchronisatie met issuetrackers (Jira, Linear, Zendesk)
Is je synchronisatie met de issuetracker gebaseerd op Git-commits (commits via een ID aan tickets koppelen), dan blijft die werken. De commit-SHA’s blijven bij de migratie behouden. Is de synchronisatie gebaseerd op de GitHub-API (luisteren naar PR-gebeurtenissen, GitHub-issues opvragen), stel hem dan opnieuw in op webhooks van fremforge of zet hem uit.
Stap 6: DNS en eigen domeinen (indien van toepassing)
fremforge levert repository-inhoud alleen op frem.sh/<org>/<repo>. Eigen Git-domeinen van klanten worden niet ondersteund: er is geen equivalent van de functie “custom hostname” van GitHub Enterprise Server, waarbij TLS eindigt met jouw certificaat op git.company.com. Twee gevolgen die we expliciet willen noemen:
Vanity-CNAME zonder TLS
Een vanity-CNAME in de DNS van de klant (bijv. een interne git.company.com CNAME → frem.sh) is technisch mogelijk, maar het geleverde TLS-certificaat is altijd het *.frem.sh-certificaat van fremforge, NIET een *.company.com-certificaat. Een browser die https://git.company.com/... opent, toont een waarschuwing over een niet-overeenkomende naam, tenzij de klant ook een eigen certificaat regelt en dat via een eigen reverse proxy ervoor serveert. Dat is werk aan de kant van de klant: fremforge beëindigt geen TLS voor vanity-hostnamen, accepteert geen certificaten van klanten en draait geen SNI-laag met meerdere certificaten.
Aanbevolen route voor klanten die van GitHub Enterprise Server overstappen: neem het URL-patroon frem.sh/<org>/* direct over. Werk interne links, CI-configuraties en documentatie bij naar de nieuwe URL’s. De route met een vanity-CNAME en een certificaat van de klant levert operationele schuld op (certificaatvernieuwing, beheer van de proxy) en is geen configuratie die fremforge ondersteunt.
Vereist je inkoop een SLA voor een vanity-domein, sluit dan een Enterprise-on-Demand-contract af: dat opent een gesprek over een eigen edge-laag met beëindiging van het certificaat van de klant, maar dat valt buiten de selfservicelaag.
Wat wel en niet wordt gemigreerd
Dit onderdeel somt op met welke getrouwheid de GitHub-artefacten door de migratie komen. Gebruik het als afstemmingschecklist vóór de migratie.
| Artefact | Gemigreerd? | Opmerkingen over getrouwheid |
|---|---|---|
| Repository-inhoud (commits, branches, tags) | ✓ | SHA’s blijven gelijk; volledige geschiedenis behouden |
| LFS-objecten | ✓ (≤ 5 GB pool via de UI-importer; groter via mirror-clone) | Dezelfde OID’s; de groottegrens is operationeel, niet van het protocol |
| Issues | ✓ naar beste vermogen | De importer van Forgejo kent geïmporteerde issues opeenvolgende Issue.Index-waarden toe; gaten in de nummering van de bron blijven niet behouden (bijv. GitHub #1, #2, #42 wordt #1, #2, #3 op Forgejo). Verwijzingen tussen issues in de tekst van opmerkingen worden herschreven naar de toegekende nummers als de importer ze kan oplossen; niet-oplosbare verwijzingen blijven letterlijke tekst. Doet exacte nummering ertoe (langlopende issuetrackers met publieke bladwijzers), dan is de route via de API om op de bestemming vóór de import voor elk gat placeholder-issues aan te maken en die na de import te verwijderen. |
| Pull requests | ✓ naar beste vermogen | PR’s delen dezelfde nummerreeks als issues (de gecombineerde teller van Forgejo, net als bij Gitea). De onderlinge volgorde blijft dus behouden, maar voor de absolute nummers geldt het voorbehoud uit de issues-rij hierboven: gaten in de nummering van de bron vallen bij de import weg. Heeft je bron Issue #1, PR #2, Issue #5, PR #7, dan wordt dat op de bestemming Issue #1, PR #2, Issue #3, PR #4. Gebruik dezelfde oplossing met vooraf aangemaakte placeholders als bij issues als exacte PR-nummers ertoe doen (publieke bladwijzers, deeplinks). Openstaande PR’s worden als draft gemigreerd als ze op het moment van de migratie open zijn. |
| Reviewopmerkingen bij PR’s (inline, aan regels gekoppeld) | ⚠ gedeeltelijk | Aan regels gekoppelde opmerkingen worden gewone PR-opmerkingen (een beperking van het datamodel tussen forges). Zie “Reviewopmerkingen bij PR’s worden als gewone opmerkingen geïmporteerd” hieronder. |
| Regels voor branchbescherming | ✗, opnieuw aanmaken | De vorm van de branch_protections-regels van GitHub komt niet overeen met de vorm BranchProtection van Forgejo. Vóór de migratie: leg elke regel vast via gh api /repos/<owner>/<repo>/branches/<name>/protection. Na de migratie: maak ze opnieuw aan via het tabblad Standaarden voor repositories in de beheer-UI van fremforge + een override per repository. Een .gitea/branch-protection.yaml-sjabloon in de organisatie kan de gewenste stand vastleggen; toepassen gebeurt vandaag door een operator via de beheer-UI (branchbescherming als code via de API komt in fase 2). |
| Webhooks | ✗, niet behouden | Het migrate-endpoint van Forgejo somt de webhooks van de bronforge niet op (de downloaders voor GitHub/GitLab lopen hooks niet langs; MigrateRepoOptions heeft geen vlag migrate webhooks). Klanten komen dus aan zonder webhooks op de bestemming. Maak webhooks na de migratie opnieuw aan op fremforge aan de hand van het overzicht dat pre-migration-check.sh maakt: dat geeft per bronwebhook de URL + gebeurtenissen. HMAC-secrets zijn niet uit GitHub op te halen, dus elke ontvangende integratie heeft ook een nieuw secret nodig, ingesteld in het dashboard van de brondienst zodra de fremforge-URL opnieuw is geregistreerd. fremforge levert historische gebeurtenissen ook niet opnieuw af. |
| Submodules | ⚠ URL herschrijven vereist | URL’s in .gitmodules die naar github.com/<org>/<repo> wijzen, blijven na de migratie letterlijke github.com-URL’s. Werk na de migratie (a) elk .gitmodules-item bij naar de nieuwe fremforge-URL en commit dat, OF (b) gebruik per clone git config submodule.<name>.url <fremforge-url> als de bovenliggende repository niet in jouw beheer is. De importer van fremforge herschrijft .gitmodules niet automatisch, omdat submodule-URL’s inhoud zijn die van de auteur van het project is. |
| Actions-secrets op organisatieniveau | ✗, opnieuw invoeren | Secrets zijn bewust niet via de API uit GitHub terug te halen. Voer ze opnieuw in bij Organisatiebeheer → Secrets (frem.sh/<org>/_admin/secrets). Vóór de migratie: maak een lijst met gh secret list --org <org>, zodat je de namen hebt om opnieuw in te voeren. |
| Actions-variabelen op organisatieniveau (niet geheim) | ✓ via export | Gewone variabelen kun je exporteren met gh variable list --org <org> --json name,value > gh-vars.json en opnieuw importeren via de beheer-UI van fremforge. Voor bulkimport via de API stuur je de export door het variables-endpoint: jq -c '.[]' < gh-vars.json | while read row; do n=$(jq -r .name <<<"$row"); v=$(jq -r .value <<<"$row"); curl -fsS -X POST "https://frem.sh/_app/api/v1/orgs/<org>/actions/variables" -H "Authorization: Bearer $T" -H "Content-Type: application/json" -d "{\"name\":\"$n\",\"value\":\"$v\"}"; done. Dezelfde vorm werkt voor variabelen op repositoryniveau (vervang /orgs/<org>/ door /repos/<owner>/<repo>/). |
| GitHub Discussions | ✗, geen equivalent | Forgejo heeft vandaag geen equivalent voor Discussions. Exporteer naar een apart archief als discussiethreads voor je organisatie belangrijk zijn. |
| GitHub Projects (borden) | ✗, geen equivalent | Projectopvolging bouw je opnieuw op met issues, labels en mijlpalen in fremforge. |
Hervatbaarheid
Het Forgejo-endpoint /repos/migrate is niet hervatbaar. Mislukt de aanroep halverwege (verbinding weg, rate-limit van de bron-API enzovoort), dan blijft de half geïmporteerde repository in een inconsistente staat achter. Herstelprocedure:
- Verwijder de halve repository via Instellingen → Verwijderen in de beheer-UI van fremforge.
- Doe de migrate-aanroep meteen opnieuw. Geeft hij 422 terug met
repository already exists, wacht dan 5 seconden en probeer het opnieuw: dat is replicatievertraging van RDS op het pad van de leesreplica, geen tombstone-cyclus van Forgejo. - Mislukt de tweede poging op dezelfde manier, gebruik dan een nieuwe repositorynaam.
Voor repository’s waarbij opnieuw importeren duur is (veel LFS, veel issues), gebruik je de terugvaloptie met een lokale mirror uit “Grote repository’s”: git push --mirror is van nature hervatbaar, omdat Git zelf netjes met verbroken verbindingen omgaat.
Verificatie na de migratie
Naast de lijst “verifiëren en uitfaseren” in stap 7 hieronder volgt hier de verificatiechecklist na de migratie die klanten het vaakst vergeten:
- Vergelijk het aantal commits.
git rev-list --count HEADin de GitHub-clone tegenover de fremforge-clone. De aantallen moeten exact gelijk zijn. - Vergelijk de lijst met branches.
git branch -r | sortaan beide kanten endiffop de uitvoer. Verouderderefs/pull/*-refs van GitHub worden niet gemigreerd (Forgejo nummert PR’s in een eigen ref-ruimte); al het andere moet overeenkomen. - Vergelijk de lijst met tags.
git tag --sort=v:refnameaan beide kanten; verwacht identieke lijsten. - Vergelijk het aantal LFS-pointers.
git lfs ls-files | wc -l; de aantallen moeten exact gelijk zijn. Is dat niet zo, voer dangit lfs fetch --all && git lfs push --all originuit tegen de fremforge-remote. - Aantal en nummering van issues en PR’s.
gh issue list --limit 5000 --state all --json number | jq lengthop GitHub tegenover/api/v1/repos/<org>/<repo>/issues?state=allop fremforge (met paginering). Pagineringslus voor fremforge:n=0; for p in $(seq 1 200); do c=$(curl -fsS "https://frem.sh/api/v1/repos/<org>/<repo>/issues?state=all&page=$p&limit=50" -H "Authorization: Bearer $T" | jq length); [ "$c" = 0 ] && break; n=$((n + c)); done; echo $n. Nummering behouden. - CI groen. Start een no-op-build op
mainen controleer dat de Forgejo Actions-runsuccessbereikt. Zo vang je gaten in deuses:-mirrors op (de meest voorkomende CI-breuk na een migratie).
Komt bij een van deze controles een afwijking naar boven, faseer de GitHub-bron dan niet uit voordat de afwijking is opgelost.
Stap 7: verifiëren en uitfaseren
Na de migratie:
- Clone de gemigreerde repository uit fremforge, voer de build uit en controleer dat de tests slagen.
- Open een test-PR om te controleren dat de pre-receive-secretscanner, de dependency-scanner en de verificatie van ondertekende commits actief zijn zoals verwacht.
- Kijk in de weergave Bevindingen in de beheer-UI of de scans van de gemigreerde geschiedenis geen verrassende resultaten opleveren.
- Controleer bij Instellingen → Webhooks → Recente bezorgingen dat webhooks correct worden afgeleverd.
- Controleer dat inloggen via SSO werkt voor elke gebruiker die de repository gaat gebruiken.
- Werk documentatie en interne wiki’s bij, zodat ze naar de nieuwe repository-URL’s wijzen.
- Zet de GitHub-repository’s na 30 dagen succesvol gebruik op fremforge op gearchiveerd. Verwijder ze niet; bewaar ze voor de auditgeschiedenis.
Terugdraaien (gedeeltelijk, plan erop)
Een migratie is gedeeltelijk omkeerbaar, niet volledig. Wees eerlijk over wat wel en niet heen en terug kan voordat je productieverkeer overzet.
Wat terugdraaien WEL kan herstellen:
- Git-geschiedenis:
git push --mirrorvanuit een lokale fremforge-clone terug naar de GitHub-repository herstelt branches, tags en commits. - Webhooks + integraties: zet ze aan de kant van GitHub weer aan; je moet de doel-URL’s van de webhooks handmatig terugzetten naar endpoints die door GitHub worden gehost.
Wat terugdraaien NIET volledig getrouw kan herstellen:
- Issues, PR’s en opmerkingen die na de migratie zijn aangemaakt: Organisatiebeheer → Gegevensexport van fremforge levert een JSON-dump, maar de import-API van GitHub gebruikt een ander schema, dus opnieuw importeren is handmatig koppelwerk. Issuenummers komen niet overeen; verwijzingen in commitberichten lopen dood. Toeschrijving aan auteurs vereist dat elke bijdrager weer een GitHub-account heeft. Reacties, reviewthreads en de koppeling van inline opmerkingen aan regels overleven de rondgang meestal niet.
- CI-geschiedenis + Actions-logs die op fremforge zijn aangemaakt: niet te exporteren in een equivalent formaat.
- fremforge-specifieke bevindingen: weigeringen door secret-scans, resultaten van dependency-scans en attestaties van ondertekende commits die op fremforge zijn aangemaakt, hebben geen GitHub-equivalent om in te importeren.
Behandel de migratie voor productiegebruik als een deur die maar één kant op gaat. Draai eerst een pilot met één niet-kritieke repository; controleer dat CI, webhooks en SSO werken; migreer daarna de rest in porties. “Binnen 30 dagen omkeerbaar” geldt alleen voor het terugdraaien van de Git-geschiedenis; reken er niet op voor het volledig herstellen van de samenwerkingsstand.
Veelvoorkomende valkuilen
LFS-objecten zijn na de migratie niet zichtbaar.
De importer in de UI handelt LFS voor kleine pools (<5 GB) automatisch af. Voer voor grotere pools git lfs fetch --all uit op een lokale mirror-clone en daarna handmatig git lfs push --all origin naar fremforge.
Actions-workflows mislukken bij de eerste run met “action not found”.
De mirrors op https://frem.sh/<owner>/<repo> (zie het oplossen van actions hierboven) dekken de standaard actions/*-set en tien andere uitgeversorganisaties. Een mislukte uses:-verwijzing betekent dat de action nog niet gespiegeld is: open een ticket via support@frem.sh met de ontbrekende verwijzing, dan neemt de volgende mirror-ronde hem mee; of pin op een eerder opgeloste versie die al in de cache staat.
Reviewopmerkingen bij PR’s worden als gewone opmerkingen geïmporteerd.
De importer van Forgejo zet reviewopmerkingen bij PR’s om naar PR-opmerkingen, niet naar reviewopmerkingen op regelniveau. Dat is een beperking van het datamodel tussen forges; inline reviewopmerkingen verliezen de context van de regel waaraan ze hingen. Oplossing: exporteer voor repository’s waar inline opmerkingen belangrijk zijn die opmerkingen vóór de migratie via de API van GitHub naar een apart databestand en bewaar ze als archiefbijlage bij de gemigreerde PR.
Gebruikers worden niet automatisch gekoppeld.
De importer koppelt GitHub-gebruikers op e-mailadres. Gebruikers van wie het GitHub-e-mailadres niet overeenkomt met hun fremforge-e-mailadres (bijv. een persoonlijk adres op GitHub en een bedrijfsadres op fremforge) verschijnen als “Unknown user” bij geïmporteerde issues. Koppel ze vooraf door het e-mailadres van de GitHub-kant vóór de import als secundair adres aan het fremforge-account toe te voegen, of accepteer de weergave “Unknown user” en vertrouw op de oorspronkelijke toeschrijving in de commitgeschiedenis.
Hulp krijgen
Werkt iets in deze gids niet voor jouw situatie:
- Mail naar support@frem.sh met een onderwerpregel die begint met
MIGRATION, GITHUB -en een beschrijving van waar je vastloopt. - Zit je in het early-adopter-abonnement, dan heb je zonder extra kosten een directe lijn met het bouwteam van fremforge voor hulp bij je migratie.
Zie ook: Migratiegids voor GitLab · Migratiegids voor Azure DevOps · Compatibiliteitsmatrix van de top 20 Marketplace-actions · Checklist voor de migratie.