Una piattaforma Git in un solo binario Rust.

Repository, merge request con revisione in linea, ticket, wiki, release, webhook firmati e un motore CI/CD. Un processo, un PostgreSQL, sul tuo server.

Apri FerrisGit
$docker compose up -d --build

Un solo binario e un database. Nessun account presso terzi, nessuna telemetria inviata da nessuna parte. Guarda com'è fatto.

Illustrazione di una merge request in FerrisGit, dal push al merge: un push su HTTPS crea la richiesta, una revisora suggerisce una modifica su una riga, l'autore la applica con un clic, la revisora approva, la richiesta viene unita. Il merge avvia la pipeline del repository: format e clippy vengono eseguiti, poi test, e tutti e tre riescono.

In cifre

1
binario Rust serve l'API REST, Git su HTTP e l'interfaccia web
1
PostgreSQL 18 conserva ogni record; i repository vivono su disco
5
crate Cargo, in architettura esagonale
173
route REST sotto /api, ciascuna documentata
3
fattori di accesso (TOTP, passkey, codici di recupero); l'MFA è obbligatoria
2
motori di esecuzione: runner Docker o Pod Kubernetes

Cosa ottieni, come lo mostra l'interfaccia

Ogni riquadro è un pezzo del prodotto reale. L'interfaccia per ora è in francese; cinque lingue sono previste per la 0.2.

src/webhooks/dispatch.rs:48 Aperto

CA

camille · 2 min

Backoff esponenziale, così un endpoint instabile smette di essere martellato.

Modifica suggerita

La revisione sul diff

Un commento resta legato alla sua riga. Chi revisiona può scrivere un suggerimento che l'autore applica con un clic, come commit. Le approvazioni vengono contate, i conflitti rilevati.

Una pipeline a ogni push

Dopo ogni push, FerrisGit legge il file sul branch predefinito e crea una pipeline. Gli stage sono barriere, needs sono dipendenze; i job girano in container Docker tramite un piccolo runner, o come Pod Kubernetes.

Ticket, in lista o su una board

Etichette, milestone, assegnatari e quattro stati. Trascina una scheda per cambiarne lo stato, o usa il menu della scheda da tastiera.

Azione Lett. Collab. Manut.
Sfogliare, clonare, leggere
Push, aprire ticket e richieste, revisionare
Unire, pubblicare release, impostazioni, collaboratori

Tre ruoli, per repository o per gruppo

Un ruolo assegnato su un gruppo vale per tutto ciò che contiene. Vince il ruolo più alto.

Webhook firmati

Dodici eventi su merge request, ticket, pipeline e collaboratori. Ogni invio porta una firma HMAC-SHA256 del corpo grezzo; il segreto è cifrato a riposo.

Pagine pubbliche, senza account

I visitatori sfogliano catalogo, README, file, commit e release dei repository pubblici, e li clonano. Un interruttore di amministrazione spegne le pagine pubbliche.

Autenticazione a più fattori, per tutti

Nessun account può farne a meno. App di autenticazione (TOTP), passkey (WebAuthn) e dieci codici di recupero monouso.

L'elenco completo delle funzionalità

Un push diventa una pipeline

Descrivi i job in .ferrisgit-ci.yml alla radice del repository. Dopo ogni push riuscito, FerrisGit legge il file sul branch predefinito e crea una pipeline. Attiva l'interruttore per vedere cosa fa lo scheduler quando un job fallisce.

.ferrisgit-ci.yml
stages: [lint, test]

jobs:
  format:
    stage: lint
    image: rust:1
    script:
      - rustup component add rustfmt
      - cargo fmt --all -- --check

  clippy:
    stage: lint
    image: rust:1
    script:
      - rustup component add clippy
      - cargo clippy --all-targets -- -D warnings

  test:
    stage: test
    image: rust:1
    needs: [format, clippy]
    script:
      - cargo test --all-targets

Pipeline riuscita

lint

formatriuscito
clippyriuscito

test

testriuscito

format e clippy partono insieme; test dichiara needs: [format, clippy] e parte quando entrambi sono riusciti.

Due modi di eseguire un job
Runner Docker: un piccolo binario ferrisgit-runner interroga il server ed esegue ogni job in un container. Oppure Kubernetes: il server crea un Pod per job nel tuo cluster.
Gli errori si vedono
Un file presente ma non valido crea una pipeline fallita che porta il messaggio del parser, mostrato nell'interfaccia.
Variabili e cache
Variabili CI per repository, cifrate a riposo con AES-256-GCM (runner Docker). Cache per job con Kubernetes.

Il riferimento di .ferrisgit-ci.yml (in francese)

Due minuti per il self-hosting

FerrisGit è un'immagine container con PostgreSQL accanto. Provalo con Docker Compose, installa il chart Helm su Kubernetes, o avvialo dai sorgenti.

Docker Compose

Avviare lo stack con Docker Compose
git clone https://github.com/Masmarino/FerrisGit.git
cd FerrisGit
cp .env.example .env
# set POSTGRES_PASSWORD, JWT_SECRET, SETTINGS_ENCRYPTION_KEY and the admin password in .env
docker compose up -d --build

Compose costruisce l'immagine dai sorgenti. Per usare l'immagine pubblicata, sostituisci build: . con image: masmarino/ferrisgit:0.1.1 in docker-compose.yml.

Guida all'installazione (in francese)

Chart Helm

Installare il chart su Kubernetes
git clone https://github.com/Masmarino/FerrisGit.git
cd FerrisGit
helm upgrade --install ferrisgit ./helm/ferrisgit \
  --namespace ferrisgit --create-namespace \
  --set image.tag=0.1.1 \
  --set ingress.host=git.example.com \
  --set-string ferrisgit.trustedProxyCidrs=10.42.0.0/16
kubectl -n ferrisgit rollout status deployment/ferrisgit

Se lasciati vuoti, il chart genera la password del database, JWT_SECRET, SETTINGS_ENCRYPTION_KEY e la password del primo amministratore nel Secret ferrisgit-secrets. La release deve chiamarsi ferrisgit.

Deployment su Kubernetes (in francese)

Dai sorgenti

Avviare backend e applicazione web in locale
git clone https://github.com/Masmarino/FerrisGit.git
cd FerrisGit
cp .env.example .env          # then set real secrets
./scripts/dev.sh              # PostgreSQL via Compose, cargo run on :8080, ng serve on :4201

Servono rustup, Node.js 26, Docker con Compose e git nel PATH. Lo script avvia PostgreSQL, applica le migrazioni e lancia il backend sulla porta 8080 e il server di sviluppo Angular sulla porta 4201.

Guida all'installazione (in francese)

Com'è fatto

Un processo, cinque crate, un'architettura esagonale: il dominio non sa nulla del database, gli adattatori non sanno nulla dei casi d'uso.

Architettura di un'istanza di FerrisGitDisegno isometrico. Un client Git e un browser parlano con un solo binario Rust, ferrisgit-api, composto dai crate api, application, domain e infrastructure. Il binario conserva i dati in PostgreSQL e in repository Git su disco, ed esegue i job delle pipeline tramite un ferrisgit-runner su un host Docker o come Pod in un cluster Kubernetes. Una linea arancione segue un push fino ai suoi job. Sette cerchi numerati rimandano ai riquadri della pagina.api application domain infrastructure ferrisgit-runner ferrisgit-api: un solo binario ferrisgit-runner Client Git HTTPS, utente + token ancora niente SSH Browser con login, o anonimo sulle pagine pubbliche api API REST, Git su HTTP, interfaccia web domain entità e porte, senza I/O application casi d'uso infrastructure adattatori: PostgreSQL, git, Docker, Kubernetes, SMTP, webhook PostgreSQL account, issue, pipeline; le migrazioni partono all'avvio Repository Git su disco, wiki incluse Host Docker il runner interroga ogni 5 s di default, un job alla volta, in un container Cluster Kubernetes un Pod per job, creato dal server git push pipeline creata job interroga i job

Fig. 1 Un'istanza. La linea arancione segue un push dal client ai job che avvia.

  • richiesta o archiviazione
  • un push, fino ai suoi job
  • il runner interroga
  • un riquadro numerato di questa pagina
  1. ferrisgit-domainEntità, value object e le porte da cui dipende il resto. Nessun I/O.
  2. ferrisgit-applicationI casi d'uso. Dipende solo dal dominio, testato con finti in memoria.
  3. ferrisgit-infrastructureAdattatori: PostgreSQL (sqlx), Git (gix e il binario git), SMTP, Kubernetes, Argon2, AES-GCM, JWT.
  4. ferrisgit-apiIl server axum: API REST sotto /api, Git smart HTTP, il bundle Angular. È lui il binario.
  5. ferrisgit-runnerIl runner Docker autonomo.

Il codice sorgente su GitHub

Sicurezza e i tuoi dati

Ciò che protegge un'istanza, con il suo nome preciso. I dati non lasciano mai il tuo server.

L'autenticazione a più fattori è obbligatoria
Un account senza fattore attivo passa dalla configurazione prima di poter fare qualsiasi altra cosa. TOTP, passkey e codici di recupero.
Password con hash Argon2
Un sale per password. Un nome utente sconosciuto costa tanto calcolo quanto una password sbagliata, e riceve la stessa risposta.
Segreti cifrati con AES-256-GCM
Variabili CI, segreti dei webhook, password SMTP e segreti TOTP, sotto SETTINGS_ENCRYPTION_KEY.
Token per Git, mai password
Git su HTTPS si autentica con un token di accesso personale, conservato con hash: il server non può rileggerlo.
Un registro di audit
Accessi falliti, accessi Git rifiutati, reset di password, promozioni e reset dell'MFA da parte di un amministratore vengono registrati come eventi.
Niente cookie, header rigorosi
Le sessioni sono JWT. Ogni risposta porta una Content-Security-Policy, X-Frame-Options: DENY, e le route di accesso sono limitate per IP.
I tuoi dati, sul tuo server
PostgreSQL e una directory di repository, entrambi da salvare come preferisci. L'immagine gira con un utente senza privilegi su un filesystem in sola lettura.

La pagina Sicurezza della documentazione (in francese)

Dove sta andando

Cinque versioni, nessuna rilasciata. Una voce viene spuntata solo quando è rilasciata.

  1. 0.2Branch protetti, controlli, cinque linguePrevisto
  2. 0.3Un motore di analisi: segreti e dipendenzePrevisto
  3. 0.4Quality gate e cruscottoPrevisto
  4. 0.5Qualità del codice: metriche, regole, coperturaPrevisto
  5. 0.6Analisi di sicurezza e ArtiFerrisPrevisto

Provalo, poi avvia il tuo.

L'istanza pubblica mostra il prodotto. La tua istanza custodisce il tuo codice.