ferro-oci-server
Server-side primitives for the OCI Distribution Specification v1.1. Implements the Manifest / Blob / Tag / Referrers API surface as an Axum router, plus a chunked-upload state machine, error envelope that matches §6.2 of the spec, and a metadata-plane trait that keeps the storage layer abstract.
⚠️ Alpha (
v0.0.1). API will shift beforev0.1. The roadmap target forv0.1.0is "passes the upstreamopencontainers/distribution-specconformance test suite".
Part of the Ferro ecosystem. Existing Rust crates implement the
OCI client (oci-client) and types (oci-spec); as far as we can
tell, this is the first crate on crates.io that publishes the
server half.
What this crate does
router/handlers— Axum router for/v2/**:GET /v2/— version check (200 OK)GET|HEAD|DELETE /v2/{name}/blobs/{digest}— blob planePOST|PATCH|PUT /v2/{name}/blobs/uploads/{uuid?}— chunked + monolithic upload state machineGET|HEAD|PUT|DELETE /v2/{name}/manifests/{reference}— manifest plane (digest or tag references)GET /v2/{name}/tags/list— tag listing with paginationGET /v2/_catalog— repository listing with paginationGET /v2/{name}/referrers/{digest}— referrer index per spec §6.7
error—OciErrorplusOciErrorCodeenum that renders the spec's error JSON envelope ({ "errors": [...] })manifest—ImageManifest,ImageIndex,Descriptorserde typesmedia_types— Media-type classification (Docker v2 vs OCI v1 manifests, configs, layers)reference— image-name + tag + digest parsing with spec-compliant validationregistry—RegistryMetatrait (manifest + tag + upload + referrer book-keeping). Reference implInMemoryRegistryMetausingparking_lot::RwLock+BTreeMap.upload—UploadState,ContentRangeparser
What this crate does not do
- Persistent metadata — only
InMemoryRegistryMetaships. A SQLite / Postgres backend is on the roadmap; the trait is stable enough that you can implement your own today. - Authentication — handlers are open. Layer your auth in the Axum middleware stack above this router.
- Sigstore / SLSA / TUF / cosign — the OCI server stores and serves manifests but does not sign or verify. Those live in separate crates (not yet published).
- Conformance suite vendoring —
tests/conformance_smoke.rsexercises the request paths end-to-end, but the upstreamopencontainers/distribution-specconformance harness is not yet wired in. Doing so is the gate forv0.1.0.
Quick start
use Arc;
use Router;
use FsBlobStore;
use ;
# async
Then docker push localhost:5000/myimage:latest should work
against the running server.
Status
| Aspect | Status |
|---|---|
| API stability | alpha (v0.0.x) |
| Manifest / blob / tag / catalog / referrers handlers | working |
| Chunked uploads | working |
| Conformance suite | smoke tests only — formal harness pending |
| Persistent metadata backend | in-memory only |
| Authentication | scaffold — layer your own middleware |
| MSRV | rustc 1.88 |
Used in production by
- FerroRepo (private) — Rust artifact repository.
License
Apache-2.0. See LICENSE.