vexobj ← Portfolio
GitHub
Version 0.1.0 · Disponible

Stockage objet
compatible S3.

VexObj est une plateforme de stockage objet auto-hébergée, compatible avec l'API Amazon S3. Elle fournit le chiffrement au repos (AES-256-GCM), le versioning, l'object lock en mode WORM, et la réplication asynchrone primary-replica. Distribuée sous forme de binaire unique sans dépendances externes.

Performance · chemins critiques · par cœur
Mesures reproductibles
01 1,25Go/s

Débit AES-256-GCM. Le chiffrement au repos n'introduit pas de surcoût perceptible sur les charges courantes.

02 100k rps

Vérifications SigV4 par cœur et par seconde. Contrôle complet de signature, pas uniquement validation de la clé d'accès.

03 ~14Mo

Binaire autonome. Aucun runtime, interpréteur, ou orchestrateur de conteneurs requis au déploiement.

Méthodologie et résultats par taille de payload : docs/benchmarks.md. Benchmarks reproductibles localement via cargo bench.

À qui s'adresse VexObj.

Positionnement

Idéal pour

  • SaaS B2B / B2C jusqu'à quelques millions d'utilisateurs — binaire + backend S3 tient la charge sans sharding custom.
  • Plateforme média indépendante — podcasts, vidéos, galeries photo. Pipeline ingestion + transformation + transcoding couverte de bout en bout.
  • Instance fédérée — Mastodon, Matrix, Peertube, Pixelfed : stockage média local avec compat S3 pour les clients et réplication asynchrone.
  • Backend documentaire d'entreprise — object lock WORM + audit log + rétention immuable. Santé, finance, archivage légal.
  • Environnement dev / staging — mime une instance S3 localement en secondes, même auth, même compat SDK.

Pas taillé pour

  • Échelle des réseaux sociaux grand public (Meta, TikTok, Snap) — SQLite single-writer sature vers ~100 TB, au-delà il faut une couche metadata distribuée.
  • Multi-région actif-actif avec écritures simultanées des deux côtés — la réplication est asynchrone unidirectionnelle, pas de consensus Raft.
  • Modération automatique (NSFW, DMCA, copyright matching) — ces couches doivent être construites à côté.
  • Drop-in replacement d'un écosystème AWS complet — l'auth est plus simple, ce qui est une force pour 95 % des cas et une limite pour les 5 % restants.
Fonctionnalités

Ensemble de fonctionnalités de production.

Toutes les fonctionnalités ci-dessous sont incluses dans la version 0.1.0. Couverture de tests, documentation API (OpenAPI) et benchmarks disponibles dans le dépôt.

  1. 01
    API compatible S3 avec vérification SigV4

    Le préfixe /s3/* expose une API compatible avec les clients AWS SDK standards. Les en-têtes Authorization sont entièrement vérifiés : la requête canonique est reconstruite à partir des données reçues par le serveur et les HMAC sont comparés en temps constant. Toute requête altérée en transit est rejetée avec un code HTTP 403.

  2. 02
    Chiffrement au repos avec déduplication

    Chiffrement AES-256-GCM au repos. Les clés par blob sont dérivées par HKDF à partir d'une clé maître et du SHA-256 du contenu en clair, ce qui préserve la déduplication content-addressable : deux uploads identiques produisent un ciphertext identique.

  3. 03
    Versioning et object lock WORM

    Historique de versions par clé via le paramètre ?version_id= sur GET et DELETE, avec endpoint de purge dédié. La rétention par objet (mode WORM) et le legal hold bloquent toute suppression avec un code HTTP 409 jusqu'à l'expiration de la période de rétention.

  4. 04
    Réplication primary-replica asynchrone

    Chaque écriture ajoute un événement atomique à un log de réplication. Les répliques consomment ce log, récupèrent les blobs content-addressed via HTTP, et les appliquent directement en base. Une commande CLI dédiée permet la promotion d'une réplique en cas de défaillance du nœud primary.

  5. 05
    Traitement d'images à la volée

    Redimensionnement, recadrage et conversion de format via paramètres d'URL. Négociation automatique entre AVIF, WebP et JPEG selon l'en-tête Accept. Cache à deux niveaux en amont (LRU en mémoire + cache disque borné) pour optimiser la distribution via CDN.

  6. 06
    Politiques de cycle de vie, quotas, audit

    Règles d'expiration par préfixe, exécutables à la demande ou sur planification. Quotas par bucket en volume et en nombre d'objets. Journal d'audit persistant en SQLite pour chaque écriture : acteur, action, cible, adresse IP source.

  7. 07
    Observabilité Prometheus et Grafana

    Métriques exposées au format Prometheus sur /metrics, interface d'administration embarquée sur /dashboard, et dashboard Grafana prêt à importer couvrant les latences p50/p95/p99, le taux d'erreur et le débit.

  8. 08
    SDKs officiels

    SDKs TypeScript (fetch natif, aucune dépendance), Python (httpx, dataclasses typées) et Go (net/http standard, aucune dépendance). Couverture complète des opérations CRUD, du versioning, de l'object lock et des politiques de cycle de vie.

Exemples d'intégration.

API
# Création d'un bucket, upload d'une image, transformation à la volée.

curl -X POST http://localhost:8000/v1/buckets \
  -H "Authorization: Bearer $VFS_KEY" \
  -d '{"name": "photos"}'

curl -X PUT http://localhost:8000/v1/objects/photos/beach.jpg \
  -H "Authorization: Bearer $VFS_KEY" \
  -H "Content-Type: image/jpeg" \
  --data-binary @beach.jpg

# Téléchargement au format WebP à 400 pixels de large.
curl "http://localhost:8000/v1/objects/photos/beach.jpg?w=400&format=webp" \
  -H "Authorization: Bearer $VFS_KEY" -o beach.webp
import { VexObj } from "@vexobj/client";

const vfs = new VexObj({
  baseUrl: "http://localhost:8000",
  apiKey:  process.env.VFS_KEY!,
});

await vfs.enableVersioning("photos");
await vfs.putObject("photos", "beach.jpg", file, "image/jpeg");

// Application d'une rétention de 30 jours et d'un legal hold.
await vfs.setLock("photos", "beach.jpg", {
  retain_until: new Date(Date.now() + 30 * 86_400_000).toISOString(),
  legal_hold:   true,
});
from vexobj import VexObj

vfs = VexObj("http://localhost:8000", api_key=os.environ["VFS_KEY"])

vfs.enable_versioning("photos")
vfs.put_object("photos", "beach.jpg",
               open("beach.jpg", "rb"), "image/jpeg")

# Chaque PUT crée une nouvelle version sur un bucket versionné.
versions = vfs.list_versions("photos", "beach.jpg")
for v in versions:
    print(v.version_id, v.size, v.is_latest)
import "github.com/vortex-soft/vexobj/sdks/go"

c := vexobj.New("http://localhost:8000", os.Getenv("VFS_KEY"))

// Règle d'expiration à 7 jours sous le préfixe tmp/.
rule, _ := c.CreateLifecycleRule("photos", "tmp/", 7)
fmt.Println("rule id:", rule.ID)

// Exécution immédiate, sans attendre la prochaine planification.
expired, freed, _ := c.RunLifecycle()
fmt.Printf("expired %d objects, freed %d bytes\n", expired, freed)
# Réplication continue depuis un nœud primary distant.
vexobjctl replicate \
  --url          http://localhost:8000 \
  --key          $REPLICA_KEY \
  --primary      https://primary.example.com \
  --primary-key  $PRIMARY_KEY \
  --cursor-file  /var/lib/vexobj/replica.cursor \
  --interval     5

# Promotion de la réplique en cas de défaillance du primary.
vexobjctl promote \
  --url          http://localhost:8000 \
  --key          $REPLICA_KEY \
  --cursor-file  /var/lib/vexobj/replica.cursor
Architecture

Conception simple et prévisible.

Un processus, un répertoire de données, une base SQLite pour les métadonnées, des blobs content-addressed organisés sous blobs/<aa>/<bb>/<sha>, et un journal de réplication append-only optionnel. Sauvegarde et restauration via rsync standard.

Mise en route

Démarrage en quelques secondes.

Trois méthodes d'installation sont disponibles. Au premier démarrage, le serveur génère une clé API administrateur qu'il affiche sur la sortie standard — cette clé doit être conservée, elle ne sera plus affichée par la suite.

Option A · Docker

Docker

Configuration minimale. Un volume pour les données persistantes. Image officielle publiée sur GitHub Container Registry.

docker run -d \
  --name vexobj \
  -p 8000:8000 \
  -v vexobj-data:/data \
  ghcr.io/vortex-soft/vexobj:latest
Option B · Binaire

Binaire précompilé

Disponible pour Linux amd64 et macOS arm64. Empreintes SHA-256 signées publiées sur la page de release.

# linux-amd64
curl -LO https://github.com/vortex-soft/vexobj/\
releases/download/v0.1.0/\
vexobj-linux-amd64.tar.gz
tar xzf vexobj-linux-amd64.tar.gz
./vexobj
Option C · Sources

Compilation depuis les sources

Rust 1.85 minimum (edition 2024). La suite de tests complète s'exécute en environ deux secondes après un build à chaud.

git clone \
  https://github.com/vortex-soft/vexobj.git
cd vexobj
cargo build --release
./target/release/vexobj