sithbit-gateway: the IPFS HTTP gateway
Standard port(s): bind 8183, health 8198.
A read-only IPFS path gateway (GET/HEAD /ipfs/{cid}) serving
mail blobs straight out of the same block/pin bucket the node writes —
deserialized file bytes by default, trustless raw-block and CARv1
responses via ?format=raw|car (or the matching Accept types), with
the standard immutable-caching, conditional-request, and range
semantics of the
IPFS gateway specs.
It is deliberately local-content-only: a CID whose blocks are not
in the bucket answers 404 — the gateway never fetches foreign content
from the IPFS network. Point [blobs] at the shared S3 bucket (or
share the local ipfs/ directory) and it serves exactly what the
node/cluster pinned, nothing else.
When you need it: only when pinned mail blobs should be fetchable
over plain HTTP — a recipient’s client verifying an on-chain CID
without running IPFS, a load-balancer-friendly read path in front of
the bucket, or public retrievability without opening the swarm port.
Mail delivery itself never needs it; sithbitd and decentralized
clients read blobs through IPFS directly.
Quickstart:
cargo run -p ipfs-gateway
Config file ipfs_gateway.toml, or point IPFS_GATEWAY_CONFIG at an
alternate path.
Subdomain (Host-based) gateway
Alongside the path gateway, sithbit-gateway can answer subdomain
requests of the form <base32-cidv1>.ipfs.<public_host>, where the CID
lives in the leftmost DNS label rather than the URL path. This is the
gateway form that gives each CID its own web origin, so browsers isolate
one blob’s scripts, cookies, and storage from another’s.
It is off by default. Turn it on by setting the base domain:
public_host = "example.com"
Left unset (the default), the gateway is path-only and the subdomain dispatch is a no-op on every request. With it set:
- A
Hostof<label>.ipfs.example.comserves the CID named by<label>, reusing the exact same format negotiation (?format=raw|car), range, and caching behavior as the path route. - Both entry surfaces canonicalize to lowercase
base32CIDv1, matching Kubo:- Label surface. A
Hostwhose label is a CIDv0 (base58) or otherwise non-canonical answers a 301 to the canonical host (//<base32-cidv1>.ipfs.example.com/…), preserving path and query. - Path→subdomain surface. A request to the bare
public_hostitself (Host: example.com) with a path of/ipfs/{cid}answers a 301 into the subdomain form://<base32-cidv1>.ipfs.example.com/, scheme-relative, query preserved. This is the redirect Kubo issues to move a path request onto its own origin, so a blob reached by path lands on one stable origin too.
- Label surface. A
- Only the bare subdomain root resolves. A sub-path under a subdomain host
(
.../some/file) returns 404 — mail blobs are single-file DAGs, so the gateway does no directory resolution.
This surface is conformance-tested against a live Kubo (v0.42.0) node, and the canonicalization on both surfaces now tracks it. Two deliberate, spec-legal differences remain:
- Sub-path 404 shape. A path of
/ipfs/{cid}/<sub>on the bare host is, on Kubo, a 301 into the subdomain followed by a 404 there; ours short-circuits to a direct 404 — same observable end state, one fewer hop (no directory resolution to attempt on a single-file DAG). Locationshape. Our redirects are scheme-relative (//host/…); Kubo emits absolute (https://host/…). Both are RFC 7231 §7.1.2-legal and resolve identically in browsers.
Honest scope: this surface is spec-conformance and future-proofing for a
public deployment. The SithBit mail client fetches blobs by path
(GET /ipfs/{cid}) and never needs subdomain origins; the subdomain
gateway only adds the browser origin-isolation semantics that a general
web-facing IPFS gateway is expected to provide, which this private,
read-only gateway does not itself consume. Leave public_host unset
unless you are exposing the gateway to third-party browsers.
See the Configuration reference for the full key/default table.