Gitea zelf hosten op een VPS met Docker Compose

10 min leestijd·Matthieu·ci-cdself-hostingdocker-composegiteapostgresqldockergit|

Zet een productieklare Gitea-instantie op met PostgreSQL, SSH-passthrough op poort 22, Gitea Actions CI/CD, Git LFS, GitHub-mirroring en geautomatiseerde back-ups. Alles op één VPS met Docker Compose.

Gitea is een lichtgewicht, zelf te hosten Git-service geschreven in Go. Het biedt pull requests, issue tracking, CI/CD, pakketregisters en Git LFS in één binair bestand dat in rust ongeveer 150 MB RAM gebruikt. Vergelijk dat met de 4 GB minimum van GitLab en je begrijpt waarom Gitea perfect op een VPS past.

Deze handleiding zet Gitea op met Docker Compose en PostgreSQL op een VPS. Je configureert SSH-passthrough zodat git clone git@jouw-server:user/repo.git werkt op poort 22, stelt Gitea Actions in met een gecontaineriseerde runner, activeert Git LFS, spiegelt repositories van GitHub, configureert webhooks en automatiseert back-ups.

Wat heb je nodig voordat je Gitea installeert?

Je hebt een VPS nodig met Debian 12 of Ubuntu 24.04 waarop Docker en Docker Compose v2 zijn geïnstalleerd, een domeinnaam die naar je server wijst, en een reverse proxy (Nginx of Caddy) met TLS geconfigureerd. Deze handleiding gaat ervan uit dat je de initiële serverbeveiliging hebt uitgevoerd: niet-root gebruiker met sudo, SSH-sleutelauthenticatie, firewall ingeschakeld.

Vereiste Minimum
OS Debian 12 / Ubuntu 24.04
RAM 1 GB (2 GB aanbevolen met CI-runner)
Docker 27.x+ met Compose v2
Domein A-record dat naar het VPS-IP wijst
Reverse proxy Nginx of Caddy met TLS

Hoe zet je Gitea op met Docker Compose en PostgreSQL?

Maak een projectmap aan, genereer secrets in een .env-bestand en definieer de Gitea- en PostgreSQL-services in docker-compose.yml. Het .env-bestand houdt inloggegevens buiten versiebeheer en compose-bestanden.

Projectmap aanmaken

sudo mkdir -p /opt/gitea
sudo chown $USER:$USER /opt/gitea
cd /opt/gitea

Secrets genereren

openssl rand -base64 32 > /dev/null  # test that openssl works
cat > .env << 'ENVFILE'
POSTGRES_USER=gitea
POSTGRES_PASSWORD=REPLACE_ME
POSTGRES_DB=gitea
GITEA_SECRET_KEY=REPLACE_ME
GITEA_INTERNAL_TOKEN=REPLACE_ME
GITEA_LFS_JWT_SECRET=REPLACE_ME
ENVFILE

Vervang nu elke REPLACE_ME door een echt secret:

sed -i "s/^POSTGRES_PASSWORD=.*/POSTGRES_PASSWORD=$(openssl rand -base64 32)/" .env
sed -i "s/^GITEA_SECRET_KEY=.*/GITEA_SECRET_KEY=$(openssl rand -base64 32)/" .env
sed -i "s/^GITEA_INTERNAL_TOKEN=.*/GITEA_INTERNAL_TOKEN=$(openssl rand -base64 32)/" .env
sed -i "s/^GITEA_LFS_JWT_SECRET=.*/GITEA_LFS_JWT_SECRET=$(openssl rand -base64 32)/" .env
chmod 600 .env

Docker Compose-bestand

# /opt/gitea/docker-compose.yml
services:
  gitea:
    image: docker.gitea.com/gitea:1.25.5
    container_name: gitea
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - GITEA__database__DB_TYPE=postgres
      - GITEA__database__HOST=db:5432
      - GITEA__database__NAME=${POSTGRES_DB}
      - GITEA__database__USER=${POSTGRES_USER}
      - GITEA__database__PASSWD=${POSTGRES_PASSWORD}
      - GITEA__server__DOMAIN=git.example.com
      - GITEA__server__ROOT_URL=https://git.example.com/
      - GITEA__server__SSH_DOMAIN=git.example.com
      - GITEA__server__SSH_PORT=22
      - GITEA__server__LFS_START_SERVER=true
      - GITEA__server__LFS_JWT_SECRET=${GITEA_LFS_JWT_SECRET}
      - GITEA__service__DISABLE_REGISTRATION=true
      - GITEA__service__REQUIRE_SIGNIN_VIEW=false
      - GITEA__security__SECRET_KEY=${GITEA_SECRET_KEY}
      - GITEA__security__INTERNAL_TOKEN=${GITEA_INTERNAL_TOKEN}
      - GITEA__actions__ENABLED=true
    restart: always
    volumes:
      - gitea-data:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "127.0.0.1:3000:3000"
    depends_on:
      db:
        condition: service_healthy
    networks:
      - gitea

  db:
    image: docker.io/library/postgres:17
    container_name: gitea-db
    environment:
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_DB=${POSTGRES_DB}
    restart: always
    volumes:
      - postgres-data:/var/lib/postgresql/data
    networks:
      - gitea
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 10s
      timeout: 5s
      retries: 5

networks:
  gitea:
    external: false

volumes:
  gitea-data:
  postgres-data:

Vervang git.example.com door je werkelijke domein. Belangrijke keuzes:

  • PostgreSQL 17 in plaats van het verouderde 14 dat de meeste handleidingen nog aanbevelen
  • Benoemde volumes (gitea-data, postgres-data) in plaats van bind mounts voor schoner beheer
  • Health check op PostgreSQL zodat Gitea wacht tot de database gereed is
  • DISABLE_REGISTRATION=true omdat open registratie op een publieke instantie misbruik uitlokt
  • ACTIONS__ENABLED=true om Gitea Actions direct te activeren
  • Poort 3000 gebonden aan localhost (127.0.0.1:3000:3000) zodat deze alleen bereikbaar is via de reverse proxy, niet rechtstreeks vanaf internet
  • Geen SSH-poortmapping op de container. SSH wordt afgehandeld via host-passthrough (volgende sectie)

Stack starten

docker compose up -d
[+] Running 3/3
 ✔ Network gitea_gitea     Created
 ✔ Container gitea-db      Healthy
 ✔ Container gitea         Started
docker compose ps
NAME        IMAGE                           STATUS                   PORTS
gitea       docker.gitea.com/gitea:1.25.5   Up 2 minutes             127.0.0.1:3000->3000/tcp
gitea-db    postgres:17                     Up 2 minutes (healthy)   5432/tcp

Reverse proxy-configuratie

Voeg Gitea toe aan je bestaande Nginx-configuratie:

server {
    listen 443 ssl http2;
    server_name git.example.com;

    ssl_certificate /etc/letsencrypt/live/git.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/git.example.com/privkey.pem;

    server_tokens off;

    client_max_body_size 512M;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

client_max_body_size 512M staat grote pushes toe, vooral nuttig bij actief Git LFS. server_tokens off verbergt de Nginx-versie in de responseheaders, omdat versie-informatie aanvallers helpt bekende kwetsbaarheden uit te buiten.

sudo nginx -t && sudo systemctl reload nginx

Beheerder aanmaken

docker exec -it gitea gitea admin user create \
  --username admin \
  --password "$(openssl rand -base64 16)" \
  --email admin@example.com \
  --admin \
  --must-change-password
New user 'admin' has been successfully created!

Bewaar het gegenereerde wachtwoord op een veilige plek (een wachtwoordmanager, geen plakbriefje). De --must-change-password-vlag forceert een wachtwoordwijziging bij de eerste login. Schakel na het inloggen tweefactorauthenticatie in via Settings > Security > Two-Factor Authentication.

Hoe stel je SSH-passthrough in voor Gitea in Docker?

Maak een git-gebruiker aan op de host met dezelfde UID als in de container. Voeg een AuthorizedKeysCommand-blok toe aan /etc/ssh/sshd_config dat docker exec gitea /usr/local/bin/gitea keys aanroept. Dit routeert SSH-gitoperaties van poort 22 op de host rechtstreeks naar de container, zonder een tweede SSH-poort bloot te stellen.

Git-gebruiker aanmaken op de host

De gebruiker heeft UID 1000 nodig om overeen te komen met de interne gebruiker van de container:

sudo adduser --system --shell /bin/bash --group --disabled-password --home /home/git --uid 1000 git

Als UID 1000 al in gebruik is door je reguliere gebruiker, wijzig dan USER_UID/USER_GID in het compose-bestand naar een beschikbare UID, of pas de --uid-vlag hier aan.

Shell-wrapper aanmaken

De shell van de git-gebruiker moet commando's doorsturen naar de container:

sudo tee /usr/local/bin/gitea-shell > /dev/null << 'WRAPPER'
#!/bin/sh
/usr/bin/docker exec -i --env SSH_ORIGINAL_COMMAND="$SSH_ORIGINAL_COMMAND" gitea sh "$@"
WRAPPER
sudo chmod 755 /usr/local/bin/gitea-shell
sudo usermod -s /usr/local/bin/gitea-shell git
ls -la /usr/local/bin/gitea-shell
-rwxr-xr-x 1 root root 99 Mar 20 10:00 /usr/local/bin/gitea-shell

Git-gebruiker toevoegen aan de docker-groep

sudo usermod -aG docker git

Dit geeft de git-gebruiker toestemming om docker exec uit te voeren. Op een dedicated Gitea-server is dit acceptabel. Op een gedeelde host kun je beter sudo-regels gebruiken die beperkt zijn tot het specifieke docker exec-commando.

sshd configureren

Voeg dit blok toe aan het einde van /etc/ssh/sshd_config:

# Gitea SSH passthrough
Match User git
  AuthorizedKeysCommandUser git
  AuthorizedKeysCommand /usr/bin/docker exec -i gitea /usr/local/bin/gitea keys -c /etc/gitea/app.ini -e git -u %u -t %t -k %k

Het AuthorizedKeysCommand vraagt de Gitea-container of de publieke sleutel die de SSH-client presenteert bij een geregistreerde Gitea-gebruiker hoort. Als deze overeenkomt, verleent SSH toegang. Het Match User git-blok beperkt dit tot alleen de git-gebruiker en laat je reguliere SSH-toegang onaangetast.

sudo sshd -t

Geen uitvoer betekent dat de configuratie geldig is. Als je fouten ziet, controleer het Match-blok op typefouten.

sudo systemctl restart sshd

SSH-toegang testen

Voeg je publieke SSH-sleutel toe aan je Gitea-account via de webinterface (Settings > SSH/GPG Keys). Test dan vanaf je lokale machine:

ssh -T git@git.example.com
Hi there, admin! You've successfully authenticated with the key named "my-laptop", but Gitea does not provide shell access.

Je kunt nu klonen, pushen en pullen via SSH op poort 22:

git clone git@git.example.com:admin/my-repo.git

Hoe activeer en configureer je Gitea Actions voor CI/CD?

Gitea Actions is een ingebouwd CI/CD-systeem met een syntaxis die compatibel is met GitHub Actions. Je activeert het met een omgevingsvariabele (al ingesteld in ons compose-bestand), implementeert een runner als Docker Compose-service en schrijft workflow-YAML-bestanden in je repositories.

Hoe registreer je een act_runner met Docker Compose?

Genereer eerst een runner-registratietoken vanuit het Gitea-beheerpaneel:

docker exec -it gitea gitea actions generate-runner-token
NxxxxxxxxxxxxxxxxxxxxxxxN

Kopieer dit token. Voeg het toe aan je .env-bestand:

echo "GITEA_RUNNER_TOKEN=YOUR_TOKEN_HERE" >> /opt/gitea/.env
chmod 600 /opt/gitea/.env

Voeg nu de runner-service toe aan je docker-compose.yml:

  runner:
    image: docker.io/gitea/act_runner:0.3.0
    container_name: gitea-runner
    environment:
      - GITEA_INSTANCE_URL=http://gitea:3000
      - GITEA_RUNNER_REGISTRATION_TOKEN=${GITEA_RUNNER_TOKEN}
      - GITEA_RUNNER_NAME=vps-runner
    volumes:
      - runner-data:/data
      - /var/run/docker.sock:/var/run/docker.sock
    depends_on:
      - gitea
    restart: always
    networks:
      - gitea

Voeg runner-data: toe aan de volumes:-sectie onderaan het bestand. Start vervolgens de runner:

docker compose up -d runner
docker compose logs runner --tail 20
level=info msg="Starting runner daemon"
level=info msg="Runner registered successfully"

De runner mount de Docker-socket (/var/run/docker.sock) om containers te kunnen starten voor elke job. Dit is standaardpraktijk voor CI-runners, maar betekent dat jobs toegang hebben tot de Docker-daemon van de host. Voor geïsoleerde omgevingen kun je de runner met Docker-in-Docker (DinD) draaien.

Omgevingsvariabele Doel
GITEA_INSTANCE_URL Interne URL waarmee de runner Gitea bereikt (gebruik de servicenaam, niet het publieke domein)
GITEA_RUNNER_REGISTRATION_TOKEN Eenmalig token van gitea actions generate-runner-token
GITEA_RUNNER_NAME Weergavenaam in het Gitea-beheerpaneel

Hoe ziet een Gitea Actions-workflow eruit?

Gitea Actions gebruikt dezelfde YAML-syntaxis als GitHub Actions, met enkele verschillen. Maak .gitea/workflows/build.yml aan in je repository:

name: Build and Test

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Go
        uses: actions/setup-go@v5
        with:
          go-version: '1.23'

      - name: Build
        run: go build -v ./...

      - name: Test
        run: go test -v ./...

  deploy:
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4

      - name: Deploy via SSH
        env:
          DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
        run: |
          mkdir -p ~/.ssh
          echo "$DEPLOY_KEY" > ~/.ssh/id_ed25519
          chmod 600 ~/.ssh/id_ed25519
          ssh -o StrictHostKeyChecking=accept-new user@production "cd /app && git pull && systemctl restart myapp"

Sla het DEPLOY_KEY-secret op in je repository-instellingen onder Settings > Actions > Secrets.

Functie Gitea Actions GitHub Actions
Workflow-directory .gitea/workflows/ .github/workflows/
uses: actions/* Werkt (standaard opgehaald van GitHub) Natief
Containerservices Ondersteund Ondersteund
Matrix-builds Ondersteund Ondersteund
Herbruikbare workflows Ondersteund sinds Gitea 1.24 Ondersteund
Marketplace-actions De meeste werken, sommige hebben aanpassing nodig Natief

Hoe activeer je Git LFS in Gitea?

Git Large File Storage laat je binaire bestanden (afbeeldingen, modellen, datasets) tracken zonder je repository op te blazen. Gitea heeft ingebouwde LFS-ondersteuning. We hebben het al geactiveerd met LFS_START_SERVER=true in het compose-bestand. LFS-data wordt standaard opgeslagen in het gitea-data-volume.

Om het opslagpad expliciet te configureren of limieten te verhogen, bewerk de Gitea-configuratie:

docker exec -i gitea sh -c 'cat >> /data/gitea/conf/app.ini' << 'EOF'

[lfs]
PATH = /data/git/lfs
EOF

Herstart Gitea om toe te passen:

docker compose restart gitea

Aan de clientkant, installeer git-lfs en track bestandstypen:

git lfs install
git lfs track "*.bin" "*.h5" "*.onnx"
git add .gitattributes
git commit -m "Track model files with LFS"
git push

LFS-bestanden worden op de server opgeslagen op het geconfigureerde PATH in de container. Voor grote deployments kun je S3-compatibele opslag configureren in app.ini onder de [lfs]-sectie.

Hoe spiegel je GitHub-repositories naar Gitea?

Pull-mirroring maakt een alleen-lezen kopie van een GitHub-repository op je Gitea-instantie. De synchronisatie verloopt automatisch volgens een instelbaar schema. Handig voor back-ups, als lokale cache achter je CI-runner, of om de afhankelijkheid van GitHub te verminderen.

In de Gitea-webinterface:

  1. Klik op + > New Migration
  2. Selecteer GitHub als bron
  3. Voer de repository-URL in (bijv. https://github.com/owner/repo.git)
  4. Voor privérepo's vul je je GitHub-gebruikersnaam in en een personal access token als wachtwoord
  5. Vink This repository will be a mirror aan
  6. Stel het spiegelinterval in (standaard: 8 uur)
  7. Klik op Migrate Repository

De spiegel synchroniseert branches, tags en releases. Issues, pull requests en wiki's kunnen ook worden gemigreerd tijdens de initiële import, maar worden niet continu gesynchroniseerd.

Om te spiegelen via de API:

curl -X POST "https://git.example.com/api/v1/repos/migrate" \
  -H "Authorization: token YOUR_GITEA_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "clone_addr": "https://github.com/owner/repo.git",
    "mirror": true,
    "mirror_interval": "8h",
    "repo_name": "repo-mirror",
    "repo_owner": "admin",
    "service": "github"
  }'

Hoe configureer je webhooks voor deployment?

Webhooks sturen HTTP POST-verzoeken naar een URL wanneer er gebeurtenissen plaatsvinden in een repository. Ze zijn een eenvoudige manier om deployments, notificaties of externe CI-systemen te triggeren.

Ga in je repository naar Settings > Webhooks > Add Webhook > Gitea:

  • Target URL: https://deploy.example.com/hooks/gitea
  • HTTP Method: POST
  • Content Type: application/json
  • Secret: genereer met openssl rand -hex 32
  • Trigger events: Push events (of pas aan)

Aan de ontvangstkant moet je deploymentscript de webhook-handtekening verifiëren:

# The webhook sends a X-Gitea-Signature header
# Verify it with the shared secret before acting on the payload
EXPECTED=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET" | awk '{print $2}')
if [ "$SIGNATURE" != "$EXPECTED" ]; then
  echo "Invalid signature"
  exit 1
fi

Een minimale webhook-ontvanger met een lichtgewicht tool zoals webhook:

[
  {
    "id": "deploy",
    "execute-command": "/opt/deploy.sh",
    "command-working-directory": "/opt/app",
    "trigger-rule": {
      "match": {
        "type": "payload-hmac-sha256",
        "secret": "your-webhook-secret",
        "parameter": {
          "source": "header",
          "name": "X-Gitea-Signature"
        }
      }
    }
  }
]

Hoe maak je een back-up van een Gitea-instantie?

Gitea levert een gitea dump-commando dat repositories, de database, configuratie en LFS-objecten verpakt in één zip-bestand. Voor PostgreSQL wil je ook een aparte pg_dump voor point-in-time-recovery.

Handmatige back-up

docker exec -it gitea /usr/local/bin/gitea dump -c /data/gitea/conf/app.ini --file /data/gitea-backup.zip
docker cp gitea:/data/gitea-backup.zip /opt/gitea/backups/

De dump bevat:

Inhoud In dump opgenomen
Git-repositories Ja
Database (SQLite of dump) Ja
Configuratie (app.ini) Ja
LFS-objecten Ja
Bijlagen, avatars Ja
Pakketten Nee (apart back-uppen)

Voor PostgreSQL voer je ook uit:

docker exec gitea-db pg_dump -U gitea gitea | gzip > /opt/gitea/backups/gitea-db-$(date +%Y%m%d).sql.gz

Geautomatiseerde back-up met cron

sudo mkdir -p /opt/gitea/backups
sudo chown root:root /opt/gitea/backups
sudo chmod 700 /opt/gitea/backups

Maak het back-upscript aan:

sudo tee /opt/gitea/backup.sh > /dev/null << 'BACKUP'
#!/bin/bash
set -euo pipefail

BACKUP_DIR="/opt/gitea/backups"
DATE=$(date +%Y%m%d-%H%M)

# Gitea dump
docker exec gitea /usr/local/bin/gitea dump -c /data/gitea/conf/app.ini --file /data/gitea-backup.zip --quiet
docker cp gitea:/data/gitea-backup.zip "$BACKUP_DIR/gitea-dump-$DATE.zip"
docker exec gitea rm /data/gitea-backup.zip

# PostgreSQL dump
docker exec gitea-db pg_dump -U gitea gitea | gzip > "$BACKUP_DIR/gitea-db-$DATE.sql.gz"

# Keep last 7 daily backups
find "$BACKUP_DIR" -name "gitea-*" -mtime +7 -delete

echo "Backup completed: $DATE"
BACKUP
sudo chmod 700 /opt/gitea/backup.sh
ls -la /opt/gitea/backup.sh
-rwx------ 1 root root 523 Mar 20 10:00 /opt/gitea/backup.sh

Plan het dagelijks om 3 uur 's nachts:

echo "0 3 * * * root /opt/gitea/backup.sh >> /var/log/gitea-backup.log 2>&1" | sudo tee /etc/cron.d/gitea-backup
sudo chmod 644 /etc/cron.d/gitea-backup

Test het script eenmaal handmatig:

sudo /opt/gitea/backup.sh
Backup completed: 20260320-1030
ls -lh /opt/gitea/backups/
-rw-r--r-- 1 root root 2.3M Mar 20 10:30 gitea-dump-20260320-1030.zip
-rw-r--r-- 1 root root  48K Mar 20 10:30 gitea-db-20260320-1030.sql.gz

Kopieer back-ups van de server af. Een lokale back-up die met de schijf sterft is geen back-up.

Hoe werk je Gitea veilig bij?

Pull de nieuwe image, maak de container opnieuw aan en laat Gitea de databasemigraties automatisch afhandelen. Pin imageversies zodat updates bewust zijn, niet per ongeluk.

cd /opt/gitea

# Back up first
sudo /opt/gitea/backup.sh

# Update the image tag in docker-compose.yml, then:
docker compose pull gitea
docker compose up -d gitea
docker compose logs gitea --tail 30

Let op migratieberichten:

2026/03/20 10:35:00 ...les/migration.go:67:Migrate() [I] Migration completed

Na bevestiging dat Gitea schoon opstart, werk de runner bij als er een nieuwe versie beschikbaar is:

docker compose pull runner
docker compose up -d runner

Wat is het verschil tussen Gitea en Forgejo?

Forgejo splitstte zich eind 2022 af van Gitea, nadat een commercieel bedrijf (Gitea Ltd.) de controle over het Gitea-project overnam. Forgejo wordt bestuurd door Codeberg e.V., een Duitse stichting zonder winstoogmerk. Begin 2026 is Forgejo een hard fork met uiteenlopende codebases. Beide werken met een vergelijkbare Docker-setup, maar migratie tussen de twee is niet meer naadloos.

Gitea Forgejo
Bestuur Gitea Ltd. (commercieel) Codeberg e.V. (non-profit)
Licentie MIT GPL-3.0+ (sinds Forgejo v9.0)
Docker-image docker.gitea.com/gitea codeberg.org/forgejo/forgejo
Actions-ondersteuning Ja (act_runner) Ja (compatibele runner)
API-compatibiliteit GitHub-compatibel GitHub-compatibel
Unieke functies Gitea Enterprise, MCP-server Federatie (ForgeFed), moderatietools

Als je een door de gemeenschap bestuurd project wilt met een copyleft-licentie, kies Forgejo. Als je het oorspronkelijke project wilt met commerciële ondersteuning, kies Gitea. De Docker Compose-setup uit deze handleiding werkt voor beide met minimale aanpassingen (wissel de image, pas de paden aan).

Als je met Gitea begint en later wilt overstappen: exporteer je data met gitea dump, installeer Forgejo en importeer. Test grondig. De codebases zijn genoeg uiteengelopen dat sommige databaseschema's verschillen.

Hoeveel RAM en CPU heeft Gitea nodig?

Een Gitea-instantie met PostgreSQL gebruikt in rust ongeveer 150-250 MB RAM. Bij actief gebruik met 5-10 gebruikers en CI-runners, reken op 300-500 MB totaal. Dat is ongeveer 10 keer lichter dan een GitLab-instantie, die minimaal 4 GB nodig heeft.

Deze cijfers komen van een draaiende Gitea-instantie op een Virtua Cloud VPS (4 vCPU, 8 GB RAM):

docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"
NAME            CPU %     MEM USAGE / LIMIT
gitea           0.15%     148.2MiB / 7.77GiB
gitea-db        0.08%     45.3MiB / 7.77GiB
gitea-runner    0.02%     32.1MiB / 7.77GiB
Scenario RAM (volledige stack) CPU
Rust, weinig repo's ~230 MB < 1%
Actief, 5-10 gebruikers ~400 MB 2-5%
CI-build draait ~600 MB (pieken tijdens builds) 20-50% per job
GitLab-equivalent 4.000+ MB 10%+ in rust

Gitea draait comfortabel op een 2 GB VPS. Met CI-runners geeft 4 GB je ruimte voor gelijktijdige builds.

Probleemoplossing

SSH-verbinding geweigerd: Controleer of de git-gebruiker bestaat, of sshd_config het Match-blok bevat en of sshd is herstart. Bekijk de logs:

journalctl -u sshd -f

Runner pikt geen jobs op: Bevestig dat de runner is geregistreerd in het beheerpaneel (Site Administration > Actions > Runners). Controleer de runner-logs:

docker compose logs runner --tail 50

Databaseverbindingsfouten bij opstarten: De health check zou dit moeten voorkomen, maar als Gitea start voordat PostgreSQL gereed is:

docker compose restart gitea

LFS-push mislukt met 413: Verhoog client_max_body_size in je Nginx-configuratie. 512M is meestal genoeg, maar pas aan voor je grootste bestanden.

Gitea-logs:

docker compose logs gitea --tail 100

Of volg live:

docker compose logs gitea -f

Copyright 2026 Virtua.Cloud. Alle rechten voorbehouden. Deze inhoud is een origineel werk van het Virtua.Cloud-team. Reproductie, herpublicatie of herdistributie zonder schriftelijke toestemming is verboden.

Klaar om het zelf te proberen?

Deploy uw eigen server in seconden. Linux, Windows of FreeBSD.

Bekijk VPS-aanbod