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 passare all’installazione, è necessario capire come Forgejo utilizza le porte in un ambiente dove andremo ad utilizzare Docker. Infatti, oltre alla Web UI, Forgejo permette di gestire la connessione con i repository tramite SSH, utilizzando di norma la porta 22, che di default è dedicata a OpenSSH. Con Docker la gestione delle porte è più semplice rispetto a una configurazione nativa (o quella in NixOS ), in quanto il port mapping del container si occupa di instradare il traffico senza bisogno di regole NAT sul sistema.

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

Configurazione del Reverse Proxy

Per la Web Interface è necessario configurare un reverse proxy che veicoli il traffico HTTPS verso la porta 3000 di Forgejo. In questa guida utilizziamo Caddy , ma è possibile usare qualsiasi reverse proxy. Nel blocco seguente è riportata la configurazione di base, disponibile anche nella documentazione ufficiale . Il dominio, l’IP del server e la porta vanno adattati alla propria configurazione:

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

Configurazione del Protocollo 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, in quanto SSH è un protocollo a sé stante che opera direttamente su TCP, mentre Caddy gestisce solo traffico HTTP/HTTPS.

Nel docker-compose di questa guida la porta SSH è mappata come 22:22, così che Docker possa esporre il server SSH di Forgejo direttamente sulla porta 22 dell’host, permettendo di clonare i repository con il formato standard senza dover specificare porte personalizzate:

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

Prima di poter utilizzare la porta 22 per Forgejo è però necessario spostare OpenSSH di sistema, che di default occupa quella stessa porta per l’accesso remoto alla macchina. In questa guida lo sposteremo sulla porta 5555, ma è possibile scegliere qualsiasi porta libera. Se non si esegue questa modifica, Docker non riuscirà a fare il bind sulla porta 22 trovandola già occupata.

Modifica della porta SSH

Per farlo è sufficiente modificare il file sshd_config e sostituire la porta 22 con quella scelta:

bash
sudo nvim /etc/ssh/sshd_config

Configurazione SELinux e Firewall

Su distribuzioni come Fedora o RHEL, SELinux blocca l’utilizzo di porte non standard per SSH. È necessario autorizzare la nuova porta e aprirla nel firewall:

bash
sudo semanage port -a -t ssh_port_t -p tcp 5555
sudo firewall-cmd --permanent --add-port=5555/tcp
sudo firewall-cmd --reload

Riavvio del servizio SSH

Una volta fatto, riavviare il servizio SSH per applicare la modifica:

bash
sudo systemctl restart sshd

Nel video sotto è possibile vedere il processo, testato su Fedora 43, in cui viene cambiata la porta SSH e configurato il firewall per consentire l’accesso al server sulla nuova porta.

Attenzione

Prima di chiudere la sessione corrente, aprire un nuovo terminale e verificare di riuscire ad accedere al server sulla nuova porta: ssh -p 5555 utente@indirizzo-server. Se la connessione funziona è possibile proseguire. In caso contrario, la sessione ancora aperta permetterà di correggere la configurazione senza restare chiusi fuori.

Docker Compose

Dopo aver installato Docker Engine , Docker Compose e modificato la porta SSH, è possibile procedere con l’installazione di Forgejo. La configurazione proposta sotto è composta da un file docker-compose.yml, che definisce in modo dichiarativo i due servizi necessari (il server Forgejo e il database PostgreSQL), e da un file .env per le variabili d’ambiente.

Creiamo il File Docker Compose

Il file docker-compose.yml qui sotto configura l’intero stack di Forgejo. Una volta completata l’installazione, il server sarà raggiungibile sulla porta 3000 per la Web UI e sulla porta 22 per le operazioni Git via SSH. I due servizi comunicano attraverso una rete Docker dedicata e il server si avvia solo dopo che il database è pronto, grazie all’healthcheck configurato su PostgreSQL.

yaml
services:
  forgejo_server:
    image: codeberg.org/forgejo/forgejo:14
    container_name: Forgejo_Server
    environment:
      USER_UID: 1000
      USER_GID: 1000
      FORGEJO__database__DB_TYPE: postgres
      FORGEJO__database__HOST: forgejo_db:5432
      FORGEJO__database__NAME: ${FORGEJO_DB_NAME}
      FORGEJO__database__USER: ${FORGEJO_DB_USER}
      FORGEJO__database__PASSWD: ${FORGEJO_DB_PASSWORD}
    restart: unless-stopped
    networks:
      - forgejo
    volumes:
      - ./forgejo:/data
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "3000:3000"
      - "22:22"
    depends_on:
      forgejo_db:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/api/healthz"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 30s

  forgejo_db:
    image: postgres:14
    container_name: Forgejo_DB
    restart: unless-stopped
    environment:
      POSTGRES_USER: ${FORGEJO_DB_USER}
      POSTGRES_PASSWORD: ${FORGEJO_DB_PASSWORD}
      POSTGRES_DB: ${FORGEJO_DB_NAME}
    networks:
      - forgejo
    volumes:
      - ./postgres:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${FORGEJO_DB_USER} -d ${FORGEJO_DB_NAME}"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

networks:
  forgejo:
    external: false

Definiamo i Container della Configurazione

  • Il container forgejo_server è il cuore dell’applicazione e si occupa di gestire l’interfaccia web, le API, i repository Git e il server SSH integrato. Il volume montato in ./forgejo contiene tutti i dati dell’istanza: repository, configurazione, avatar e file LFS. Le variabili FORGEJO__database__* configurano la connessione al database tramite la convenzione di Forgejo con doppio underscore, che permette di impostare qualsiasi parametro di app.ini direttamente via environment. Il servizio si avvia solo dopo che il database ha superato l’healthcheck, evitando errori di connessione al primo avvio.
  • Il container forgejo_db fornisce lo storage persistente tramite PostgreSQL (al momento della scrittura della guida, la documentazione ufficiale di Forgejo utilizza la versione 14 di PostgreSQL). I dati del database vengono salvati in ./postgres per garantire la persistenza tra i riavvii del container. L’healthcheck utilizza pg_isready per verificare che PostgreSQL sia pronto ad accettare connessioni prima di far partire il server Forgejo. La rete forgejo con external: false isola i due servizi in una rete Docker dedicata, non raggiungibile dall’esterno se non attraverso le porte esplicitamente mappate.

Creiamo il File .env

Il file .env contiene le credenziali del database condivise tra i due servizi. È importante personalizzare la password con una stringa sicura e non lasciare mai i valori di esempio in produzione.

bash
FORGEJO_DB_NAME=forgejo
FORGEJO_DB_USER=forgejo
FORGEJO_DB_PASSWORD=cambiami_con_una_password_sicura

Quale Database Scegliere

Forgejo supporta tre motori di database, ognuno adatto a scenari diversi. In questa guida abbiamo utilizzato PostgreSQL, ma nella documentazione ufficiale sono presenti le configurazioni Docker dedicate ad ogni database.

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, ed è il database meglio supportato dall’ecosistema Forgejo.

In questa guida abbiamo scelto PostgreSQL perché gestisce le connessioni concorrenti in modo nativo, senza i limiti di locking che caratterizzano SQLite. Questo è particolarmente rilevante in uno scenario Docker dove più processi possono accedere al database contemporaneamente: la Web UI, il server SSH, eventuali webhook e, se abilitati, i runner delle Forgejo Actions.

Nella scelta del database è importante valutare anche quanti strumenti accedono contemporaneamente a Forgejo, anche nel caso di un singolo sviluppatore. Se si utilizzano agenti di coding (Claude Code, Cursor, Copilot, Gemini…) o pipeline CI/CD che interagiscono con i repository in parallelo, le scritture concorrenti sul database aumentano sensibilmente.

Primo Avvio

Una volta installato il tutto, il servizio sarà disponibile alla porta 3000 del server e apparirà una schermata che invita a finalizzare l’installazione, andando a specificare il database, l’utente admin e le coordinate SMTP per la posta. Le opzioni disponibili sono molte, quindi non andremo a documentare tutte le varie specifiche.

Schermata di configurazione iniziale di Forgejo

Le informazioni relative al database sono già inserite in quanto Forgejo ha preso tutto dalla configurazione Docker. Una volta finalizzata l’installazione, il sistema sarà disponibile e attivo.

Forgejo installato con successo

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

Avendo spostato OpenSSH sulla porta 5555, è 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 5555
    User <utente>

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

Troubleshooting

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

bash
docker logs -f Forgejo_Server

Se l’interfaccia web non è raggiungibile sulla porta 3000, verificare che entrambi i container siano in esecuzione e che gli healthcheck siano passati:

bash
docker ps

Un problema frequente riguarda la connessione SSH. Se git clone sulla porta 22 non funziona, verificare che Docker abbia effettivamente il bind sulla porta e che OpenSSH di sistema non la stia occupando:

bash
ss -tlnp | grep :22

Se il risultato mostra sshd invece di docker-proxy, significa che OpenSSH non è stato spostato correttamente sulla porta 5555. In tal caso, rivedere la sezione Configurazione del Protocollo SSH .

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

bash
docker logs Forgejo_DB

Per verificare che il database sia raggiungibile dall’interno del container Forgejo:

bash
docker exec Forgejo_Server pg_isready -h forgejo_db -U forgejo

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. Se nel file di configurazione app.ini l’opzione COOKIE_SECURE è impostata a true, i cookie vengono inviati solo su connessioni cifrate e senza un reverse proxy con certificato valido il browser li scarta silenziosamente.