Zelfgehoste Git-server: Forgejo, Gitea of cgit kiezen
Vergelijk vier manieren om een Git-server te draaien op basis van RAM-gebruik. Ontdek welke optie geschikt is voor uw 1 GB VPS, van kale SSH-repo's tot volledige platforms.
Welke zelfgehoste Git-server moet u draaien
Een zelfgehoste Git-server is geen enkelvoudig product, en het RAM (random access memory) van uw VPS bepaalt welke versie u kunt gebruiken. Git heeft geen eigen daemon nodig: een bare repository plus een SSH (secure shell) account vormt al een werkende server op de kleinste machine die u kunt huren. Alles daarboven is een webapplicatie die u naast de repository draait, en elke stap omhoog kost geheugen waarover een kleine VPS mogelijk niet beschikt.
Er zijn vier niveaus. Een bare repository via SSH, waarbij niets luistert dat niet al actief was. cgit, een snelle read-only webinterface zonder database. Forgejo of Gitea, een volledige forge met accounts, issues en pull requests die enkele honderden megabytes verbruikt. GitLab, dat een server vereist die vele malen groter is dan de andere opties.
Bepaal uw keuze op basis van het werk dat u moet verrichten en controleer vervolgens het geheugengebruik tegenover het abonnement waarvoor u betaalt.
Hoeveel RAM elke optie werkelijk nodig heeft
Slechts twee van deze projecten publiceren een hardware-specificatie. Beschouw een gepubliceerd getal als een ondergrens in plaats van een garantie, en meet uw eigen instantie zodra deze draait met systemd-cgtop of ps -o rss= -C forgejo.
The data behind this chart
[
{
"label": "Gitea, small team",
"ram_gb": 1
},
{
"label": "GitLab, memory constrained",
"ram_gb": 8
},
{
"label": "GitLab, single node baseline",
"ram_gb": 16
}
]Gitea documenteert 1 GB RAM met 2 CPU-cores als doorgaans voldoende voor kleine teams en projecten, en noemt een Raspberry Pi 3 als toereikend voor kleine workloads. GitLab documenteert 16 GB als de basislijn voor een installatie op één node, en 8 GB als de ondergrens voor wat de eigen pagina een geheugenbeperkte omgeving noemt. Forgejo publiceert helemaal geen hardware-eisen. Het is een fork van Gitea en gedraagt zich als zodanig, dus het Gitea-cijfer is de meest nauwkeurige gepubliceerde richtlijn die u heeft.
Wat dit betekent op een 1 GB VPS: kale repositories en cgit passen met ruimte over, omdat geen van beide een resident service draait. Forgejo of Gitea zullen opstarten en een klein team bedienen op SQLite, maar u bevindt zich op de gedocumenteerde ondergrens, dus laat PostgreSQL en de CI (continuous integration) runner van die machine af. Als de webinterface zonder foutmelding verdwijnt, voer dan sudo dmesg -T | grep -i oom uit en zoek naar een regel zoals Out of memory: Killed process 1181 (forgejo); dit betekent dat de out of memory killer van de kernel het proces heeft beëindigd. GitLab op een 1 GB machine is geen kwestie van finetuning. Het zal niet draaien.
Tier 0: een bare repository via SSH
Git heeft geen netwerk-daemon die u moet starten. git push via SSH voert git-receive-pack uit op de externe machine als een gewoon Unix-proces. Elk account dat u met een sleutel kunt bereiken, fungeert daarom al als een Git-remote. Maak één account aan voor de repositories en bewaar de repositories buiten de home-directory van dit account. Op Ubuntu 24.04 krijgt een nieuwe home-directory namelijk de modus 0750, waardoor een later toegevoegde web-view de inhoud niet kan lezen.
sudo adduser --system --shell /bin/bash --gecos 'Git Version Control' \
--group --disabled-password --home /home/git git
sudo install -d -m 0755 -o git -g git /srv/git
sudo -u git git init --bare /srv/git/project.git--bare maakt een repository aan zonder werkmap, wat de standaard is voor een server. Pushen naar een repository die wel een werkmap heeft, wordt geweigerd met refusing to update checked out branch: refs/heads/main; dit is de meest gemaakte fout op dit niveau.
Geef het account nu een sleutel en kloon de repository.
sudo -u git install -d -m 700 /home/git/.ssh
sudo -u git tee -a /home/git/.ssh/authorized_keys <<'EOF'
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIexamplekeyhere alice@laptop
EOF
sudo -u git chmod 600 /home/git/.ssh/authorized_keysgit remote add origin git@vps.example.com:/srv/git/project.git
git push -u origin mainEen geslaagde eerste push eindigt met * [new branch] main -> main. Een push die eindigt met git@vps.example.com: Permission denied (publickey) is nooit geauthenticeerd; controleer in dat geval het serverlogboek met sudo journalctl -u ssh -n 20. Een regel met de tekst Authentication refused: bad ownership or modes for file /home/git/.ssh/authorized_keys betekent dat de bestandsrechten onjuist zijn, omdat sshd een sleutelbestand negeert dat door andere gebruikers kan worden gewijzigd.
Ontzeg het account vervolgens de toegang tot de shell.
command -v git-shell | sudo tee -a /etc/shells
sudo chsh -s "$(command -v git-shell)" gitgit-shell accepteert alleen de weinige commando's die Git via SSH verstuurt. Een interactieve login stopt daarom nu met een melding in plaats van een prompt:
fatal: Interactive git shell is not enabled.
hint: ~/git-shell-commands should exist and have read and execute access.Dat is de volledige server. Er is geen database en geen webproces dat moet worden bijgewerkt. U levert hiermee alle functies van een forge in: er is geen browserinterface, geen issue tracker, geen pull requests en geen rechtenbeheer per gebruiker. Elke sleutel in dat bestand heeft lees- en schrijfrechten voor elke repository die eigendom is van de gebruiker git.
Tier 1: cgit biedt een webweergave zonder database
cgit is een CGI (common gateway interface) programma geschreven in C. De webserver voert het programma per verzoek uit, leest de repositories direct vanaf de schijf en slaat zelf geen status op. Ubuntu 24.04 bevat dit programma in de universe-component.
sudo apt update
sudo apt install -y cgit fcgiwrap nginx
sudo install -d -o www-data -g www-data /var/cache/cgitWijs het programma naar de repository-map in /etc/cgitrc:
root-title=Git on example.com
css=/cgit.css
logo=/cgit.png
cache-size=1000
cache-root=/var/cache/cgit
snapshots=tar.gz zip
scan-path=/srv/gitscan-path doorloopt die map en somt elke gevonden repository op, waardoor een nieuwe bare repo zonder extra configuratie verschijnt. cache-size is het aantal gecachte pagina's; caching blijft uitgeschakeld zolang dit op nul staat. Lees wat uw pakketbeheerder al in /etc/cgitrc heeft geplaatst voordat u regels toevoegt, aangezien het Debian- en Ubuntu-pakket eigen standaardinstellingen bevat.
Elk item toont de eerste regel van het bestand description van de repository, waardoor een nieuwe bare repo zichzelf vermeldt als Unnamed repository; edit this file 'description' to name the repository.. Corrigeer dit per repository:
echo 'Project X, internal tooling' | sudo -u git tee /srv/git/project.git/descriptionHet nginx-sitebestand en hoe u dit controleert
server {
listen 80;
server_name git.example.com;
root /usr/share/cgit;
try_files $uri @cgit;
location @cgit {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /usr/lib/cgit/cgit.cgi;
fastcgi_param PATH_INFO $uri;
fastcgi_param QUERY_STRING $args;
fastcgi_param HTTP_HOST $server_name;
fastcgi_pass unix:/run/fcgiwrap.socket;
}
}sudo systemctl enable --now fcgiwrap.socket
sudo nginx -t && sudo systemctl reload nginx
systemctl show fcgiwrap.socket -p Listenroot /usr/share/cgit serveert cgit.css en cgit.png als platte bestanden, en try_files stuurt al het overige verkeer door naar de CGI op /usr/lib/cgit/cgit.cgi. Een 502-foutpagina, met connect() to unix:/run/fcgiwrap.socket failed (2: No such file or directory) in /var/log/nginx/error.log, betekent dat de socket-unit niet draait of op een ander pad luistert. De regel systemctl show toont het pad dat daadwerkelijk wordt gebruikt.
Er zijn twee beperkingen waar u rekening mee moet houden voordat u hierop voortbouwt. cgit is alleen-lezen en heeft geen inlogfunctie, dus alles onder scan-path is openbaar: houd een privé-repository uit die map of plaats HTTP basic authentication voor de gehele site. Daarnaast draait de CGI als de webservergebruiker; deze gebruiker moet dus de map /srv/git kunnen doorlopen en elke repository kunnen lezen. Een map die de gebruiker niet kan openen, wordt weergegeven als een lege index in plaats van een foutmelding.
Niveau 2: Forgejo of Gitea voor issues en pull requests
Forgejo en Gitea zijn gebaseerd op hetzelfde concept: één Go-binary die een web-gebaseerd platform biedt voor gebruikers, organisaties, issues, pull requests, releases, een pakketregister en een ingebouwd CI-systeem. De volledige installatie bestaat uit de binary en SQLite; daarom zijn ze geschikt voor hardware waar GitLab niet op draait. Het onderstaande Compose-bestand is afkomstig uit de documentatie van Forgejo, met de image-tag zoals vermeld in augustus 2026.
networks:
forgejo:
external: false
services:
server:
image: codeberg.org/forgejo/forgejo:16
container_name: forgejo
environment:
- USER_UID=1000
- USER_GID=1000
restart: always
networks:
- forgejo
volumes:
- ./forgejo:/data
- /etc/localtime:/etc/localtime:ro
ports:
- '3000:3000'
- '222:22'docker compose up -d
docker compose ps
curl -sI http://127.0.0.1:3000 | head -1De regel curl hoort een HTTP-statusregel te tonen. Voordat u de eerste configuratie voltooit, kan dit een redirect naar /install zijn, wat eveneens betekent dat de service actief is. Als de container in plaats daarvan afsluit, is de meest voorkomende oorzaak het eigenaarschap: de map ./forgejo moet toebehoren aan de UID (user id) in USER_UID, anders kan het proces niet naar de eigen datamap schrijven. Docker Compose op een VPS behandelt de bestandsstructuur en de regels voor volume-eigenaarschap volledig.
Twee antwoorden op de configuratiepagina bepalen of clone-URL's correct werken. De SSH-poort moet 222 zijn, omdat het Compose-bestand hostpoort 222 koppelt aan poort 22 van de container, en het domein moet de naam zijn die gebruikers daadwerkelijk invoeren. Als een van beide onjuist is, toont elke repositorypagina een clone-commando dat voor iedereen die het kopieert zal falen. Beide instellingen bevinden zich achteraf in de sectie [server] van app.ini, als SSH_PORT, SSH_DOMAIN en ROOT_URL.
Voor een publieke instantie publiceert u de webpoort alleen op het loopback-adres ('127.0.0.1:3000:3000') en plaatst u nginx ervoor voor TLS (transport layer security). Gitea wordt op dezelfde manier geïnstalleerd vanuit de gitea/gitea-image, of als een enkele binary met één systemd-unit en één app.ini; de huidige stabiele release is 1.27.1 per augustus 2026.
Blijf bij SQLite zolang dat mogelijk is. Dit houdt de instantie beperkt tot één proces en één bestand, en het overleeft een herstart zonder dat er een extra service beheerd hoeft te worden. PostgreSQL is de investering waard wanneer meerdere mensen tegelijkertijd schrijven, omdat SQLite schrijfacties serialiseert en langdurige CI-processen constant schrijven. Beide projecten kunnen een bestaande instantie later naar PostgreSQL migreren, dus u zit niet aan deze keuze vast.
Forgejo of Gitea: wat is het werkelijke verschil
De oorsprong is gedeeld. Gitea is in 2016 een fork geworden van Gogs. Eind 2022 ging de controle over het domein en het handelsmerk van Gitea over naar een bedrijf, Gitea Ltd, waarna verschillende beheerders samen met Codeberg Forgejo startten. Forgejo wordt uitgegeven door Codeberg e.V., een non-profitvereniging geregistreerd in Duitsland, en is in 2024 overgestapt van de MIT-licentie naar GPLv3 (GNU general public license version 3). Gitea blijft onder de MIT-licentie vallen en wordt ontwikkeld met commerciële ondersteuning.
In het dagelijks gebruik liggen de functies dicht bij elkaar. Het pad tussen beide is dat echter niet. Forgejo v10.0, van januari 2025, was de laatste release die rechtstreeks een Gitea-database kon inlezen, en alleen vanaf Gitea v1.22 of ouder. Gitea zit in augustus 2026 op versie 1.27.1, dus een huidige Gitea-instantie heeft geen ondersteunde methode voor een directe overstap naar Forgejo. Kies een platform voordat u het met data vult en beschouw een latere overstap als een export en een herimport.
Een korte regel voor de keuze. Als bestuur voor u van belang is, of als u wilt dat het project bij een non-profit blijft, gebruik dan Forgejo. Als u de voorkeur geeft aan een grotere installatiebasis en een commerciële ondersteuningsoptie, gebruik dan Gitea. Beide worden openlijk onderhouden en brengen regelmatig releases uit: Forgejo publiceert elke drie maanden een stabiele release en elk jaar een LTS-release (long term support), waarbij v16.0.2 de huidige versie is en v15.0.6 de LTS-versie in augustus 2026.
Tier 3: wat GitLab kost voordat het iets doet
GitLab CE is een andere klasse software. Eén instantie is een verzameling samenwerkende services: Puma voor de webapplicatie, Sidekiq voor achtergrondtaken, PostgreSQL, Redis, Gitaly voor repository-toegang en nginx aan de voorzijde. Het Omnibus-pakket installeert deze gezamenlijk, wat de installatie eenvoudig maakt en de minimale geheugenbehoefte hoog legt.
De vereistenpagina van GitLab documenteert 16 GB RAM en 8 vCPU als basislijn voor een installatie op één node, waarbij 8 GB wordt genoemd als ondergrens in een omgeving met beperkt geheugen. Dezelfde pagina adviseert om swap uit te schakelen, omdat swappen onder belasting de prestaties van de instantie ernstig verslechtert. Dit zijn de gepubliceerde cijfers per augustus 2026, en deze zijn in de loop der jaren gestegen; lees de pagina dus opnieuw voordat u een server dimensioneert.
U krijgt voor dat budget concrete zaken: een container registry, een package registry, fijnmazige rechten, compliance- en auditfuncties, en CI die op grote schaal is getest. Als niemand in uw team iets uit die lijst kan noemen dat zij dit kwartaal nodig hebben, betaalt u voor een grotere VPS in ruil voor niets.
Het SSH-toegangsmodel: één git-gebruiker en meerdere sleutels
Elke laag hier authenticeert op dezelfde manier. Er is één Unix-account genaamd git, en elke publieke sleutel wordt in de ~/.ssh/authorized_keys van dat account geplaatst. Authenticatie is de sleutel. Autorisatie wordt bepaald door de opties die u op dezelfde regel vóór de sleutel plaatst.
Een standaard sleutelregel geeft de houder alle rechten van dat account. Een geforceerd commando beperkt dit tot Git:
restrict,command="git-shell -c \"$SSH_ORIGINAL_COMMAND\"" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIexamplekeyhere alice@laptoprestrict, beschikbaar sinds OpenSSH 7.2, schakelt port forwarding, agent forwarding, X11 en PTY-allocatie (pseudo terminal) in één woord uit. command= vervangt wat de client heeft aangevraagd door het commando dat u opgeeft, en Git blijft werken omdat Git zijn verzoek verstuurt in $SSH_ORIGINAL_COMMAND.
Een forge schrijft dat bestand voor u, en dat is het werkelijke verschil tussen laag 0 en laag 2. Forgejo en Gitea herschrijven authorized_keys met één regel per geregistreerde sleutel, waarbij elke regel een geforceerd commando bevat dat de sleutel identificeert aan de hand van het database-ID:
command="/usr/local/bin/forgejo --config=/etc/forgejo/app.ini serv key-3",no-port-forwarding,no-x11-forwarding,no-agent-forwarding,no-pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIexamplekeyhere aliceDat geforceerde commando is de manier waarop één gedeeld Unix-account verandert in rechten per gebruiker: key-3 vertelt de forge welke gebruiker verbinding maakt, en deze controleert die gebruiker tegen de repository voordat er objecten worden verplaatst. Bewerk dat bestand niet handmatig op een door een forge beheerde server, omdat het wordt herschreven vanuit de database en uw regel dan verdwijnt. Deploy-sleutels maken gebruik van hetzelfde mechanisme: een deploy-sleutel is een gewone SSH-sleutel die is geregistreerd voor één specifieke repository, meestal alleen-lezen, waarbij de controle in de forge plaatsvindt in plaats van in sshd.
Twee gewoontes zijn belangrijker dan alle bovenstaande configuratie. Geef één sleutel uit per persoon of per machine, nooit een gedeelde sleutel, omdat het intrekken van een gedeelde sleutel betekent dat deze voor iedereen tegelijk moet worden vervangen. Verwijder sleutels op de dag dat iemand vertrekt, aangezien een oude sleutel in dat bestand een permanente login is die door niemand wordt gecontroleerd. Goed SSH-sleutelbeheer op een server behandelt sleuteltypes en wachtzinnen, en alles daarvan is hier ongewijzigd van toepassing. Als de server nieuw is, is de eerste tien minuten op een nieuwe VPS de juiste procedure voordat u er repositories op plaatst.
Kan ik GitHub Actions uitvoeren op mijn eigen Git-server?
U kunt workflows uitvoeren die zijn geschreven in de GitHub Actions-syntaxis. U kunt echter niet GitHub zelf draaien. Forgejo Actions is sinds Forgejo v1.21 standaard ingeschakeld en leest workflowbestanden uit .forgejo/workflows in elke repository. Gitea Actions werkt op dezelfde manier en leest .gitea/workflows. Beide vereisen een tweede programma, de runner, dat moet worden geïnstalleerd en geregistreerd bij uw instantie met een token uit de beheerdersinstellingen. Veel gepubliceerde actions werken ongewijzigd; alles wat de GitHub API aanroept of verwacht dat de infrastructuur door GitHub wordt gehost, werkt niet.
Houd rekening met twee gevolgen. De runner start een container voor elke taak, dus deze heeft een container-engine en een eigen geheugenbudget nodig. Daarom hoort deze niet thuis op dezelfde 1 GB-server als de forge. Daarnaast voert de runner alles uit wat in een workflowbestand staat, wat de documentatie van Forgejo expliciet vermeldt: de runner voert remote code execution uit. Geef de runner waar mogelijk een eigen host, of op zijn minst een eigen gebruiker zonder privileges en een registratietoken dat beperkt is tot één repository.
Als uw repositories op GitHub blijven staan en u alleen de rekenkracht op hardware wilt die u zelf beheert, dan is dat een andere configuratie met andere stappen: een self-hosted GitHub Actions runner koppelt aan een GitHub-repository en heeft dit alles niet nodig. Als u nog afweegt wat vertrek u kost, scheidt wat GitHub u daadwerkelijk biedt de Git-hosting van het netwerk eromheen.
Backups: repositories zijn slechts de helft van de status
Een bare repository is een directory, dus het kopiëren ervan kopieert alles wat erin staat. Een mirror clone vanaf een andere machine is een echte back-up en deze ververst zichzelf op de locatie:
git clone --mirror git@vps.example.com:/srv/git/project.git
cd project.git && git remote updateDit haalt elke ref en elk object op. Het haalt echter geen server-side hooks of het description-bestand op, dus bewaar ook een kopie op bestandsniveau van de directory als u hooks gebruikt.
Een forge bewaart issues, pull requests, gebruikers, keys en permissies in zijn database; een kopie van alleen de repositories gooit dit alles weg. Beide projecten leveren een dump-commando dat de database, de repositories, de configuratie en de bijlagen naar één archief schrijft:
sudo -u git forgejo dump -c /etc/forgejo/app.ini -f /var/backups/forgejo-dump.zipOnder Docker draait hetzelfde commando binnen de container, en het configuratiepad hangt af van de image, dus kijk goed voordat u typt:
docker compose exec server ls /data/gitea/conf
docker compose exec -u git server forgejo dump -c /data/gitea/conf/app.iniVoer het uit als de gebruiker die eigenaar is van de data en schrijf het archief naar een directory waar die gebruiker schrijfrechten heeft. Kopieer het archief vervolgens van de server af, want een back-up die alleen op de machine zelf bestaat, is geen back-up. Het herstellen is de stap die mensen vaak overslaan: pak nu een dump uit op een reservemachine, zodat u de procedure leert op een rustig moment in plaats van tijdens een storing.
Kiezen op basis van scenario
Eén persoon met een laptop en een VPS, waarbij browsen niet nodig is: gebruik bare repositories via SSH. Er draait geen extra service en er is niets om bij te werken.
Hetzelfde, maar u wilt code in een browser lezen en links daarnaar versturen: voeg cgit toe. Nog steeds geen database, nog steeds geen resident processen.
Een team dat elkaars code beoordeelt en issues bijhoudt: Forgejo of Gitea, op 2 GB RAM of meer. Verplaats de CI runner naar een tweede machine zodra de taken serieus worden.
Een organisatie die een container registry en audit trails nodig heeft, met 16 GB aan servergeheugen: GitLab. Begin hier niet aan onder dit budget.
Upgraden tussen de eerste drie niveaus is goedkoop, omdat de repositories in al deze gevallen gewone Git-mappen op de schijf zijn. Begin bij het laagste niveau dat aan uw eisen voldoet. Als u bepaalt wat er nog meer op dezelfde server past, plaatst de shortlist van wat de moeite waard is om zelf te hosten een Git-server naast de andere services die om dat RAM-geheugen strijden.
FAQ
Kan een 1 GB VPS Forgejo of Gitea draaien?
Ja, voor een klein team, op SQLite, mits er geen andere zware processen op de server draaien. De documentatie van Gitea geeft aan dat 1 GB RAM en 2 CPU-cores doorgaans volstaan voor kleine teams en projecten; Forgejo is een fork van Gitea met dezelfde vereisten. Voeg geen PostgreSQL of een CI-runner toe aan die machine. Als de service verdwijnt zonder foutmelding in het eigen logboek, voer dan sudo dmesg -T | grep -i oom uit: een regel die het beëindigde proces noemt, betekent dat de kernel out-of-memory killer het proces heeft beëindigd. De oplossing is dan een groter abonnement in plaats van een configuratie-instelling.
Wat is het verschil tussen Forgejo en Gitea?
Ze delen een gezamenlijke codebase en de meeste functies. Gitea is in 2016 geforkt van Gogs, en Forgejo is eind 2022 geforkt van Gitea nadat de controle over het Gitea-handelsmerk naar een bedrijf was overgegaan. Forgejo wordt uitgegeven door Codeberg e.V., een non-profit in Duitsland, onder de GPLv3-licentie; Gitea blijft onder de MIT-licentie met commerciële ondersteuning. Het praktische verschil zit in het migratiepad. Forgejo v10.0, van januari 2025, was de laatste release die een Gitea-database direct kon inlezen, en alleen vanaf Gitea v1.22 of ouder. Een huidige Gitea-instantie heeft daarom geen ondersteunde methode voor een directe overstap.
Kan ik GitHub Actions-workflows draaien op een zelfgehoste Git-server?
Forgejo Actions en Gitea Actions voeren beide workflows uit die zijn geschreven in de GitHub Actions YAML-syntaxis, gelezen vanuit .forgejo/workflows en .gitea/workflows. U installeert een apart runner-programma en registreert dit bij uw instantie. Veel gepubliceerde actions werken zonder aanpassingen, terwijl alles wat de GitHub API aanroept niet werkt. De runner voert willekeurige code uit uw repositories uit en start een container per job. Geef de runner daarom een eigen host, of op zijn minst een eigen gebruiker zonder privileges, en laat deze niet draaien op een 1 GB-server die al de Git-service host.
Hoe maak ik een back-up van een zelfgehoste Git-server?
Voor bare repositories kopieert git clone --mirror vanaf een andere machine elke ref en elk object, en git remote update binnen die mirror ververst deze. Voor Forgejo of Gitea vormen de repositories slechts een deel van de status, omdat issues, pull requests, gebruikers en sleutels in de database staan. Gebruik de ingebouwde dump-functie, sudo -u git forgejo dump -c /etc/forgejo/app.ini, of hetzelfde commando binnen de container bij een Docker-installatie. Kopieer het archief van de server af en herstel er eenmaal een op een reservemachine, zodat u weet dat de procedure werkt.