Forgejo, Gitea o cgit: quale server Git scegliere
Confronta quattro server Git self-hosted in base alla RAM: repository bare via SSH, cgit, Forgejo o Gitea e GitLab. Scopri cosa può ospitare un VPS da 1 GB.
Quale server Git self-hosted eseguire
Un server Git self-hosted non è un singolo prodotto. La RAM (memoria ad accesso casuale) disponibile sul VPS determina quale soluzione puoi usare. Git non richiede un demone dedicato: un repository bare e un account SSH (secure shell) costituiscono già un server funzionante anche sul VPS più piccolo che puoi noleggiare. Tutto ciò che va oltre questa configurazione è un'applicazione web che scegli di eseguire insieme a Git. Ogni livello aggiuntivo richiede memoria che un VPS di piccole dimensioni potrebbe non avere.
Esistono quattro livelli. Un repository bare accessibile tramite SSH, senza alcun processo in ascolto oltre a quelli già attivi. cgit, una vista web rapida in sola lettura che non richiede un database. Forgejo o Gitea, forge completi con account, issue e pull request in poche centinaia di megabyte. GitLab, che richiede un server molte volte più grande degli altri.
Scegli in base alle attività che devi svolgere, quindi confronta il requisito di memoria con il piano che stai pagando.
Di quanta RAM ha realmente bisogno ciascuna opzione
Solo due di questi progetti pubblicano un requisito hardware. Considerate il valore pubblicato come un limite minimo, non come una garanzia, e misurate la vostra istanza dopo l'avvio con systemd-cgtop o ps -o rss= -C forgejo.
I dati alla base di questo grafico
[
{
"label": "Gitea, small team",
"ram_gb": 1
},
{
"label": "GitLab, memory constrained",
"ram_gb": 8
},
{
"label": "GitLab, single node baseline",
"ram_gb": 16
}
]Gitea indica 1 GB di RAM con 2 core CPU come quantità generalmente sufficiente per team e progetti piccoli e specifica che un Raspberry Pi 3 è adeguato per carichi di lavoro ridotti. GitLab indica 16 GB come requisito di base per un'installazione a nodo singolo e 8 GB come valore minimo per quello che la sua documentazione definisce un ambiente con memoria limitata. Forgejo non pubblica alcun requisito hardware. È un fork di Gitea e si comporta allo stesso modo, quindi il valore indicato da Gitea è il riferimento pubblicato più vicino disponibile.
Su un VPS con 1 GB questo significa che i repository bare e cgit funzionano lasciando memoria disponibile, perché nessuno dei due esegue un servizio residente. Forgejo o Gitea si avviano e possono servire un team piccolo usando SQLite, ma siete al limite minimo documentato. Lasciate quindi PostgreSQL e il runner CI (integrazione continua) fuori da quel server. Se l'interfaccia web scompare senza mostrare errori, eseguite sudo dmesg -T | grep -Ei 'oom|out of memory|killed process' e cercate una riga come Out of memory: Killed process 1181 (forgejo). Indica che l'OOM killer del kernel ha terminato il processo. GitLab su un server con 1 GB non è un problema di ottimizzazione. Non funzionerà.
Livello 0: un repository bare tramite SSH
Git non ha un demone di rete da avviare. git push tramite SSH esegue git-receive-pack sul sistema remoto come normale processo Unix, quindi qualsiasi account raggiungibile con una chiave è già un remote Git. Crea un account per i repository e mantieni i repository al di fuori della relativa home directory, perché su Ubuntu 24.04 una nuova home directory ha modalità 0750 e una web view aggiunta in seguito non può accedervi.
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 crea un repository senza working copy, come quelli che vengono mantenuti su un server. Il push verso il branch estratto di un repository che dispone di una working copy viene rifiutato per impostazione predefinita con refusing to update checked out branch: refs/heads/main, ed è l'errore più comune a questo livello.
Ora assegna una chiave all'account e clona il 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 mainUn primo push riuscito termina con * [new branch] main -> main. Un push che termina con git@vps.example.com: Permission denied (publickey) non è mai stato autenticato, quindi leggi il log del server con sudo journalctl -u ssh -n 20. Una riga contenente Authentication refused: bad ownership or modes for file /home/git/.ssh/authorized_keys indica che la modalità del file è errata, perché sshd ignora un file di chiavi su cui altri utenti possono scrivere.
Poi rimuovi la shell dall'account.
command -v git-shell | sudo tee -a /etc/shells
sudo chsh -s "$(command -v git-shell)" gitgit-shell accetta soltanto i pochi comandi che Git invia tramite SSH, quindi un accesso interattivo si interrompe con un messaggio invece di mostrare un prompt:
fatal: Interactive git shell is not enabled.
hint: ~/git-shell-commands should exist and have read and execute access.Questo è l'intero server. Non c'è un database e non c'è alcun processo web da aggiornare. Rinunci a tutte le funzioni offerte da una forge: nessuna consultazione dei repository, nessun issue tracker, nessuna pull request e nessuna autorizzazione per utente. Ogni chiave presente in quel file può leggere e scrivere in ogni repository di cui è proprietario l'utente git.
Livello 1: cgit offre una vista web senza database
cgit è un programma CGI (Common Gateway Interface) scritto in C. Il server web lo esegue una volta per richiesta, legge i repository direttamente dal disco e non conserva alcuno stato proprio. Ubuntu 24.04 lo include nel componente universe.
sudo apt update
sudo apt install -y cgit fcgiwrap nginx
sudo install -d -o www-data -g www-data /var/cache/cgitIndicate la directory dei repository 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 esamina la directory e mostra tutti i repository che trova, quindi un nuovo repository bare compare senza ulteriore configurazione. cache-size indica il numero di pagine memorizzate nella cache; la cache resta disabilitata quando il valore è zero. Prima di aggiungere righe, leggete ciò che il pacchetto ha già inserito in /etc/cgitrc, perché i pacchetti Debian e Ubuntu forniscono alcune impostazioni predefinite.
Ogni voce mostra la prima riga del file description del repository, quindi un nuovo repository bare viene mostrato come Unnamed repository; edit this file 'description' to name the repository.. Correggete il valore una volta per ogni repository:
echo 'Project X, internal tooling' | sudo -u git tee /srv/git/project.git/descriptionIl file del sito nginx e come verificarlo
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 serve cgit.css e cgit.png come file statici, mentre try_files inoltra tutto il resto al CGI in /usr/lib/cgit/cgit.cgi. Una pagina 502, con connect() to unix:/run/fcgiwrap.socket failed (2: No such file or directory) in /var/log/nginx/error.log, indica che l'unità socket non è in esecuzione oppure è in ascolto su un altro percorso. La riga systemctl show stampa il percorso effettivamente utilizzato.
Prima di basarvi su questa configurazione, considerate due limitazioni. cgit è di sola lettura e non offre autenticazione, quindi tutto ciò che si trova sotto scan-path è pubblico: mantenete i repository privati fuori da quella directory oppure configurate l'autenticazione HTTP Basic davanti all'intero sito. Inoltre, il CGI viene eseguito con l'utente del server web, che deve poter attraversare /srv/git e leggere ogni repository. Se l'utente non può accedere a una directory, questa compare nell'indice come vuota invece di generare un errore.
Livello 2: Forgejo o Gitea per issue e pull request
Forgejo e Gitea seguono lo stesso modello: un singolo binario Go che fornisce una forge web con utenti, organizzazioni, issue, pull request, release, un registro dei pacchetti e un sistema CI integrato. L'installazione completa consiste nel binario e in SQLite. Per questo possono essere eseguiti su hardware sul quale GitLab non sarebbe adatto. Il file Compose riportato di seguito è quello della documentazione di Forgejo, con il tag dell'immagine indicato nella documentazione a ottobre 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 -1La riga curl dovrebbe stampare una riga di stato HTTP. Prima di completare la configurazione iniziale, può restituire un redirect a /install. Anche in questo caso il servizio è attivo. Se invece il container termina, la causa più comune è la proprietà dei file: la directory ./forgejo deve appartenere all'UID (user id) indicato in USER_UID, altrimenti il processo non può scrivere nella propria directory dati. Docker Compose su un VPS descrive in dettaglio la struttura dei file e la regola relativa alla proprietà dei volumi.
Due risposte nella pagina di configurazione determinano se gli URL di clone funzionano. La porta SSH deve essere 222, perché il file Compose mappa la porta 222 dell'host sulla porta 22 del container. Il dominio deve essere il nome che gli utenti inseriranno effettivamente. Se uno dei due valori è errato, ogni pagina del repository mostra un comando di clone che non funziona per chiunque lo copi. In seguito entrambi si trovano nella sezione [server] di app.ini, come SSH_PORT, SSH_DOMAIN e ROOT_URL.
Per un'istanza pubblica, pubblica la porta web soltanto sull'indirizzo loopback ('127.0.0.1:3000:3000') e usa nginx come reverse proxy per TLS (transport layer security). Gitea può essere installato nello stesso modo usando l'immagine docker.gitea.com/gitea indicata dalla relativa documentazione, oppure come singolo binario con una sola unità systemd e un solo app.ini. La release stabile attuale è v28.1.0, pubblicata il 6 ottobre 2026. Con v28.0.0, alla fine di settembre, il progetto ha rimosso il vecchio prefisso 1.. Di conseguenza, la release successiva alla 1.27 è la 28, non la 1.28.
Mantieni SQLite finché è possibile. L'istanza richiede un solo processo e un solo file e sopravvive a un riavvio senza servizi aggiuntivi da supervisionare. PostgreSQL giustifica il costo quando più persone scrivono contemporaneamente, perché SQLite serializza le scritture e le esecuzioni CI prolungate scrivono continuamente. Entrambi i progetti consentono di migrare in seguito un'istanza esistente a PostgreSQL. Non è quindi una scelta vincolante.
Forgejo o Gitea: quali sono le differenze effettive
L’origine è condivisa. Gitea è nato da un fork di Gogs nel 2016. Alla fine del 2022, il controllo del dominio e del marchio Gitea è passato a una società, Gitea Ltd, e diversi maintainer, insieme a Codeberg, hanno avviato Forgejo. Forgejo è pubblicato da Codeberg e.V., un’associazione senza scopo di lucro registrata in Germania, e nel 2024 è passato dalla licenza MIT alla GPLv3 (GNU general public license version 3). Gitea resta distribuito con licenza MIT ed è sviluppato con il supporto di un’azienda commerciale.
Nell’uso quotidiano, i set di funzionalità sono simili. Il percorso di migrazione tra i due progetti, invece, non lo è. Forgejo v10.0, rilasciato a gennaio 2025, è stata l’ultima release in grado di importare direttamente un database Gitea, e solo da Gitea v1.22 o versioni precedenti. A ottobre 2026 Gitea è alla v28.1.0, quindi un’istanza Gitea aggiornata non dispone di una procedura supportata per il passaggio a Forgejo in-place. Scegli una delle due soluzioni prima di inserirvi dati e considera ogni migrazione successiva come un’esportazione seguita da una nuova importazione.
Una regola semplice per scegliere. Se per te la governance è importante o vuoi che il progetto resti affidato a un’organizzazione senza scopo di lucro, usa Forgejo. Se vuoi una base di installazioni più ampia e un’opzione di supporto commerciale, usa Gitea. Entrambi i progetti sono sviluppati apertamente e pubblicano release frequenti: Forgejo rilascia una release stabile ogni tre mesi e una release LTS (long term support) ogni anno; a ottobre 2026, la versione corrente è la v16.0.5 e la LTS è la v15.0.9. Forgejo supporta la v16 fino al 29 ottobre 2026 e la v15 fino al 15 luglio 2027; controlla quindi la pagina delle release prima di bloccare una major version.
Livello 3: quanto costa GitLab prima di fare qualsiasi cosa
GitLab CE appartiene a una categoria diversa di software. Una singola istanza è costituita da un insieme di servizi cooperanti: Puma per l'applicazione web, Sidekiq per i processi in background, PostgreSQL, Redis, Gitaly per l'accesso ai repository e nginx come frontend. Il pacchetto Omnibus li installa insieme. Questo semplifica l'installazione, ma aumenta il fabbisogno minimo di memoria.
La pagina dei requisiti di GitLab indica 16 GB di RAM e 8 vCPU come configurazione di riferimento per un'installazione a nodo singolo. Indica inoltre 8 GB come valore minimo in un ambiente con memoria limitata. La stessa pagina consiglia di disabilitare lo swap, perché l'uso dello swap sotto carico degrada gravemente l'istanza. Questi sono i valori pubblicati a ottobre 2026. Nel corso degli anni sono aumentati, quindi consulta nuovamente la pagina prima di dimensionare il server.
Con quel budget ottieni funzionalità concrete: un container registry, un package registry, autorizzazioni granulari, funzioni di compliance e audit e una CI testata su larga scala. Se nessuno nel tuo team sa indicare una funzionalità di questo elenco necessaria nel trimestre in corso, stai pagando un VPS più grande senza ottenere alcun vantaggio.
Il modello di accesso SSH: un utente Git e molte chiavi
Ogni livello qui utilizza lo stesso metodo di autenticazione. Esiste un account Unix denominato git e tutte le chiavi pubbliche vengono inserite nel file ~/.ssh/authorized_keys di quell'account. L'autenticazione si basa sulla chiave. L'autorizzazione dipende dalle opzioni inserite davanti alla chiave sulla stessa riga.
Una riga con la sola chiave concede all'utente tutte le operazioni consentite a quell'account. Un comando forzato limita l'accesso a Git:
restrict,command="git-shell -c \"$SSH_ORIGINAL_COMMAND\"" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIexamplekeyhere alice@laptoprestrict, disponibile da OpenSSH 7.2, disabilita con una sola parola il port forwarding, l'agent forwarding, X11 e l'allocazione di una PTY (pseudo terminal). command= sostituisce la richiesta del client con quella specificata e Git continua a funzionare perché invia la propria richiesta in $SSH_ORIGINAL_COMMAND.
Una piattaforma Git genera quel file automaticamente, e questa è la differenza sostanziale tra il livello 0 e il livello 2. Quando utilizzano il server OpenSSH di sistema, che è la configurazione predefinita, Forgejo e Gitea riscrivono authorized_keys con una riga per ogni chiave registrata. Ogni riga contiene un comando forzato che identifica la chiave tramite il relativo ID nel database:
command="/usr/local/bin/forgejo --config=/etc/forgejo/app.ini serv key-3",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty,no-user-rc,restrict ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIexamplekeyhere aliceIl comando forzato trasforma un unico account Unix condiviso in autorizzazioni specifiche per ogni utente: key-3 indica alla piattaforma quale utente si sta connettendo e la piattaforma verifica l'utente rispetto al repository prima che venga trasferito qualsiasi oggetto. Non modificare manualmente quel file su un server gestito dalla piattaforma, perché viene rigenerato dal database e la riga aggiunta scompare. Se abiliti il server SSH integrato della piattaforma, oppure configuri OpenSSH per ottenere le chiavi dalla piattaforma tramite AuthorizedKeysCommand, quel file non è necessario. Nel secondo caso, entrambi i progetti indicano di disabilitarne la generazione. Le deploy key utilizzano lo stesso meccanismo: una deploy key è una normale chiave SSH registrata per un singolo repository, generalmente in sola lettura. Il controllo viene eseguito dalla piattaforma anziché da sshd.
Due procedure sono più importanti di tutte le configurazioni precedenti. Usa una chiave distinta per ogni persona o macchina, mai una chiave condivisa, perché revocare una chiave condivisa significa sostituirla per tutti contemporaneamente. Rimuovi inoltre le chiavi il giorno stesso in cui una persona lascia il progetto: una vecchia chiave presente nel file consente un accesso permanente che nessuno sta monitorando. Una corretta gestione delle chiavi SSH su un server illustra i tipi di chiavi e le passphrase; tutte queste indicazioni si applicano qui senza modifiche. Se il server è nuovo, i primi dieci minuti su un nuovo VPS sono il passaggio corretto da completare prima di inserirvi i repository.
Posso eseguire GitHub Actions sul mio server Git?
Puoi eseguire workflow scritti con la sintassi di GitHub Actions. Non puoi eseguire GitHub. Forgejo Actions è abilitato per impostazione predefinita da Forgejo v1.21 e legge i file di workflow da .forgejo/workflows in ogni repository. Gitea Actions funziona allo stesso modo e legge .gitea/workflows. Entrambi richiedono un secondo programma, il runner, che deve essere installato e registrato sulla tua istanza usando un token disponibile nelle impostazioni di amministrazione. Molte actions pubblicate funzionano senza modifiche; non funzionano invece quelle che chiamano l'API di GitHub o che si aspettano un'infrastruttura ospitata da GitHub.
Considera due conseguenze. Con le consuete etichette dei container, il runner avvia un container per ogni job. Di conseguenza, richiede un container engine e una quota di memoria propria. Per questo non va eseguito sullo stesso server da 1 GB che ospita la piattaforma Git. Entrambi i runner possono anche eseguire i job direttamente sull'host, tramite un'etichetta che termina con :host in Forgejo. Questa modalità non richiede un engine, ma non inserisce alcun container tra il job e la macchina. Inoltre, il runner esegue qualunque istruzione sia contenuta nel file di workflow. La documentazione di Forgejo lo dichiara esplicitamente: il runner esegue codice da remoto. Quando possibile, assegnagli un host dedicato. Come minimo, usa un utente non privilegiato dedicato e un token di registrazione limitato a un solo repository.
Se i repository resteranno su GitHub e vuoi soltanto utilizzare risorse di calcolo su hardware sotto il tuo controllo, si tratta di una configurazione diversa, con passaggi diversi: un runner self-hosted di GitHub Actions si collega a un repository GitHub e non richiede nulla di tutto questo. Se stai ancora valutando il costo dell'abbandono, che cosa offre realmente GitHub distingue il servizio di hosting Git dalla rete di servizi che lo circonda.
Backup: i repository contengono solo metà dello stato
Un repository bare è una directory, quindi copiarlo significa copiare tutto il suo contenuto. Un clone mirror da un altro computer è un vero backup e viene aggiornato direttamente nella directory esistente:
git clone --mirror git@vps.example.com:/srv/git/project.git
cd project.git && git remote updateIl comando recupera ogni ref e ogni oggetto. Non recupera gli hook lato server né il file description, quindi, se usi gli hook, conserva anche una copia a livello di file della directory.
Un forge conserva nel database issue, pull request, utenti, chiavi e permessi. Una copia dei soli repository elimina tutti questi dati. Entrambi i progetti includono un comando dump che scrive database, repository, configurazione e allegati in un unico archivio:
sudo -u git forgejo dump -c /etc/forgejo/app.ini -f /var/backups/forgejo-dump.zipCon Docker, lo stesso comando viene eseguito all'interno del container. Il percorso della configurazione dipende dall'immagine, quindi controllalo prima di digitare il comando:
docker compose exec server ls /data/gitea/conf
docker compose exec -u git server forgejo dump -c /data/gitea/conf/app.iniEseguilo con l'utente proprietario dei dati e scrivi l'archivio in una directory in cui quell'utente possa scrivere. Poi copia l'archivio fuori dal server, perché un backup presente solo sulla macchina di cui esegui il backup non è un backup. Il ripristino è il passaggio che spesso viene saltato: estrai ora un dump su una macchina di riserva, così impari la procedura in un momento tranquillo invece che durante un'interruzione del servizio.
Scegli in base allo scenario
Una persona con un laptop e un VPS, senza bisogno di navigare nel codice: repository bare tramite SSH. Non è necessario eseguire servizi aggiuntivi e non c'è nulla da aggiornare.
Lo stesso scenario, con l'esigenza di leggere il codice in un browser e condividere link: aggiungi cgit. Non serve ancora un database e non rimane in esecuzione alcun servizio aggiuntivo.
Un team che revisiona il codice degli altri e tiene traccia delle issue: Forgejo o Gitea, con almeno 2 GB di RAM. Sposta il runner CI su un secondo server quando i job diventano consistenti.
Un'organizzazione che ha bisogno di un container registry e di audit trail, con 16 GB da dedicare al server: GitLab. Con una dotazione inferiore, non avviarlo.
Passare dai primi tre livelli è semplice, perché in tutti i casi i repository sono normali directory Git su disco. Inizia dal livello più basso che soddisfa le esigenze. Se stai valutando quali altri servizi meritano spazio sullo stesso server, la selezione dei servizi che vale la pena eseguire in self-hosting mette il server Git accanto agli altri servizi che competono per quella RAM.
FAQ
Un VPS da 1 GB può eseguire Forgejo o Gitea?
Sì, per un team piccolo, usando SQLite e senza altri carichi pesanti sul server. La documentazione di Gitea indica 1 GB di RAM e 2 core CPU come risorse in genere sufficienti per team e progetti di piccole dimensioni; Forgejo è un fork di Gitea e ha requisiti simili. Non aggiungere PostgreSQL o un runner CI a quella macchina. Se il servizio scompare senza errori nel proprio log, esegui sudo dmesg -T | grep -Ei 'oom|out of memory|killed process': una riga che indica il processo terminato significa che è intervenuto l'out-of-memory killer del kernel. In questo caso serve un piano più grande, non un flag di ottimizzazione.
Qual è la differenza tra Forgejo e Gitea?
Condividono la storia del codice e la maggior parte delle funzionalità. Gitea è nato come fork di Gogs nel 2016; Forgejo è nato come fork di Gitea alla fine del 2022, dopo che il controllo del marchio Gitea è passato a un'azienda. Forgejo è pubblicato da Codeberg e.V., un'organizzazione non profit tedesca, con licenza GPLv3; Gitea mantiene la licenza MIT e ha il supporto di un'azienda commerciale. La differenza pratica riguarda il percorso di migrazione. Forgejo v10.0, pubblicato a gennaio 2025, è stata l'ultima release in grado di utilizzare direttamente un database Gitea, e soltanto a partire da Gitea v1.22 o versioni precedenti. Di conseguenza, per un'istanza Gitea aggiornata non esiste un passaggio in-place supportato.
Posso eseguire workflow GitHub Actions su un server Git self-hosted?
Forgejo Actions e Gitea Actions eseguono entrambi workflow scritti con la sintassi YAML di GitHub Actions, letti da .forgejo/workflows e .gitea/workflows. Devi installare un programma runner separato e registrarlo presso la tua istanza. Molte actions pubblicate funzionano senza modifiche, mentre quelle che chiamano l'API GitHub non funzionano. Il runner esegue codice arbitrario proveniente dai tuoi repository e, con le consuete configurazioni dei container, avvia un container per ogni job. Assegnagli quindi un host dedicato o almeno un utente non privilegiato dedicato. Non eseguirlo su un server da 1 GB che sta già eseguendo il forge.
Come posso eseguire il backup di un server Git self-hosted?
Per i repository bare, git clone --mirror eseguito da un'altra macchina copia ogni ref e ogni oggetto, mentre git remote update all'interno di quel mirror lo aggiorna. Per Forgejo o Gitea, i repository rappresentano solo una parte dello stato, perché issue, pull request, utenti e chiavi risiedono nel database. Usa il dump integrato, sudo -u git forgejo dump -c /etc/forgejo/app.ini, oppure lo stesso comando all'interno del container se l'installazione utilizza Docker. Copia l'archivio fuori dal server e ripristinalo una volta su una macchina di riserva, per verificare che la procedura funzioni.