Forgejo è una piattaforma Git self-hosted leggera, scritta in Go e nata come fork community-driven di Gitea. Il progetto è nato alla fine del 2022, dopo che i domini e il marchio di Gitea sono stati trasferiti a una società a scopo di lucro (Gitea Limited) senza il consenso della comunità. In risposta, Codeberg e.V. ha promosso la creazione di Forgejo con l’obiettivo di mantenere il software libero e governato dalla comunità. Dal 2024 Forgejo è diventato un hard fork, prendendo una direzione di sviluppo autonoma rispetto a Gitea.

Rispetto a soluzioni più pesanti come GitLab, Forgejo si distingue per il consumo minimo di risorse e la semplicità di configurazione, offrendo allo stesso tempo tutto il necessario per ospitare i propri repository: gestione del codice, issue tracking, pull request, wiki integrata e un sistema di CI/CD opzionale tramite Forgejo Actions.

Configurazione Porte e Flussi di Rete

Prima di iniziare a installare e configurare Forgejo è necessario capire come questo servizio (e in generale tutti i servizi Git self-hosted) utilizzano le porte del sistema. Oltre alla WebUI, Forgejo permette di gestire la connessione con i repository tramite SSH, utilizzando di norma la porta 22, che di default è dedicata a OpenSSH. Nella configurazione di questa guida andremo quindi a riorganizzare le porte, in modo che il risultato finale sia il più trasparente possibile.

graph LR Client["Client"] -->|HTTPS :443| Caddy["Reverse Proxy
(Caddy)"] Caddy -->|HTTP :3000| Forgejo["Forgejo
Web UI"] Client -->|SSH :22| NAT["NAT
Forward"] NAT -->|:2222| ForgejoSSH["Forgejo
SSH Server"] Client -->|SSH :8181| OpenSSH["OpenSSH
(Sistema)"]

Flusso Web Interface

Per la Web Interface è necessario configurare un reverse proxy che instradi il traffico HTTPS verso la porta 3000 di Forgejo. In questa guida utilizziamo Caddy , ma è possibile usare qualsiasi reverse proxy. Il blocco seguente va adattato con il proprio dominio e l’IP del server su cui gira Forgejo:

caddy
git.nome-dominio.com {
    reverse_proxy 80.81.82.83:3000
}

Flusso SSH

Il protocollo SSH viene utilizzato per le operazioni Git quotidiane: git clone, git push e git pull. A differenza della Web Interface, il traffico SSH non passa dal reverse proxy. SSH è un protocollo a sé stante che opera direttamente su TCP, mentre Caddy gestisce solo traffico HTTP/HTTPS. Le connessioni SSH vengono quindi gestite a livello di rete tramite una regola NAT.

Un elemento da risolvere è che la porta 22, usata di default da SSH, è già occupata dal servizio OpenSSH di sistema, quello che permette di accedere alla macchina da remoto per amministrazione. Forgejo ha bisogno della stessa porta per offrire URL di clone nel formato standard git@git.nome-dominio.com:utente/repo.git, senza costringere l’utente a specificare una porta personalizzata.

La soluzione adottata in questa guida è spostare OpenSSH sulla porta 8181 e usare una regola NAT che redirige il traffico in arrivo sulla porta 22 verso la porta 2222, dove ascolta il server SSH integrato di Forgejo. In questo modo l’utente clona i repository con il comando classico sulla porta 22, il NAT instraderà la connessione a Forgejo in modo trasparente, e l’accesso di amministrazione alla macchina resterà disponibile sulla porta 8181.

Script di Configurazione

Su NixOS l’installazione è particolarmente comoda: il modulo dedicato si occupa di creare il servizio systemd, configurare il database e gestire i backup in modo completamente dichiarativo.

nix
{ config, pkgs, ... }:

{
  environment.systemPackages = [ pkgs.forgejo ];

  services.forgejo = {
    enable = true;

    database.type = "postgres";

    lfs.enable = true;

    settings = {
      server = {
        DOMAIN = "git.nome-dominio.com"; # <-- Cambia con il tuo dominio
        ROOT_URL = "https://git.nome-dominio.com/";
        HTTP_PORT = 3000;
        HTTP_ADDR = "0.0.0.0";
        SSH_PORT = 22;
        SSH_LISTEN_PORT = 2222;
        START_SSH_SERVER = true;
        DISABLE_SSH = false;
      };

      service.DISABLE_REGISTRATION = true;
      actions.ENABLED = false;

      cache = {
        ADAPTER = "twoqueue";
        HOST = ''{"size":100, "recent_ratio":0.25, "ghost_ratio":0.5}'';
      };

      session.COOKIE_SECURE = true;
    };

    dump = {
      enable = true;
      type = "tar.zst";
      interval = "daily";
      backupDir = "/var/backup/forgejo";
    };
  };

  services.openssh = {
    enable = true;
    ports = [ 8181 ];
  };

  networking.nat = {
    enable = true;
    internalInterfaces = [ "lo" ];
    externalInterface = "eth0"; # <-- Cambia con la tua interfaccia di rete
    forwardPorts = [{
      destination = "127.0.0.1:2222";
      proto = "tcp";
      sourcePort = 22;
    }];
  };

  networking.firewall.allowedTCPPorts = [
    80    # HTTP (per il redirect HTTPS e ACME challenge)
    443   # HTTPS
    3000  # Forgejo web
    22    # SSH Forgejo (operazioni git)
    8181  # SSH di sistema
  ];
}

Attivazione Database

Forgejo supporta tre motori di database, ognuno adatto a scenari diversi, che per questioni di semplicità si è voluto riassumere nella tabella sottostante:

Database Risorse Quando usarlo
SQLite Minime (nessun processo separato, pochi MB) Ideale per un uso personale o per piccoli team con pochi utenti. Non richiede alcun servizio esterno: i dati vengono salvati in un singolo file, il che rende semplicissimi backup e migrazione. È la scelta più leggera se si prevede un utilizzo contenuto.
MySQL Medie (150-400 MB per il servizio) Adatto se si ha già un’istanza MySQL in uso per altri servizi e si vuole centralizzare la gestione dei database. Non offre vantaggi particolari rispetto a PostgreSQL per Forgejo, ma può avere senso in ambienti dove MySQL è già lo standard.
PostgreSQL Medie (100-300 MB per il servizio) La scelta consigliata per istanze in produzione o con più utenti attivi. Gestisce senza problemi letture e scritture simultanee, offre strumenti avanzati di backup e manutenzione, e su NixOS l’integrazione è particolarmente fluida.

Quale Database devo scegliere?

Anche se si è un solo sviluppatore, bisogna considerare quanti strumenti accedono contemporaneamente a Forgejo. Se si utilizzano agenti di coding (Claude Code, Cursor, Copilot…) o pipeline CI/CD che interagiscono con i repository in parallelo, le scritture concorrenti sul database aumentano sensibilmente. SQLite, ad esempio, blocca l’intero file durante ogni scrittura, il che può causare rallentamenti o errori. Quindi in scenari dove ci sono connessioni frequenti e contemporanee, è preferibile optare per PostgreSQL anche su istanze personali.

In questa guida utilizziamo PostgreSQL, ma cambiare è semplice: basta modificare il valore di database.type con "sqlite3" o "mysql". Con database.type = "postgres" NixOS gestisce tutto in autonomia: abilita PostgreSQL se non lo è già, crea un utente e un database dedicati a Forgejo, e configura la connessione via Unix socket con peer authentication. Non serve specificare credenziali perché il processo Forgejo viene riconosciuto direttamente dal sistema operativo.

Large File Storage

L’opzione lfs.enable attiva il supporto a Git Large File Storage, che permette di gestire file binari di grandi dimensioni (immagini, archivi, asset grafici) senza appesantire la cronologia del repository. I file vengono salvati in una directory separata mentre nel repository Git resta solo un riferimento leggero. Un nice-to-have che può essere disabilitato se non lo si vuole.

Gestione Server

La sezione settings.server definisce come Forgejo è raggiungibile dall’esterno. DOMAIN e ROOT_URL indicano il dominio pubblico dell’istanza e vanno personalizzati con il proprio indirizzo. Forgejo resta in ascolto sulla porta 3000 su tutte le interfacce di rete (0.0.0.0), in modo da essere raggiungibile anche da altre macchine nella rete locale. Questo è necessario quando il reverse proxy si trova su un server diverso da quello di Forgejo: il proxy instraderà il traffico verso l’IP della macchina sulla porta 3000, occupandosi di gestire i certificati HTTPS. Per la configurazione del reverse proxy si possono consultare le guide di Caddy o Nginx presenti su questo sito.

Connessione SSH

Come anticipato all’inizio della guida, la parte SSH merita un’attenzione particolare. Forgejo integra un proprio server SSH per gestire le operazioni Git via git clone, git push e git pull tramite chiave. L’obiettivo è poter clonare i repository con il classico git clone git@git.nome-dominio.com:utente/repo.git senza dover specificare porte non standard nell’URL.

Poiché le porte sotto la 1024 sono privilegiate e il servizio Forgejo gira come utente non privilegiato, non è possibile farlo ascoltare direttamente sulla porta 22. Per aggirare questa limitazione, Forgejo ascolta internamente sulla porta 2222 (SSH_LISTEN_PORT) mentre SSH_PORT = 22 indica la porta mostrata negli URL di clone dell’interfaccia web. Una regola NAT nel firewall (networking.nat.forwardPorts) si occupa di redirigere il traffico in arrivo sulla porta 22 verso la 2222, rendendo il tutto trasparente per l’utente.

Il servizio SSH di sistema (OpenSSH), usato per accedere alla macchina da remoto, deve essere spostato su un’altra porta per evitare il conflitto con la regola NAT. Per questo motivo la configurazione include services.openssh.ports = [ 8181 ], che sposta OpenSSH sulla porta 8181.

Registrazione e Actions

Con service.DISABLE_REGISTRATION impostato a true la registrazione pubblica viene disabilitata: solo un amministratore potrà creare nuovi account. Questo è consigliato per istanze personali o di piccoli team che non vogliono utenti esterni. Le Forgejo Actions, il sistema di CI/CD integrato, sono disabilitate tramite actions.ENABLED = false e possono essere attivate in seguito se necessario.

Cache e sessioni

La cache è configurata con l’algoritmo twoqueue, una strategia di caching in memoria che bilancia gli elementi utilizzati di recente con quelli più frequenti. È una buona scelta per istanze di piccole e medie dimensioni perché non richiede servizi esterni come Redis. L’opzione session.COOKIE_SECURE forza l’invio dei cookie di sessione solo su connessioni HTTPS, garantendo che le credenziali di sessione non vengano mai trasmesse in chiaro.

Backup

La sezione dump configura il backup automatico dell’intera istanza Forgejo, comprensivo di database, repository, configurazione e file LFS. In questa configurazione il backup viene eseguito quotidianamente in formato tar.zst (compressione Zstandard, efficiente e veloce) e salvato nella directory /var/backup/forgejo. Le opzioni possono essere modificate in base alle necessità dell’utente.

Network & Firewall

La configurazione del firewall apre le porte strettamente necessarie: la 80 e la 443 per il traffico HTTP/HTTPS, la 3000 per permettere al reverse proxy remoto di raggiungere l’interfaccia web di Forgejo, la 22 per le operazioni Git via SSH di Forgejo, e la 8181 per l’accesso SSH di sistema alla macchina.

Primo avvio

Una volta applicata la configurazione con nixos-rebuild switch, Forgejo è attivo ma non ancora utilizzabile. Avendo disabilitato la registrazione pubblica, è necessario creare l’utente amministratore da riga di comando.

Il comando forgejo è disponibile perché nella configurazione abbiamo aggiunto il pacchetto forgejo a environment.systemPackages, altrimenti su NixOS il binario sarebbe accessibile solo al servizio systemd e non dalla shell:

bash
sudo -u forgejo forgejo --config /var/lib/forgejo/custom/conf/app.ini --work-path /var/lib/forgejo admin user create --admin --username admin --password Sup3rP4ssw0rd --email admin@nome-dominio.com

Anatomia del comando

Nel comando sopra la parola forgejo compare due volte: la prima, dopo sudo -u, indica l’utente di sistema con cui viene eseguito il comando; la seconda è il nome del binario vero e proprio. Ricordatevi di modificare username, password ed email con i vostri dati.

A questo punto è possibile accedere all’interfaccia web tramite il reverse proxy (ad esempio https://git.nome-dominio.com) e completare la configurazione dal pannello di amministrazione. Da qui si possono creare ulteriori utenti, organizzazioni e repository, oltre a personalizzare aspetto e comportamento dell’istanza. Per la configurazione del reverse proxy si rimanda alla sezione Gestione Server sopra.

Autenticazione SSH per Git

Per lavorare con i repository tramite git clone, git push e git pull senza dover inserire la password ogni volta, è necessario configurare l’autenticazione via chiave SSH. La procedura è la stessa usata per qualsiasi server SSH: si genera una coppia di chiavi sul proprio computer e si carica la chiave pubblica nel proprio profilo Forgejo. La guida Chiavi SSH spiega nel dettaglio come generare e gestire le chiavi.

Impostazioni chiavi SSH in Forgejo

Una volta generata la chiave, basta accedere a Forgejo, andare in Impostazioni utente → Chiavi SSH/GPG e incollare il contenuto della chiave pubblica (il file .pub). Da quel momento in poi tutte le operazioni Git via SSH saranno autenticate automaticamente:

bash
git clone git@git.nome-dominio.com:utente/repo.git

Se si è spostato OpenSSH sulla porta 8181 come indicato nella configurazione, è utile aggiungere un blocco nel file ~/.ssh/config della propria macchina locale per evitare di specificare la porta ogni volta che ci si collega al server per amministrazione:

text
Host mioserver
    HostName 80.81.82.83
    Port 8181
    User <utente>

In questo modo ssh mioserver userà automaticamente la porta 8181 per la connessione di amministrazione, mentre le operazioni Git verso git@git.nome-dominio.com continueranno a passare dalla porta 22 gestita da Forgejo.

Consigli finali

È buona pratica verificare periodicamente che i backup automatici funzionino correttamente. I dump vengono salvati in /var/backup/forgejo e conviene controllare che i file vengano effettivamente creati e che non siano corrotti, provando ogni tanto un restore di prova su un’istanza separata.

Uno dei vantaggi di Forgejo su NixOS è la semplicità degli aggiornamenti: essendo gestito come pacchetto di sistema, viene aggiornato automaticamente insieme al resto del sistema al successivo nixos-rebuild switch. Non serve alcun intervento manuale, le migrazioni del database vengono eseguite in automatico all’avvio del servizio.

Troubleshooting

Se Forgejo non si avvia o si comporta in modo inaspettato, il primo strumento da consultare sono i log del servizio systemd:

bash
journalctl -u forgejo -f

Un problema frequente riguarda la connessione SSH. Se git clone sulla porta 22 non funziona, verificare che la regola NAT sia attiva e che il forwarding dalla porta 22 alla 2222 stia funzionando:

bash
sudo iptables -t nat -L PREROUTING -n --line-numbers

Se la regola non è presente, potrebbe essere necessario un nixos-rebuild switch. Per verificare che Forgejo stia effettivamente ascoltando sulla porta 2222:

bash
ss -tlnp | grep 2222

Se invece non si riesce più ad accedere alla macchina via SSH per amministrazione, probabilmente OpenSSH non è stato spostato correttamente sulla porta 8181. Si può verificare con ss -tlnp | grep 8181.

Se l’interfaccia web restituisce errori relativi al database, conviene verificare che PostgreSQL sia attivo e che il database esista:

bash
systemctl status postgresql
sudo -u forgejo psql -d forgejo -c '\conninfo'

Nel caso in cui i cookie di sessione non vengano mantenuti e il login non funzioni, il problema è quasi sempre legato all’assenza di HTTPS. L’opzione session.COOKIE_SECURE = true impone che i cookie vengano inviati solo su connessioni cifrate, quindi senza un reverse proxy con certificato valido il browser li scarta silenziosamente.

Se i backup non vengono creati nella directory /var/backup/forgejo, verificare che la directory esista e che l’utente forgejo abbia i permessi di scrittura:

bash
ls -la /var/backup/forgejo