Vue d'ensemble de l'architecture¶
Gitrust est une plateforme d'hébergement Git auto-hébergée construite sur le framework rustwarden-core. L'application expose deux points d'entrée réseau (HTTP + SSH) et persiste ses données dans PostgreSQL.
Vue d'ensemble¶
graph TB
subgraph Clients
Browser["Navigateur Web"]
GitCLI["Git CLI (ssh/https)"]
end
subgraph "Gitrust Binary (src/main.rs)"
Main["main()"]
end
subgraph "Crates Gitrust"
Web["gitrust-web
Routes HTTP, templates,
handlers Axum"]
SSH["gitrust-ssh
Serveur SSH (russh),
auth par clé, sessions"]
SshGuard["gitrust-ssh-guard
SecureListener, détecteurs,
BanManager, AuthTracker"]
Hooks["gitrust-hooks
impl RustwardenHooks
(on_user_registered, ...)"]
Core["gitrust-core
Models, services, migrations,
rôles, types, DTOs"]
Git["gitrust-git
Bare repos, tree browser,
pack protocol (git2)"]
end
subgraph "Framework"
RW["rustwarden-core
Auth, users, JWT, sessions,
ResourceService, i18n"]
end
subgraph "Stockage"
PG[(PostgreSQL)]
FS[("Système de fichiers
bare repos .git")]
end
subgraph "CI/CD (optionnel)"
CiWorker["CiWorker
tokio::spawn, mpsc,
sous-processus Dagger"]
Dagger["Dagger Engine
Containers isolés,
cache, exécution"]
CiEngine["ci-engine
Module Dagger Python
(Easy Mode)"]
Syft["Syft (optionnel)
Génération SBOM
CycloneDX"]
DTrack["Dependency-Track
(optionnel)
Analyse vulnérabilités"]
end
Browser -->|HTTP :4000| Web
GitCLI -->|SSH :2222| SshGuard
SshGuard -->|"AcceptOutcome::Accepted"| SSH
GitCLI -->|HTTPS :4000| Web
Main --> Web
Main --> SSH
Main --> SshGuard
Main --> Hooks
Main -.->|"si CI_ENABLED"| CiWorker
Web --> Core
Web --> Git
Web -.->|"admin ACL/ban"| SshGuard
SSH --> Core
SSH --> Git
SSH --> SshGuard
SshGuard --> Core
Hooks --> Core
Core --> RW
Core --> PG
Git --> FS
CiWorker --> Core
CiWorker -->|"dagger call"| Dagger
Dagger -->|"Easy Mode"| CiEngine
Dagger -->|"Power Mode"| FS
CiWorker -.->|"si CI_SBOM_ENABLED"| Syft
Syft -.->|"si CI_DTRACK_ENABLED"| DTrack
Démarrage de l'application¶
Le diagramme suivant détaille la séquence d'initialisation depuis main() jusqu'au démarrage des serveurs HTTP et SSH.
sequenceDiagram
participant Main as main()
participant Builder as RustwardenBuilder
participant App as RustwardenApp
participant Mig as AppMigrator
participant DB as PostgreSQL
participant SMTP as Serveur SMTP
Main->>Main: GitrustConfig::from_env()
Main->>Main: Arc (hooks FS)
Main->>Builder: builder().from_env()
Note over Builder: Charge .env, init tracing
Main->>Builder: .headless().auto_migrate(false)
Main->>Builder: .merge_routes(app_routes(hooks))
Note over Builder: Routes = framework API
+ pages SSR gitrust
+ Extension(hooks)
Main->>Builder: .build().await
Builder->>DB: Connexion pool
Builder->>DB: Migrations rustwarden-core
Builder->>SMTP: EmailQueueProcessor.start()
Note over SMTP: Worker de fond : dépile
email_queue toutes les 30s
Builder-->>Main: RustwardenApp
Main->>Mig: run_migrations(app.database())
Mig->>DB: core_migrations() + gitrust_migrations()
Note over DB: Tables: users, resources,
repositories, ssh_keys,
teams, team_members,
team_repository_access
Mig-->>Main: Ok
Main->>Main: tokio::spawn(SSH server :2222)
alt CI_ENABLED=true
Main->>Main: CiWorker::start(config.ci)
Note over Main: Vérifie dagger dans PATH
Si CI_SBOM_ENABLED: vérifie syft
Si CI_DTRACK_ENABLED: vérifie API DT
Main->>Main: tokio::spawn(CiWorker loop)
Note over Main: Écoute mpsc channel
pour les jobs CI
end
Main->>App: app.run().await
Note over App: HTTP :4000 démarre
Principes de conception¶
Séparation framework / métier gitrust¶
Gitrust est construit au-dessus de rustwarden-core, un framework Rust d'authentification et de gestion d'utilisateurs. Cette séparation est intentionnelle :
- rustwarden-core gère : auth JWT, sessions, users, roles génériques, i18n, SMTP, OAuth, audit log générique.
- gitrust-core gère : tout ce qui est spécifique à la forge Git — dépôts, clés SSH, équipes, permissions RBAC à 4 niveaux, CI, import de dépôts.
La règle fondamentale : ne jamais modifier crates/rustwarden-core/. Toute extension passe par des wrappers, des hooks (RustwardenHooks) ou des traits implémentés côté gitrust.
Mode headless¶
gitrust-web opère en mode headless() : les pages UI standard de rustwarden (login, register, settings) sont désactivées et réimplémentées entièrement dans gitrust-web/templates/. Cela permet un design cohérent (sidebar Git, DaisyUI) sans compromis avec l'UI générique du framework.
SSR + HTMX, zéro CDN¶
L'interface est rendue côté serveur via Askama (templates Rust compilés). HTMX gère les interactions dynamiques (mises à jour partielles de page, SSE pour les notifications et les logs CI). Aucun asset externe : tout CSS/JS est servi depuis static/ — imposé par la Content Security Policy du framework.
Bare repos sur le système de fichiers¶
gitrust-git est découplé de la base de données. Les opérations Git (navigation d'arbre, lecture de blobs, pack protocol) travaillent directement sur les bare repos ({GIT_REPOS_BASE_PATH}/{owner}/{slug}.git/) via libgit2. La base ne stocke que les métadonnées (nom, description, visibilité, ownership). Ce découplage permet de remplacer ou tester gitrust-git indépendamment.
CI hybride : Dagger comme abstraction d'exécution¶
Plutôt que d'implémenter un runner CI from scratch, gitrust délègue l'exécution à Dagger, qui garantit l'isolation (containers), la reproductibilité (cache) et la portabilité (local ou runner distant via SSH+rsync). Le CiWorker est une tâche Tokio dans le processus principal — pas un daemon séparé — ce qui simplifie le déploiement (un seul binaire).
Pour aller plus loin¶
- Référence structurelle complète (tables de modules, routes, dépendances) : Architecture des crates
- Diagrammes de séquence détaillés (clone SSH, push, permissions) : Flux de requêtes
- Conception de la couche de durcissement SSH : Conception de ssh-guard et Crate gitrust-ssh-guard
- Règles de code et gates QA : Règles QA et conformité ANSSI