Self-hosting di Gitea su un VPS con Docker Compose
Distribuisci un'istanza Gitea pronta per la produzione con PostgreSQL, passthrough SSH sulla porta 22, CI/CD con Gitea Actions, Git LFS, mirroring da GitHub e backup automatizzati. Tutto su un singolo VPS con Docker Compose.
Gitea è un servizio Git self-hosted, leggero e scritto in Go. Offre pull request, issue tracking, CI/CD, registri di pacchetti e Git LFS in un singolo binario che a riposo occupa circa 150 MB di RAM. Confrontalo con i 4 GB minimi di GitLab e capirai perché Gitea si adatta perfettamente a un VPS.
Questa guida distribuisce Gitea con Docker Compose e PostgreSQL su un VPS. Configurerai il passthrough SSH in modo che git clone git@tuo-server:user/repo.git funzioni sulla porta 22, configurerai Gitea Actions con un runner containerizzato, abiliterai Git LFS, farai il mirroring di repository da GitHub, configurerai i webhook e automatizzerai i backup.
Cosa serve prima di installare Gitea?
Serve un VPS con Debian 12 o Ubuntu 24.04 con Docker e Docker Compose v2 installati, un nome di dominio che punta al tuo server e un reverse proxy (Nginx o Caddy) con TLS configurato. Questa guida presuppone che tu abbia completato l'hardening iniziale del server: utente non-root con sudo, autenticazione con chiave SSH, firewall attivo.
| Prerequisito | Minimo |
|---|---|
| OS | Debian 12 / Ubuntu 24.04 |
| RAM | 1 GB (2 GB consigliati con runner CI) |
| Docker | 27.x+ con Compose v2 |
| Dominio | Record A che punta all'IP del VPS |
| Reverse proxy | Nginx o Caddy con TLS |
Come distribuire Gitea con Docker Compose e PostgreSQL?
Crea una directory di progetto, genera i secret in un file .env e definisci i servizi Gitea e PostgreSQL in docker-compose.yml. Il file .env tiene le credenziali fuori dal controllo di versione e dai file compose.
Creare la directory del progetto
sudo mkdir -p /opt/gitea
sudo chown $USER:$USER /opt/gitea
cd /opt/gitea
Generare i secret
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
Ora sostituisci ogni REPLACE_ME con un vero 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
File Docker Compose
# /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:
Sostituisci git.example.com con il tuo dominio reale. Decisioni chiave:
- PostgreSQL 17 invece del 14 obsoleto che la maggior parte delle guide raccomanda ancora
- Volumi nominati (
gitea-data,postgres-data) invece di bind mount per una gestione più pulita - Health check su PostgreSQL per far attendere Gitea fino a quando il database è pronto
DISABLE_REGISTRATION=trueperché la registrazione aperta su un'istanza pubblica invita abusiACTIONS__ENABLED=trueper attivare Gitea Actions fin dall'inizio- Porta 3000 vincolata a localhost (
127.0.0.1:3000:3000) in modo che sia raggiungibile solo attraverso il reverse proxy, non direttamente da internet - Nessun mapping della porta SSH sul container. L'SSH sarà gestito tramite passthrough sull'host (sezione successiva)
Avviare lo stack
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
Configurazione del reverse proxy
Aggiungi Gitea alla tua configurazione Nginx esistente:
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 consente push di grandi dimensioni, particolarmente utile con Git LFS attivo. server_tokens off nasconde la versione di Nginx negli header di risposta, perché la divulgazione della versione aiuta gli attaccanti a sfruttare vulnerabilità note.
sudo nginx -t && sudo systemctl reload nginx
Creare l'utente amministratore
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!
Salva la password generata in un posto sicuro (un password manager, non un post-it). Il flag --must-change-password forza il cambio password al primo accesso. Una volta effettuato il login, abilita l'autenticazione a due fattori in Settings > Security > Two-Factor Authentication.
Come configurare il passthrough SSH per Gitea in Docker?
Crea un utente git sull'host con lo stesso UID del container. Aggiungi un blocco AuthorizedKeysCommand in /etc/ssh/sshd_config che chiama docker exec gitea /usr/local/bin/gitea keys. Questo instrada le operazioni SSH git dalla porta 22 dell'host direttamente nel container, senza esporre una seconda porta SSH.
Creare l'utente git sull'host
L'utente deve avere UID 1000 per corrispondere all'utente interno del container:
sudo adduser --system --shell /bin/bash --group --disabled-password --home /home/git --uid 1000 git
Se l'UID 1000 è già occupato dal tuo utente abituale, modifica USER_UID/USER_GID nel file compose per usare un UID disponibile, oppure adatta il flag --uid qui.
Creare il wrapper della shell
La shell dell'utente git deve inoltrare i comandi nel 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
Aggiungere l'utente git al gruppo docker
sudo usermod -aG docker git
Questo dà all'utente git il permesso di eseguire docker exec. Su un server dedicato a Gitea è accettabile. Su un host condiviso, considera regole sudo limitate al comando docker exec specifico.
Configurare sshd
Aggiungi questo blocco alla fine di /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
L'AuthorizedKeysCommand chiede al container Gitea di verificare se la chiave pubblica presentata dal client SSH appartiene a un utente Gitea registrato. Se corrisponde, SSH concede l'accesso. Il blocco Match User git limita questo al solo utente git, lasciando il tuo accesso SSH abituale invariato.
sudo sshd -t
Nessun output significa che la configurazione è valida. Se vedi errori, controlla il blocco Match per eventuali refusi.
sudo systemctl restart sshd
Testare l'accesso SSH
Aggiungi la tua chiave pubblica SSH al tuo account Gitea tramite l'interfaccia web (Settings > SSH/GPG Keys). Poi dalla tua macchina locale:
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.
Ora puoi clonare, fare push e pull tramite SSH sulla porta 22:
git clone git@git.example.com:admin/my-repo.git
Come abilitare e configurare Gitea Actions per il CI/CD?
Gitea Actions è un sistema CI/CD integrato con una sintassi compatibile con GitHub Actions. Lo abiliti con una variabile d'ambiente (già impostata nel nostro file compose), distribuisci un runner come servizio Docker Compose e scrivi file YAML di workflow nei tuoi repository.
Come registrare un act_runner con Docker Compose?
Prima genera un token di registrazione del runner dal pannello di amministrazione di Gitea:
docker exec -it gitea gitea actions generate-runner-token
NxxxxxxxxxxxxxxxxxxxxxxxN
Copia questo token. Aggiungilo al tuo file .env:
echo "GITEA_RUNNER_TOKEN=YOUR_TOKEN_HERE" >> /opt/gitea/.env
chmod 600 /opt/gitea/.env
Ora aggiungi il servizio runner al tuo 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
Aggiungi runner-data: alla sezione volumes: in fondo al file. Poi avvia il runner:
docker compose up -d runner
docker compose logs runner --tail 20
level=info msg="Starting runner daemon"
level=info msg="Runner registered successfully"
Il runner monta il socket Docker (/var/run/docker.sock) per poter creare container per ogni job. È una pratica standard per i runner CI, ma significa che i job possono accedere al demone Docker dell'host. Per ambienti isolati, considera l'uso di Docker-in-Docker (DinD).
| Variabile d'ambiente | Scopo |
|---|---|
GITEA_INSTANCE_URL |
URL interna dove il runner raggiunge Gitea (usa il nome del servizio, non il dominio pubblico) |
GITEA_RUNNER_REGISTRATION_TOKEN |
Token monouso da gitea actions generate-runner-token |
GITEA_RUNNER_NAME |
Nome visualizzato nel pannello di amministrazione di Gitea |
Come appare un workflow Gitea Actions?
Gitea Actions usa la stessa sintassi YAML di GitHub Actions, con alcune differenze. Crea .gitea/workflows/build.yml nel tuo 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"
Salva il secret DEPLOY_KEY nelle impostazioni del repository sotto Settings > Actions > Secrets.
| Funzionalità | Gitea Actions | GitHub Actions |
|---|---|---|
| Directory dei workflow | .gitea/workflows/ |
.github/workflows/ |
uses: actions/* |
Funziona (recuperato da GitHub di default) | Nativo |
| Servizi container | Supportato | Supportato |
| Build a matrice | Supportato | Supportato |
| Workflow riutilizzabili | Supportato da Gitea 1.24 | Supportato |
| Actions del Marketplace | La maggior parte funziona, alcune richiedono adattamento | Nativo |
Come abilitare Git LFS in Gitea?
Git Large File Storage permette di tracciare file binari (immagini, modelli, dataset) senza gonfiare il repository. Gitea ha il supporto LFS integrato. Lo abbiamo già abilitato con LFS_START_SERVER=true nel file compose. I dati LFS vengono salvati nel volume gitea-data di default.
Per configurare il percorso di archiviazione esplicitamente o aumentare i limiti, modifica la configurazione di Gitea:
docker exec -i gitea sh -c 'cat >> /data/gitea/conf/app.ini' << 'EOF'
[lfs]
PATH = /data/git/lfs
EOF
Riavvia Gitea per applicare le modifiche:
docker compose restart gitea
Sul lato client, installa git-lfs e traccia i tipi di file:
git lfs install
git lfs track "*.bin" "*.h5" "*.onnx"
git add .gitattributes
git commit -m "Track model files with LFS"
git push
I file LFS vengono archiviati sul server al PATH configurato dentro il container. Per deployment di grandi dimensioni, puoi configurare lo storage compatibile S3 in app.ini sotto la sezione [lfs].
Come fare il mirroring dei repository GitHub su Gitea?
Il pull mirroring crea una copia in sola lettura di un repository GitHub sulla tua istanza Gitea. La sincronizzazione avviene automaticamente secondo un intervallo configurabile. Utile per il backup, per avere una cache locale dietro il runner CI, o per ridurre la dipendenza da GitHub.
Nell'interfaccia web di Gitea:
- Clicca su + > New Migration
- Seleziona GitHub come sorgente
- Inserisci l'URL del repository (es.
https://github.com/owner/repo.git) - Per i repository privati, inserisci il tuo nome utente GitHub e un personal access token come password
- Seleziona This repository will be a mirror
- Imposta l'intervallo di mirroring (default: 8 ore)
- Clicca su Migrate Repository
Il mirror sincronizza branch, tag e release. Issue, pull request e wiki possono essere migrati durante l'importazione iniziale ma non vengono sincronizzati continuamente.
Per fare il mirroring tramite 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"
}'
Come configurare i webhook per il deployment?
I webhook inviano richieste HTTP POST a un URL quando si verificano eventi in un repository. Sono un modo semplice per attivare deployment, notifiche o sistemi CI esterni.
Nel tuo repository, vai su Settings > Webhooks > Add Webhook > Gitea:
- Target URL:
https://deploy.example.com/hooks/gitea - HTTP Method: POST
- Content Type: application/json
- Secret: genera con
openssl rand -hex 32 - Trigger events: Push events (o personalizza)
Sul lato ricevente, il tuo script di deployment deve verificare la firma del webhook:
# 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
Un ricevitore webhook minimale usando uno strumento leggero come 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"
}
}
}
}
]
Come fare il backup di un'istanza Gitea?
Gitea include un comando gitea dump che impacchetta i repository, il database, la configurazione e gli oggetti LFS in un singolo file zip. Per PostgreSQL, serve anche un pg_dump separato per il ripristino point-in-time.
Backup manuale
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/
Il dump include:
| Contenuto | Incluso nel dump |
|---|---|
| Repository Git | Sì |
| Database (SQLite o dump) | Sì |
| Configurazione (app.ini) | Sì |
| Oggetti LFS | Sì |
| Allegati, avatar | Sì |
| Pacchetti | No (backup separato) |
Per PostgreSQL, esegui anche:
docker exec gitea-db pg_dump -U gitea gitea | gzip > /opt/gitea/backups/gitea-db-$(date +%Y%m%d).sql.gz
Backup automatizzato con cron
sudo mkdir -p /opt/gitea/backups
sudo chown root:root /opt/gitea/backups
sudo chmod 700 /opt/gitea/backups
Crea lo script di backup:
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
Programmalo quotidianamente alle 3 di mattina:
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
Testa lo script una volta manualmente:
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
Copia i backup fuori dal server. Un backup locale che muore con il disco non è un backup.
Come aggiornare Gitea in sicurezza?
Scarica la nuova immagine, ricrea il container e lascia che Gitea gestisca automaticamente le migrazioni del database. Fissa le versioni delle immagini in modo che gli aggiornamenti siano intenzionali, non accidentali.
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
Osserva i messaggi di migrazione:
2026/03/20 10:35:00 ...les/migration.go:67:Migrate() [I] Migration completed
Dopo aver confermato che Gitea si avvia correttamente, aggiorna il runner se è disponibile una nuova versione:
docker compose pull runner
docker compose up -d runner
Qual è la differenza tra Gitea e Forgejo?
Forgejo si è separato da Gitea alla fine del 2022, dopo che una società a scopo di lucro (Gitea Ltd.) ha preso il controllo del progetto Gitea. Forgejo è governato da Codeberg e.V., un'associazione tedesca senza scopo di lucro. All'inizio del 2026, Forgejo è un hard fork con codebase divergenti. Entrambi funzionano con un setup Docker simile, ma la migrazione tra i due non è più trasparente.
| Gitea | Forgejo | |
|---|---|---|
| Governance | Gitea Ltd. (a scopo di lucro) | Codeberg e.V. (senza scopo di lucro) |
| Licenza | MIT | GPL-3.0+ (da Forgejo v9.0) |
| Immagine Docker | docker.gitea.com/gitea |
codeberg.org/forgejo/forgejo |
| Supporto Actions | Sì (act_runner) | Sì (runner compatibile) |
| Compatibilità API | Compatibile GitHub | Compatibile GitHub |
| Funzionalità uniche | Gitea Enterprise, server MCP | Federazione (ForgeFed), strumenti di moderazione |
Se vuoi un progetto governato dalla comunità con licenza copyleft, scegli Forgejo. Se vuoi il progetto originale con supporto commerciale, scegli Gitea. Il setup Docker Compose di questa guida funziona per entrambi con modifiche minime (cambia l'immagine, adatta i percorsi).
Se inizi con Gitea e vuoi cambiare in seguito: esporta i dati con gitea dump, installa Forgejo e importa. Testa a fondo. Le codebase si sono sufficientemente diversificate da avere alcuni schemi di database diversi.
Quanta RAM e CPU serve a Gitea?
Un'istanza Gitea con PostgreSQL usa circa 150-250 MB di RAM a riposo. Con uso attivo di 5-10 utenti e runner CI, prevedi 300-500 MB totali. È circa 10 volte più leggero di un'istanza GitLab, che richiede almeno 4 GB.
Questi numeri provengono da un'istanza Gitea in produzione su un VPS Virtua Cloud (4 vCPU, 8 GB di 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 (stack completo) | CPU |
|---|---|---|
| A riposo, pochi repo | ~230 MB | < 1% |
| Attivo, 5-10 utenti | ~400 MB | 2-5% |
| Build CI in corso | ~600 MB (picchi durante i build) | 20-50% per job |
| Equivalente GitLab | 4.000+ MB | 10%+ a riposo |
Gitea gira tranquillamente su un VPS da 2 GB. Con runner CI, 4 GB offrono margine per build simultanei.
Risoluzione dei problemi
Connessione SSH rifiutata:
Verifica che l'utente git esista, che sshd_config contenga il blocco Match e che sshd sia stato riavviato. Controlla i log:
journalctl -u sshd -f
Il runner non prende i job: Conferma che il runner è registrato nel pannello di amministrazione (Site Administration > Actions > Runners). Controlla i log del runner:
docker compose logs runner --tail 50
Errori di connessione al database all'avvio: L'health check dovrebbe prevenirlo, ma se Gitea parte prima che PostgreSQL sia pronto:
docker compose restart gitea
Il push LFS fallisce con errore 413:
Aumenta client_max_body_size nella configurazione Nginx. 512M di solito basta, ma adatta in base ai file più grandi.
Log di Gitea:
docker compose logs gitea --tail 100
Oppure segui in tempo reale:
docker compose logs gitea -f
Copyright 2026 Virtua.Cloud. Tutti i diritti riservati. Questo contenuto è un'opera originale del team Virtua.Cloud. La riproduzione, ripubblicazione o redistribuzione senza autorizzazione scritta è vietata.
Pronto a provare?
Distribuisci il tuo server in pochi secondi. Linux, Windows o FreeBSD.
Vedi piani VPS