blobarchive.net

docs / guide · updated 2026-08-01

Run an embedded follower

An embedded follower is the simplest complete BlobArchive node. A follower/replica operator—often the same person or organization as the L2 node operator—runs its libp2p host and FlatFS archive, authenticates published heads, retains the policy selected by its follow profile, and serves the L2 node a local beacon-compatible read API.

It does not run indexers or expose ingest.

It also does not require an Ethereum execution client, consensus client, validator, semi-supernode, or supernode. Complete-blob acquisition belongs to the selected writer; the follower authenticates and replicates the published archive.

Fast path: shipped Compose sample

The embedded-follower quickstart ships a complete Compose file, configuration, and durable-state layout.

# Release source archive: compose file and starter config.
curl -fsSL -o bloar-v0.1.0.tar.gz \
  https://github.com/blobarchive/bloar/archive/refs/tags/v0.1.0.tar.gz
tar xzf bloar-v0.1.0.tar.gz
cd bloar-0.1.0/deploy/quickstart/follower

# Small text file naming the image digest, not the image itself.
curl -fsSL -O \
  https://github.com/blobarchive/bloar/releases/download/v0.1.0/bloar-v0.1.0-image.env
set -a
. ./bloar-v0.1.0-image.env
set +a
sudo install -d -m 0750 -o 65532 -g 65532 data
sudo install -m 0400 -o 65532 -g 65532 /dev/null token
openssl rand -base64 32 | sudo tee token >/dev/null
docker compose pull
docker compose up -d

Compose refuses to pull or start when the release’s immutable BLOAR_IMAGE_DIGEST is absent. Verify the tag, attestation, and digest before loading the environment file; a mutable tag is not a durable deployment pin.

The sample defaults to ethereum-mainnet-arb1-live-a, binds its read API to http://127.0.0.1:8550, and publishes host TCP 4001 for direct swarm peers. Allow and forward that port whenever possible; set BLOAR_P2P_PORT before startup when host port 4001 is already occupied. The follower runs as uid/gid 65532 with a read-only root filesystem, no Linux capabilities, no-new-privileges, bounded CPU/memory/PIDs/file descriptors/logs, and only the documented durable state directory writable.

The live view is near-live, not a per-slot stream. Writers publish authenticated generations in batches, and the follower polls for a new generation once per minute by default. In normal steady state, expect new blobs to reach the local live view roughly one to two minutes after the source sees them. Public DHT conditions and bounded retries can occasionally extend that delay to several minutes. These are healthy-path expectations, not a ceiling: a publication outage can keep returning valid but frozen state for much longer. Monitor the age of the last accepted generation rather than request errors. Initial synchronization and catch-up after downtime are separate and can take much longer.

The remaining sections explain the choices encoded by that sample and the native-service equivalent.

1. Choose a follow profile

Use a finalized profile for immutable history or its -live counterpart for a finalized-plus-optimistic local view:

ethereum-mainnet-all-a
ethereum-mainnet-arb1-a
ethereum-mainnet-robinhood-a
ethereum-mainnet-base-a
ethereum-mainnet-all-live-a
ethereum-mainnet-arb1-live-a
ethereum-mainnet-robinhood-live-a
ethereum-mainnet-base-live-a

These are opaque keys. Select one by exact name; do not derive policy from the spelling.

The built-ins are curated conveniences, not the set of writers the network permits. A writer can publish under any domain it controls, and the follower/replica operator can select it through an explicit local follow-profile bundle without project approval. Inspect and pin that writer’s identity with the same care as a built-in.

2. Prepare persistent state

The archive and its replay floors belong together. Put the complete store.path on one durable filesystem and back it up as a unit.

sudo install -d -m 0750 -o 65532 -g 65532 /var/lib/bloar
sudo install -d -m 0750 -o root -g root /etc/bloar
sudo install -m 0600 -o 65532 -g 65532 /dev/null /etc/bloar/token
openssl rand -base64 32 | sudo tee /etc/bloar/token >/dev/null

These ownership values match the released container image’s uid/gid. A native systemd deployment should instead use the service account and credential delivery described in the operations guide.

Do not treat the KV directory as disposable cache. It contains publication replay floors, profile identity, root selectors, pin state, and other facts that make restart fail closed.

3. Write a minimal config

The follow profile supplies network, discovery, trust, selected heads, and retention. It does not supply paths, listener policy, private keys, or resource budgets.

follow: ethereum-mainnet-arb1-live-a

store:
  path: /var/lib/bloar

server:
  listen: 127.0.0.1:8550
  auth_token_file: /etc/bloar/token
  metrics_listen: 127.0.0.1:9550

p2p:
  listen:
    - /ip4/0.0.0.0/tcp/4001
  identity_key_file: /var/lib/bloar/p2p.key

The public BlobArchive service is the swarm. Keep the beacon and metrics listeners on loopback unless you deliberately add a private-network or TLS/reverse-proxy boundary with its own admission policy.

Read how BlobArchive uses IPFS for the relationship between port 4001, peer discovery, the DHT, Bitswap, relays, and hole punching.

4. Inspect before opening the store

config-inspect expands the profile and validates the complete effective configuration without joining libp2p, resolving DNS, reading credentials, or opening the store:

bloard config-inspect -config /etc/bloar/bloard.yaml

Review the selected profile name, version, content digest, DNSLink authority, signer pin, verify mode, heads, and retention.

5. Start and verify

Start the daemon with your service manager, then check its private operational endpoints:

curl --fail --silent --show-error http://127.0.0.1:9550/healthz
curl --fail --silent --show-error http://127.0.0.1:9550/readyz
curl --fail --silent --show-error http://127.0.0.1:8550/bloar/v1/heads

healthz proves the process is alive. readyz stays unavailable until every selected head has a serviceable committed generation. A source outage may leave readiness green when durable last-good data is still complete. The follower/replica operator monitors local readiness and publication lag; the selected writer operator owns the upstream source schedule.

Verify the configured local metrics listener from the same host:

curl --fail --silent --show-error http://127.0.0.1:9550/metrics >/dev/null

Before relying on the node in production, add the follower monitoring signals and starting alerts.

6. Query a blob

Use the local head route. Set the exact slot and versioned hash required by your consumer:

: "${BLOAR_SLOT:?set BLOAR_SLOT to a decimal beacon slot}"
: "${BLOAR_VERSIONED_HASH:?set BLOAR_VERSIONED_HASH to a 0x-prefixed versioned hash}"
curl --fail --silent --show-error --get \
  --data-urlencode "versioned_hashes=${BLOAR_VERSIONED_HASH}" \
  "http://127.0.0.1:8550/live/eth/v1/beacon/blobs/${BLOAR_SLOT}"

For a finalized-only profile, replace live with the physical selected head. For a filtered live view, provisional requests must name versioned hashes.

Backup and rollback

Stop the daemon for the simplest consistent copy, or take an atomic filesystem snapshot of the whole store. Preserve the config, libp2p key, and store together.

Rollback changes the binary or config without deleting the store or lowering trust floors. A writer outage is not a reason to reset the follower.

The complete production runbook is in operations. The exact configuration schema is in the specification.