Una plataforma Git en un solo binario Rust.

Repositorios, merge requests con revisión en línea, incidencias, wikis, releases, webhooks firmados y un motor de CI/CD. Un proceso, un PostgreSQL, en tu propio servidor.

Abrir FerrisGit
$docker compose up -d --build

Un solo binario y una base de datos. Ninguna cuenta en un servicio de terceros, ninguna telemetría enviada a ninguna parte. Ver cómo está hecho.

Ilustración de una merge request en FerrisGit, del push a la fusión: un push por HTTPS crea la solicitud, una revisora sugiere un cambio en una línea, el autor lo aplica con un clic, la revisora aprueba, la solicitud se fusiona. La fusión arranca la pipeline del repositorio: format y clippy se ejecutan, luego test, y los tres terminan bien.

En cifras

1
binario Rust sirve la API REST, Git sobre HTTP y la interfaz web
1
PostgreSQL 18 guarda cada registro; los repositorios viven en disco
5
crates de Cargo, en arquitectura hexagonal
173
rutas REST bajo /api, cada una documentada
3
factores de acceso (TOTP, passkeys, códigos de respaldo); la MFA es obligatoria
2
motores de ejecución: runners Docker o Pods de Kubernetes

Lo que obtienes, tal como lo muestra la interfaz

Cada bloque es un trozo del producto real. La interfaz está en francés por ahora; cinco idiomas están previstos para la 0.2.

src/webhooks/dispatch.rs:48 Abierto

CA

camille · 2 min

Espera exponencial, para dejar de martillear un endpoint inestable.

Cambio sugerido

La revisión sobre el diff

Un comentario queda ligado a su línea. Quien revisa puede escribir una sugerencia que el autor aplica con un clic, como commit. Las aprobaciones se cuentan, los conflictos se detectan.

Una pipeline en cada push

Tras cada push, FerrisGit lee el archivo en la rama predeterminada y crea una pipeline. Las etapas son barreras, needs son dependencias; los trabajos corren en contenedores Docker mediante un pequeño runner, o como Pods de Kubernetes.

Incidencias, en lista o en tablero

Etiquetas, hitos, asignados y cuatro estados. Arrastra una tarjeta para cambiar su estado, o usa el menú de la tarjeta desde el teclado.

Acción Lect. Colab. Mant.
Navegar, clonar, leer
Push, abrir incidencias y solicitudes, revisar
Fusionar, publicar releases, ajustes, colaboradores

Tres roles, por repositorio o por grupo

Un rol concedido en un grupo se aplica a todo lo que contiene. Gana el rol más alto.

Webhooks firmados

Doce eventos sobre merge requests, incidencias, pipelines y colaboradores. Cada envío lleva una firma HMAC-SHA256 de su cuerpo en bruto; el secreto se cifra en reposo.

Páginas públicas, sin cuenta

Los visitantes recorren el catálogo, el README, los archivos, los commits y las releases de los repositorios públicos, y los clonan. Un interruptor de administración apaga las páginas públicas.

Autenticación multifactor, para todos

Ninguna cuenta puede saltársela. Aplicaciones de autenticación (TOTP), passkeys (WebAuthn) y diez códigos de respaldo de un solo uso.

La lista completa de funciones

Un push se convierte en pipeline

Describe los trabajos en .ferrisgit-ci.yml en la raíz del repositorio. Tras cada push correcto, FerrisGit lee el archivo en la rama predeterminada y crea una pipeline. Activa el interruptor para ver qué hace el planificador cuando un trabajo falla.

.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 superada

lint

formatcorrecto
clippycorrecto

test

testcorrecto

format y clippy arrancan juntos; test declara needs: [format, clippy] y arranca cuando ambos han terminado bien.

Dos formas de ejecutar un trabajo
Runners Docker: un pequeño binario ferrisgit-runner consulta al servidor y ejecuta cada trabajo en un contenedor. O Kubernetes: el servidor crea un Pod por trabajo en tu clúster.
Los errores se muestran
Un archivo presente pero inválido crea una pipeline fallida que lleva el mensaje del analizador, mostrado en la interfaz.
Variables y cachés
Variables de CI por repositorio, cifradas en reposo con AES-256-GCM (runners Docker). Cachés por trabajo con Kubernetes.

La referencia de .ferrisgit-ci.yml (en francés)

Dos minutos para autoalojarlo

FerrisGit es una imagen de contenedor con PostgreSQL al lado. Pruébalo con Docker Compose, instala el chart de Helm en Kubernetes, o ejecútalo desde el código.

Docker Compose

Arrancar la pila 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 construye la imagen desde el código. Para usar la imagen publicada, sustituye build: . por image: masmarino/ferrisgit:0.1.1 en docker-compose.yml.

Guía de instalación (en francés)

Chart de Helm

Instalar el chart en 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

Si se dejan vacíos, el chart genera la contraseña de la base de datos, JWT_SECRET, SETTINGS_ENCRYPTION_KEY y la contraseña del primer administrador en el Secret ferrisgit-secrets. La release debe llamarse ferrisgit.

Despliegue en Kubernetes (en francés)

Desde el código

Ejecutar el backend y la aplicación web en local
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

Hacen falta rustup, Node.js 26, Docker con Compose y git en el PATH. El script arranca PostgreSQL, aplica las migraciones y ejecuta el backend en el puerto 8080 y el servidor de desarrollo de Angular en el puerto 4201.

Guía de instalación (en francés)

Cómo está hecho

Un proceso, cinco crates, una arquitectura hexagonal: el dominio no sabe nada de la base de datos, los adaptadores no saben nada de los casos de uso.

Arquitectura de una instancia de FerrisGitDibujo isométrico. Un cliente Git y un navegador hablan con un solo binario Rust, ferrisgit-api, formado por los crates api, application, domain e infrastructure. El binario guarda sus datos en PostgreSQL y en repositorios Git en disco, y ejecuta los trabajos de las pipelines con un ferrisgit-runner en un host Docker o como Pods en un clúster Kubernetes. Una línea naranja sigue un push hasta sus trabajos. Siete círculos numerados llevan a los bloques de la página.api application domain infrastructure ferrisgit-runner ferrisgit-api: un solo binario ferrisgit-runner Cliente Git HTTPS, usuario + token aún sin SSH Navegador con sesión, o anónimo en las páginas públicas api API REST, Git sobre HTTP, interfaz web domain entidades y puertos, sin E/S application casos de uso infrastructure adaptadores: PostgreSQL, git, Docker, Kubernetes, SMTP, webhooks PostgreSQL cuentas, incidencias, pipelines; las migraciones se aplican al arrancar Repositorios Git en disco, wikis incluidas Host Docker el runner consulta cada 5 s por defecto, un job a la vez, en un contenedor Clúster Kubernetes un Pod por job, creado por el servidor git push pipeline creado jobs consulta jobs

Fig. 1 Una instancia. La línea naranja sigue un push desde el cliente hasta los trabajos que arranca.

  • petición o almacenamiento
  • un push, hasta sus trabajos
  • el runner consulta
  • un bloque numerado de esta página
  1. ferrisgit-domainEntidades, objetos de valor y los puertos de los que depende el resto. Sin E/S.
  2. ferrisgit-applicationLos casos de uso. Depende solo del dominio, probado contra dobles en memoria.
  3. ferrisgit-infrastructureAdaptadores: PostgreSQL (sqlx), Git (gix y el binario git), SMTP, Kubernetes, Argon2, AES-GCM, JWT.
  4. ferrisgit-apiEl servidor axum: API REST bajo /api, Git smart HTTP, el bundle de Angular. Este es el binario.
  5. ferrisgit-runnerEl runner Docker independiente.

El código fuente en GitHub

Seguridad y tus datos

Lo que protege una instancia, nombrado con precisión. Los datos nunca salen de tu servidor.

La autenticación multifactor es obligatoria
Una cuenta sin ningún factor activo pasa por la configuración antes de poder hacer cualquier otra cosa. TOTP, passkeys y códigos de respaldo.
Contraseñas con hash Argon2
Una sal por contraseña. Un nombre de usuario desconocido cuesta tanto cálculo como una contraseña errónea, y recibe la misma respuesta.
Secretos cifrados con AES-256-GCM
Variables de CI, secretos de webhooks, contraseña SMTP y secretos TOTP, bajo SETTINGS_ENCRYPTION_KEY.
Tokens para Git, nunca contraseñas
Git sobre HTTPS se autentica con un token de acceso personal, guardado con hash: el servidor no puede volver a leerlo.
Un registro de auditoría
Inicios de sesión fallidos, accesos Git denegados, restablecimientos de contraseña, promociones y restablecimientos de MFA por un administrador se registran como eventos.
Sin cookies, cabeceras estrictas
Las sesiones son JWT. Cada respuesta lleva una Content-Security-Policy, X-Frame-Options: DENY, y las rutas de acceso tienen límite de peticiones por IP.
Tus datos, en tu servidor
PostgreSQL y un directorio de repositorios, ambos tuyos para respaldar. La imagen corre con un usuario sin privilegios sobre un sistema de archivos de solo lectura.

La página de seguridad de la documentación (en francés)

Hacia dónde va

Cinco versiones, ninguna publicada. Un punto solo se marca cuando se publica.

  1. 0.2Ramas protegidas, comprobaciones, cinco idiomasPrevisto
  2. 0.3Un motor de análisis: secretos y dependenciasPrevisto
  3. 0.4Puertas de calidad y panelPrevisto
  4. 0.5Calidad del código: métricas, reglas, coberturaPrevisto
  5. 0.6Análisis de seguridad y ArtiFerrisPrevisto

Pruébalo y luego monta el tuyo.

La instancia pública muestra el producto. Tu instancia guarda tu código.