Skip to content

Components

Components

ocid is a local-first, peer-to-peer distribution system for OCI container images. It consists of several components that work together to provide a seamless experience for users of standard OCI tooling (podman, docker, oras) while enabling direct peer-to-peer synchronization.

High-Level Architecture

The following diagram shows the high-level architecture of ocid, including all major components and their interactions:

flowchart TB
    subgraph host["Your Machine (Host)"]
        direction TB
        subgraph tools["Tooling"]
            podman["podman / docker / oras"]
            cli["ocictl (CLI)"]
            tui["ocitop (TUI)"]
            pdext["Podman Desktop Extension"]
            prom["Prometheus"]
        end

        subgraph daemon["ocid (Daemon)"]
            direction TB
            subgraph registry["Registry Layer"]
                reg["OCI v2 Registry<br/>127.0.0.1:5050/v2"]
                ctl["Control API<br/>/_ocid/*"]
                met["OpenMetrics<br/>/metrics"]
                sse["SSE Events<br/>/_ocid/events"]
            end

            subgraph core["Core Layer"]
                identity["Identity<br/>Ed25519 Keypair"]
                policy["Policy Engine<br/>policy.toml"]
                windows["Retention Windows"]
                fetch["Fetch/Replicate"]
                gc["Garbage Collection"]
            end

            subgraph store["Storage Layer"]
                blobstore["Blob Store<br/>iroh-blobs FsStore"]
                index["Index<br/>JSON (digests, releases, referrers)"]
            end

            subgraph p2p["P2P Layer"]
                gossip["iroh-gossip<br/>Swarm + Publisher Topics"]
                sync["ocid/sync/1"]
                blobs["iroh-blobs"]
                mdns["mDNS<br/>_ocid._udp"]
                ep["iroh Endpoint<br/>QUIC + NAT Traversal"]
            end
        end
    end

    subgraph peers["Peer Network"]
        peer1["Peer A"]
        peer2["Peer B"]
        peer3["Peer C"]
    end

    %% Connections
    podman -- "HTTP /v2" --> reg
    cli -- "HTTP /_ocid" --> ctl
    tui -- "HTTP + SSE" --> ctl
    tui -- "HTTP + SSE" --> sse
    pdext -- "HTTP /_ocid" --> ctl
    prom -- "Scrape" --> met

    reg --> core
    ctl --> core
    met --> core
    sse --> core

    core --> identity
    core --> policy
    core --> windows
    core --> fetch
    core --> gc

    fetch --> store
    gc --> store

    store --> blobstore
    store --> index

    core --> p2p
    p2p --> gossip
    p2p --> sync
    p2p --> blobs
    p2p --> mdns
    p2p --> ep

    ep <--> peer1
    ep <--> peer2
    ep <--> peer3

    %% Styling
    classDef tooling fill:#f9f,stroke:#333,stroke-width:2px
    classDef daemon fill:#e6f3ff,stroke:#333,stroke-width:2px
    classDef peers fill:#ffe6e6,stroke:#333,stroke-width:2px

    class podman,cli,tui,pdext,prom tooling
    class reg,ctl,met,sse,identity,policy,windows,fetch,gc,blobstore,index,gossip,sync,blobs,mdns,ep daemon
    class peer1,peer2,peer3 peers

Component Descriptions

Component Description Responsibilities
OCI Registry Embedded OCI v2 registry Handle podman/docker/oras requests, serve manifests/blobs
Control API REST API for ocid management Handle ocictl requests, manage policy, peers, releases
OpenMetrics Metrics endpoint Expose Prometheus-compatible metrics for monitoring
SSE Events Server-Sent Events Stream real-time events to ocitop and Podman Desktop
Identity Ed25519 keypair Authenticate as a publisher, sign releases
Policy Engine Retention policy Enforce follow, seed, pin, and window rules
Fetch/Replicate Replication logic Fetch releases/blobs from peers, verify signatures
Garbage Collection Cleanup Remove unpinned blobs, enforce retention windows
Blob Store iroh-blobs FsStore Store content-addressed blobs (BLAKE3 hashes)
Index JSON index Map SHA256 digests to BLAKE3 hashes, track releases/referrers
iroh-gossip Gossip protocol Broadcast announcements, discover peers
ocid/sync/1 Sync protocol Fetch releases/blobs from peers
iroh-blobs Blob transfer Download/upload blobs with incremental verification
mDNS Local discovery Discover other ocid nodes on the local network
pkarr Internet discovery Publish/resolve endpoint addresses by bare key (mainline DHT via n0.computer)
iroh Endpoint QUIC endpoint Handle NAT traversal, hole-punching, relays

Crate Structure

The ocid project is organized into the following Rust crates:

flowchart TB
    subgraph crates["Rust Crates"]
        core["ocid-core"] -->|Library| daemon["ocid"]
        core -->|Library| cli["ocictl"]
        core -->|Library| tui["ocitop"]

        daemon -->|Daemon| registry["OCI Registry"]
        daemon -->|Daemon| node["Node"]
        daemon -->|Daemon| p2p["P2P"]

        cli -->|CLI| daemon
        tui -->|TUI| daemon
    end

    subgraph ext["Extensions"]
        pdext["Podman Desktop Extension"] -->|HTTP /_ocid| daemon
    end

    %% Styling
    classDef crates fill:#e6f3ff,stroke:#333
    classDef ext fill:#f9f,stroke:#333

    class core,daemon,cli,tui crates
    class pdext ext
Crate Description Purpose
ocid-core Library crate Identity, config/policy, OCI types, release records, index, API DTOs
ocid Daemon binary Run iroh endpoint, gossip, blob store, OCI registry, control API
ocictl CLI binary Interact with the daemon over HTTP, manage policy.toml
ocitop TUI binary Interactive terminal dashboard for daemon status
podman-desktop Extension Dashboard over the /_ocid API (TypeScript + Svelte)

Data Flow

The following diagram shows how data flows through the system when publishing and pulling images:

flowchart LR
    subgraph publish["Publish Flow"]
        podman -->|PUT /v2/app/manifests/1.0| reg
        reg -->|Store blobs| store
        reg -->|Sign release| core
        core -->|Announce| gossip
        gossip -->|Broadcast| peers
    end

    subgraph pull["Pull Flow"]
        podman -->|GET /v2/A/app/manifests/1.0| reg
        reg -->|Check local| store
        reg -->|Fetch from peers| sync
        sync -->|Download blobs| blobs
        blobs -->|Store| store
        store -->|Return manifest| reg
        reg -->|Return to podman| podman
    end

    %% Styling
    classDef publish fill:#d5e8d4,stroke:#333
    classDef pull fill:#ffd966,stroke:#333

    class podman,reg,store,core,gossip,peers publish
    class podman,reg,store,sync,blobs pull

Ports and Protocols

ocid uses the following ports and protocols:

Port Protocol Purpose Direction
5050 HTTP OCI v2 Registry (/v2/...) Inbound
5050 HTTP Control API (/_ocid/...) Inbound
5050 HTTP OpenMetrics (/metrics) Inbound
5050 SSE Events (/_ocid/events) Outbound
127.0.0.1:0 QUIC iroh Endpoint (loopback) Both
*:0 QUIC iroh Endpoint (external) Both
UDP 5353 mDNS Local discovery (_ocid._udp) Outbound

Wire Protocols

ocid uses the following wire protocols for communication:

ALPN Purpose Encoding
/iroh-gossip/1 Gossip announcements Postcard
ocid/sync/1 Sync requests (GetRelease, Inventory) Postcard
/iroh-bytes/... Blob download (BLAKE3 hash) BAO
mDNS _ocid._udp LAN discovery iroh-mdns-address-lookup

Deployment Topologies

ocid can be deployed in various topologies:

Single Node (Development)

flowchart TB
    podman --> ocid[ocid Daemon]
    ocictl --> ocid
    ocitop --> ocid

Multi-Node (LAN)

flowchart TB
    subgraph nodeA["Node A"]
        podmanA --> ocidA[ocid]
    end
    subgraph nodeB["Node B"]
        podmanB --> ocidB[ocid]
    end
    subgraph nodeC["Node C"]
        podmanC --> ocidC[ocid]
    end

    ocidA <-->|mDNS| ocidB
    ocidA <-->|mDNS| ocidC
    ocidB <-->|mDNS| ocidC

Multi-Node (WAN with Relays)

flowchart TB
    subgraph nodeA["Node A"]
        podmanA --> ocidA[ocid]
    end
    subgraph nodeB["Node B"]
        podmanB --> ocidB[ocid]
    end
    subgraph relay["Relay"]
        relay1[Relay Node]
    end

    ocidA <-->|QUIC| relay1
    ocidB <-->|QUIC| relay1