Creato da Alberto Ferrer · self-hosted, in produzione

Un GitHub creato da me.
Ecco com'è fatto dentro.

surfagit è il server Git su cui vivono i miei progetti: Forgejo self-hosted, blindato a più livelli, con CI e revisione AI ad ogni push e un backup 3-2-1 con restore verificato. Questo è il viaggio, strato per strato — dall'accesso fino al disco.

0strati di difesa
3-2-1strategia di backup
0dipendenza da GitHub
0codice di mia proprietà
scorri per entrare
Il viaggio

Sette fermate, dall'esterno verso il cuore del sistema.

A destra c'è la mappa: la torre di strati che una richiesta attraversa. Man mano che scorri, si illumina la fermata in cui ti trovi. Ogni tappa ha la spiegazione in chiaro — e, per chi vuole, i dettagli tecnici da aprire.

1Accesso & identità

Nessuna pagina di login. Eppure nessuno entra.

Lo strato di rete · Tailscale

surfagit non è esposto su internet pubblico. Vive dentro la mia rete privata (una tailnet cifrata), raggiungibile solo dai miei dispositivi — laptop e telefono. Chi non è nella rete non vede nemmeno che esiste.

Dentro la rete, l'accesso è ancora più fluido: non esiste una pagina di login. L'identità arriva già verificata dal livello di rete, e il server la associa al mio account. Comodo come un servizio cloud, privato come una cassaforte.

  • Registrazione disattivata e vista pubblica bloccata: il server è privato per default.
  • Solo HTTPS con certificato reale; nessun avviso di sicurezza, nessuna scorciatoia.
  • Il server ascolta solo in locale: è la rete privata a fare da porta d'ingresso blindata.
Dettagli tecnici Identità via reverse-proxy, non password

Il proxy della rete privata inietta l'identità dell'utente in un header fidato e sovrascrive qualunque header fornito dal client — quindi non è falsificabile. Forgejo è configurato in modalità reverse-proxy auth e associa quell'identità all'account esistente tramite email (l'auto-registrazione resta off, così un'identità sconosciuta non crea account). L'account admin con password resta come fallback, ma sulla rete privata la pagina di login è scavalcata.

# il proxy sovrascrive gli header → niente spoofing
REVERSE_PROXY_AUTHENTICATION = on
ENABLE_REVERSE_PROXY_EMAIL = true # match per email
DISABLE_REGISTRATION = true
REQUIRE_SIGNIN_VIEW = true # privato per default

Git funziona su HTTPS con access token revocabili (SSH del server disabilitato → una superficie in meno).

2Il cancello di sicurezza

Il segreto che provi a pushare non entra. Punto.

Controllo server-side · pre-receive

Questa è la fermata di cui vado più fiero. Ad ogni push, prima ancora che il codice tocchi il repository, un controllo lato server lo ispeziona. È un hook pre-receive: gira sul server, non sul mio computer, quindi non si può aggirare — nemmeno da riga di comando, nemmeno per errore.

  • Scansione segreti (blocco duro): se compare una chiave API, un token, una password, il push viene respinto. Non un warning: un no.
  • Analisi di sicurezza del codice: pattern pericolosi bloccano su severità ERROR, il resto avvisa.
  • Allowlist auditabile: i falsi positivi si silenziano solo con un file versionato nel repo — tracciabile in git, non una scorciatoia nascosta.

E i repository nuovi? Vengono protetti da soli: un processo periodico ricollega l'hook a ogni repo, così nessuno nasce senza cancello.

Provalo — cosa succede al git push?
Dettagli tecnici Gitleaks + Semgrep, fail-closed sui segreti

Uno script centrale è collegato in ogni repo come primo hook pre-receive. Materializza l'albero al tip del push e lo passa a due scanner:

gitleaks → BLOCCO semgrep ERROR → BLOCCO semgrep altro → warn

# gitleaks gira DENTRO l'albero → rispetta un .gitleaksignore committato
cd "$tree" && gitleaks detect --no-git --source .
# exit ≠ 0 → push REJECTED

Scelte di design: gitleaks mancante = fail-closed (se lo scanner non parte, blocco — non lascio passare per comodità). L'errore dello scanner semantico invece è fail-open (avvisa, non blocca) per non fermare il lavoro su un suo bug. L'allowlist accetta solo i fingerprint file:rule:line esatti, committati nella root: si vede in git chi ha silenziato cosa. Interruttore di emergenza documentato per i casi limite.

3CI + revisione AI

Ogni push viene compilato e riletto. Anche da un'AI.

Integrazione continua · Forgejo Actions

Superato il cancello, il codice entra e parte la pipeline. Forgejo ha una CI integrata (le Actions, compatibili con quelle di GitHub) che gira su un runner a casa mia — niente minuti a pagamento nel cloud, niente codice che esce.

  • Build check adattivo: riconosce il linguaggio del repo e fa il check giusto (compilazione, type-check, audit delle dipendenze).
  • Revisione AI ad ogni push: Claude legge il diff e dà un verdetto. PASS o FAIL — e il FAIL è bloccante.
  • Pallini di stato inline: nella lista repo, ogni riga mostra pillole colorate (build, AI review, deploy) senza aprire nulla.
Dettagli tecnici Verdetto AI robusto + niente GitHub nella supply chain

Le Actions sono tirate dal mirror di Forgejo, non da GitHub: la supply chain della CI resta fuori da GitHub, coerente con la mia scelta di ownership. Il runner gira in host mode con l'ambiente Node corretto nel PATH.

La revisione AI legge solo l'ultima riga VERDICT: dell'output (non un grep dell'intero log, che darebbe falsi positivi quando il diff stesso contiene quella stringa). Nessun verdetto chiaro o errore del tool → fail-open (warning verde), così un imprevisto dell'AI non blocca il lavoro.

VERDICT: PASS # → check verde
VERDICT: FAIL # → check rosso, job in errore

Limite noto (segnalato dall'AI stessa): la review gira su un diff controllabile dall'attaccante, quindi in teoria è sensibile a prompt-injection. Per questo il vero blocco duro è il cancello pre-receive; la review AI è uno strato bonus, non l'unica linea.

4Osservabilità

Lo stato di ogni progetto, a colpo d'occhio.

Visibilità · pillole di stato inline

Forgejo, di suo, non mostra lo stato della CI nella lista dei repository. Me lo sono aggiunto: ogni riga della lista mostra pillole colorate — build, revisione AI, deploy in produzione — così capisco al volo cosa è verde e cosa no, senza aprire un singolo progetto.

  • Punto di iniezione ufficiale: uso il template previsto da Forgejo, così sopravvive agli aggiornamenti.
  • Aggiornamento periodico: un generatore interroga l'API e pubblica lo stato ogni pochi minuti.
  • Deploy tracciato: dopo un deploy riuscito, una pillola deploy/production punta al sito live.
5Backup 3-2-1

Se domani il laptop prende fuoco, non perdo niente.

Disaster recovery · mirror + restic

Un server Git senza backup è una bomba a orologeria. Qui la regola è la 3-2-1: tre copie, due supporti, una fuori sede. E soprattutto: il restore è stato testato davvero, non solo il salvataggio.

  • Mirror off-site orario: ogni repository viene replicato su un server esterno, ogni ora.
  • Backup cifrato e versionato (restic): deduplicato, compresso, con storia — non solo l'ultima versione. Include tutti i metadati: issue, PR, utenti.
  • Trigger intelligente: il backup parte quando la macchina è a riposo, subito dopo le sessioni di lavoro.
  • Verifica d'integrità settimanale e mensile: il backup è recuperabile, non solo scrivibile.
Dettagli tecnici Copia 3, retention, restore verificato

Copia 1 = laptop. Copia 2 = repository restic cifrato off-site (versionato, dedup). Copia 3 = mirror git orario off-site, con meccanismo indipendente. Il mirror è solo add/update: un repo cancellato per errore resta nel backup.

Retention a scaglioni (ultimi N, orari, giornalieri, settimanali, mensili) con prune automatico. Integrità: restic check strutturale settimanale + verifica a lettura di un campione mensile. Il dump completo notturno (repo + LFS + allegati) rende il restore turnkey.

La chiave di cifratura è l'unico segreto irrecuperabile — custodita off-device. Un test di restore ha confermato i dati byte-identici e il database valido. La sola parte mancante, opzionale, è una quarta copia su un secondo provider per la piena indipendenza.

6Sempre acceso

Un server casalingo che non dorme mai.

Affidabilità · always-on

Il server gira su un laptop che fa da home server sempre acceso: lo raggiungo dal telefono in qualsiasi momento. Perché funzioni davvero 24/7, la sospensione è disattivata a ogni livello — chiusura del coperchio, inattività, tasto di sospensione. Un solo evento di sleep, e il telefono perderebbe l'accesso senza preavviso.

  • Sospensione bloccata alla radice: ogni trigger passa da un percorso disattivato, quindi nulla può addormentare la macchina.
  • I servizi sopravvivono al riavvio e restano attivi anche senza login attivo.
7Il guardiano termico

Un bug lo surriscaldava. Ora un watchdog lo salva.

Resilienza · watchdog CPU

La versione di Forgejo che uso ha un difetto intermittente: ogni tanto uno dei suoi thread parte in loop a vuoto e satura la CPU — senza nessuna richiesta reale in corso. Su un laptop, senza il raffreddamento di un server, questo scalda parecchio. Un semplice riavvio azzera tutto.

Così ho scritto un guardiano: campiona la CPU di Forgejo e, se resta anomala, lo riavvia. Con una regola d'oro — mai durante un'operazione git.

  • Diagnosi mirata: distingue il loop a vuoto dal lavoro vero (un push carica processi git figli; il bug no).
  • Push-safe: se c'è un git in corso, il watchdog rinvia. Meglio caldo cinque minuti che un push interrotto.
Dettagli tecnici Firma diagnostica + bias verso il rinvio

Un timer periodico campiona la CPU del processo su una finestra di pochi secondi. Sopra soglia = spin-loop; riavvio del servizio, che riazzera l'anomalia all'istante. La firma che distingue il bug dal lavoro reale: durante lo spin non ci sono processi git figli — il lavoro vero (push/clone/gc) li mostra sempre.

Prima di riavviare, il guardiano verifica che non ci sia alcuna attività git viva e, nel dubbio, rinvia al ciclo dopo. Il bias è intenzionale verso la sicurezza del dato, non verso la temperatura. La cura definitiva sarà aggiornare Forgejo oltre questa versione.

La scelta

Perché Forgejo, e perché self-hosted per i miei progetti.

Non è nostalgia da smanettone. È una scelta di proprietà: il codice dei miei clienti e dei miei prodotti non deve dipendere da una piattaforma che non controllo.

Le feature ufficiali

Cosa mette sul piatto Forgejo, di suo.

  • Open source, community-driven. Fork di Gitea guidato da una no-profit, licenza copyleft: nessun lock-in, nessuna telemetria.
  • Binario unico e leggero. Un solo eseguibile Go, gira anche su un laptop; database SQLite, Postgres o MySQL.
  • Forgejo Actions. CI/CD integrata e compatibile con le GitHub Actions: le pipeline si portano dietro quasi senza modifiche.
  • Il set completo. Issue, pull request, wiki, release, registry pacchetti, LFS, webhook, token a grana fine, mirroring integrato.
  • Federazione in arrivo. Progettato per federare (ForgeFed/ActivityPub): forge diverse che si parlano, senza un padrone unico.

Le mie ragioni

Perché, per i miei progetti, era la scelta giusta.

  • Proprietà totale del codice. Ho deciso di uscire da GitHub: repository, CI e deploy stanno tutti su infrastruttura mia.
  • Estensibile fino in fondo. Il cancello di sicurezza, la review AI, i pallini di stato, il watchdog — li ho aggiunti io, ai miei standard. Su una piattaforma chiusa non potrei.
  • Costo prevedibile. CI senza minuti a consumo, storage senza fatture a sorpresa: gira su hardware che ho già.
  • Privacy dei clienti. Il codice non lascia la mia rete. Per chi mi affida un progetto, è una garanzia concreta.
  • Padronanza dello stack. Costruire e mantenere questo sistema è, esso stesso, la prova del mestiere: design → develop → secure → deploy → maintain.
La prova

Il sistema è vivo: ci lavoro ogni giorno.

Non è una demo lasciata lì. Da quando ho spostato tutto su surfagit, ogni riga di codice passa da qui: commit, push, CI verde, deploy. Questo è lo storico reale di versioning: ogni riquadro è un giorno, più è acceso più commit ci sono. Dati presi direttamente dai miei repository, non decorativi.

Finestra: da maggio 2026, da quando ho portato repository, CI e deploy su infrastruttura mia.

menopiù
0commit tracciati
0repository versionati
0commit nel picco (15 mag)
0su rete mia, zero GitHub
0strati, dall'accesso al disco
0segreti che superano il gate
3-2-1backup con restore testato
1binario, sul mio hardware
Webmastery · Alberto Ferrer

Questo livello di controllo, sui tuoi progetti.

Progetto, sviluppo, metto in sicurezza, faccio il deploy e mantengo sistemi in produzione — dall'infrastruttura al prodotto. Se ti serve qualcuno che possieda l'intera catena, parliamone.

Nota: surfagit è un sistema privato, in produzione sulla mia rete personale — non è pubblicamente accessibile e i dettagli sensibili (hostname, indirizzi, credenziali) sono volutamente omessi. Questa pagina racconta l'architettura e le scelte, non espone la macchina.