Retour aux mises à jour
New releaseAug 17, 2026

vpod v0.7.1

Sandbox Linux légères et sécurisées pour les processus non fiables. Fonctionne dans le navigateur et sur le serveur.

Partager

Vpod

Qu'est-ce qu'un vpod ?

Un vpod est une sandbox légère et portable qui offre à un processus non fiable un environnement Linux instantané. Elle utilise une architecture RISC‑V et s'exécute entièrement dans WebAssembly.

  • Démarrage rapide : Démarre en moins d'une seconde.
  • Portable : Fonctionne partout sans aucune configuration requise.
  • Isolée : Tout l'état d'exécution reste dans les sandboxes WASM.

Comment ça fonctionne

Un vpod exécute un système RISC‑V complet (RV64GC, un seul vCPU) compilé en WebAssembly. À l'intérieur, il démarre un vrai noyau Linux avec un véritable espace utilisateur, de sorte que les shells, outils et démons se comportent comme sur du matériel réel.

Snapshots. Au lieu de démarrer Linux de zéro, un vpod restaure un snapshot : un état machine sauvegardé (registres CPU, RAM, système de fichiers) capturé juste après le démarrage. La restauration prend bien moins d'une seconde. La suspension fonctionne de la même manière à l'envers : seules les pages mémoire modifiées sont réécrites sur le disque, vous pouvez donc mettre une sandbox en pause et la reprendre plus tard, même depuis un autre processus.

Traduction à l'avance (AOT). L'émulation pure instruction par instruction est lente, et WebAssembly exclut un JIT à l'exécution. Ainsi, au moment de la construction du snapshot, les chemins de code invité les plus chauds sont traduits du RISC‑V en code natif compilé dans le module WASM lui-même. À l'exécution, l'émulateur se dirige vers ces blocs traduits lorsque le code invité correspond, et retombe sur l'interpréteur sinon. Cela vaut environ 5x pour les travaux intensifs en CPU, avec zéro effet sur l'isolation : le code traduit passe par les mêmes vérifications MMU et mémoire que le code interprété.

La frontière WASI. Le composant WASM ne communique avec l'hôte qu'exclusivement via WASI 0.2. L'invité ne voit jamais les descripteurs de fichiers, sockets ou mémoire de l'hôte : l'accès au système de fichiers passe par des répertoires explicitement montés, et la mise en réseau passe par une pile réseau en mode utilisateur à l'intérieur du composant qui ne demande à l'hôte que de simples sockets sortantes. Tout le reste (noyau invité, processus, mémoire) vit dans la mémoire linéaire WASM et meurt avec elle.

Spécification RV64GC

G (Extensions à usage général)

  • I : Jeu d'instructions entier 64 bits de base.
  • M : Multiplication et division matérielles, utiles pour le hachage et la cryptographie.
  • A : Opérations atomiques pour les programmes thread-safe.
  • F/D : Nombres à virgule flottante simple et double précision, adaptés au calcul scientifique et à l'inférence ML.

C (Instructions compressées) Réduit la taille du code de 30 %, améliorant la vitesse de chargement des instructions et l'efficacité mémoire. C'est important lorsqu'on exécute un espace utilisateur Linux complet dans notre environnement WASM à mémoire contrainte.

[!NOTE] L'extension V (vectorielle) n'est pas implémentée. Les instructions RVV seraient exécutées comme du RISC-V émulé ; il n'y a pas de passage SIMD vers le CPU hôte. Ajouter V augmenterait la surcharge d'émulation sans aucun gain de performance pour les charges vectorisées.

Pour commencer

SDK Python

pip install vpod
from vpod import Sandbox

# Run a command
sandbox = Sandbox.create()
result = sandbox.commands.run("whoami")
print(result.stdout)  # root
sandbox.close()

# Persistent session — state preserved across calls
with Sandbox.create() as sandbox:
    sandbox.commands.run("export API_KEY=secret")
    result = sandbox.commands.run("echo $API_KEY")
    print(result.stdout)  # secret

# Python REPL — variables persist
with Sandbox.create() as sandbox:
    sandbox.code.run("import requests")
    sandbox.code.run("data = [1, 2, 3]")
    result = sandbox.code.run("print(sum(data))")
    print(result.text)  # 6

[!IMPORTANT] Le premier appel à Sandbox.create() télécharge le snapshot par défaut (alpine) et le met en cache localement s'il n'est pas déjà présent.

CLI

curl -fsSL https://install.vpod.sh | sh
Ou installez via PowerShell (Windows)
irm https://install.vpod.sh | iex
# Pull a snapshot
vpod pull alpine:latest

# Start an interactive shell
vpod

Documentation

Consultez la documentation Vpod.

Limitations

  • Surcharge d'émulation : Il n'y a pas de virtualisation matérielle dans WebAssembly, donc tout le code invité est émulé. La surcharge dépend entièrement de la charge de travail : les travaux liés aux E/S et au réseau s'exécutent presque à la vitesse native, tandis que les travaux intensifs en CPU s'exécutent nettement plus lentement, même avec la traduction AOT. Si votre charge de travail consiste surtout à "exécuter un outil, lire un fichier, appeler une API", vous ne le remarquerez pas.
  • Pas d'accès GPU : CUDA, Metal et les accélérateurs ML matériels ne sont pas disponibles. Une prise en charge pourrait être ajoutée à l'avenir avec wasi-nn.

Contribuer

Les contributions sont les bienvenues, des rapports de bugs au support de nouveaux périphériques. Ouvrez une issue pour discuter de tout élément substantiel avant de le développer.

Prérequis

  • Rust (dernière version stable) avec la cible wasm32-wasip2 : rustup target add wasm32-wasip2
  • Python 3.10+ pour le SDK
  • Zig (0.16) et bsdtar, nécessaires uniquement si vous construisez vous-même des snapshots

Configuration de développement

# One-time: generate the AOT stub (a fresh clone has no translated blocks)
./scripts/aot-stub.sh

# Build the WASM component (library + CLI)
./scripts/build-wasm.sh

# Install the host CLI
cargo install --path crates/vpod

# Install the Python SDK in dev mode
pip install -e "sdks/python[dev]"

Exécution des tests

La CI exécute ces tests à chaque PR, alors lancez-les avant de pousser :

cargo fmt --all -- --check                        # formatting
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all                                  # Rust tests

# Python SDK integration tests (needs the WASM library in place)
cp target/wasm32-wasip2/release/vpod_wasi_lib.wasm sdks/python/vpod/
pytest sdks/python/tests/ -v -m integration

Construction des snapshots

Le projet utilise des snapshots Alpine préconstruits depuis registry.vpod.sh, vous n'en avez donc normalement pas besoin. Pour en construire un localement :

./scripts/build-default-snapshot.sh   # dist/alpine-3.23.0-256mb.snap
./scripts/build-data-snapshot.sh      # 512 MB variant with numpy/pandas/scipy

[!IMPORTANT] Pour utiliser un snapshot construit localement, décommentez les lignes dans resolve_snapshot() dans crates/vpod/src/main.rs.

Les constructions de snapshots peuvent également exécuter la passe AOT (scripts/aot-snapshot.sh <snapshot>), qui trace une charge de travail représentative, traduit les blocs chauds et reconstruit l'émulateur en les intégrant. Cela prend du temps ; le stub de aot-stub.sh convient pour le développement quotidien, tout fonctionne de la même manière, juste plus lentement.

Pull requests

  • Gardez les PR ciblées : une modification par PR.
  • fmt, clippy et la suite de tests doivent passer (la CI impose les trois).
  • Si vous touchez aux chemins d'exécution ou de mémoire de l'émulateur, expliquez comment vous avez validé l'exactitude (la suite de tests au minimum ; pour les changements subtils, un démarrage plus une charge de travail réelle dans l'invité constituent un bon test de cohérence).

Licence

Ce projet est sous licence Apache License 2.0. Consultez le fichier LICENSE pour plus de détails.

Catégories