Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Per-recipient pin providers

By default, every inbound mail body a server delivers is pinned to IPFS by the operator’s provider — whatever the [ipfs] section of the server config selects (see [grpc] and [ipfs] — the chain pipeline). That single pin is what the on-chain message references, and its availability rests on that one operator continuing to pin.

A mailbox owner who wants an additional copy under their own control can register their own pinning provider with the server. Once configured, the delivery pipeline pins that recipient’s inbound sealed bodies to their provider in addition to the operator’s default pin — automatically, at delivery time, with no per-message action. It is the standing, server-side counterpart to sithbit mail pin, which re-pins already-delivered mail by hand.

Who it’s for: recipients who want their mail’s availability to outlive the operator’s pin — without running their own mail server. Bring a Pinata account, a Filebase bucket, or your own sithbit-ipfsd daemon.

How it fits into delivery

The recipient pin is deliberately best-effort and additive:

  • The operator pin runs first and stays authoritative — it yields the CID the on-chain message account records. The recipient pin is a second copy of the same sealed bytes; because IPFS is content-addressed, both providers serve the same CID.
  • A recipient-provider failure — provider outage, revoked credentials, a full bucket — is logged and dropped. It never delays, fails, or alters delivery or chain state. Your copy of the mail arrives either way; only the extra pin is missed.
  • The no_ipfs opt-out wins over everything: an opted-out mailbox gets no pin at all — not the operator’s, not yours. The opt-out means “my mail never touches public IPFS”, and a recipient-configured provider doesn’t override that.

Configuring a provider

The surface is three routes on the account API, under the same JWT wallet auth as the rest of /v1/account — so a wallet holder manages their own provider, and only theirs. The examples below assume $JWT holds a token from wallet-challenge login.

Set (or replace) a providerPUT /v1/account/pin-provider with a kind-tagged JSON body, one of three kinds:

# Pinata: an API JWT plus your dedicated gateway
curl -X PUT http://127.0.0.1:8180/v1/account/pin-provider \
  -H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \
  -d '{"kind":"pinata","jwt":"<pinata-api-jwt>","gateway":"https://example.mypinata.cloud"}'

# Filebase: S3 credentials plus the pinning bucket
# (endpoint is optional, default "https://s3.filebase.com")
curl -X PUT http://127.0.0.1:8180/v1/account/pin-provider \
  -H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \
  -d '{"kind":"filebase","access_key":"<key>","secret_key":"<secret>","bucket":"my-mail"}'

# Remote: a sithbit-ipfsd pin daemon you operate
# (endpoint defaults to "http://127.0.0.1:8182"; auth_token is optional,
#  matching the daemon's auth_token setting)
curl -X PUT http://127.0.0.1:8180/v1/account/pin-provider \
  -H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \
  -d '{"kind":"remote","endpoint":"https://ipfsd.example.net:8182","auth_token":"<token>"}'

Success is 204 No Content. A missing or empty required credential field is a 400 naming the field (e.g. filebase.secret_key must not be empty); an unknown kind is a 422; a wallet with no account on this server is a 404. For the remote kind, point the endpoint at a sithbit-ipfsd daemon — and since its pin API is a write surface, expose it beyond loopback only with its auth_token set or network isolation in front.

Check what’s configuredGET /v1/account/pin-provider:

curl -H "Authorization: Bearer $JWT" http://127.0.0.1:8180/v1/account/pin-provider
# → {"configured":true,"kind":"filebase"}   (or {"configured":false,"kind":null})

The read surface is deliberately write-only for secrets: it reports presence and the kind tag, never the credentials — not even redacted ones. To rotate credentials, simply PUT the replacement.

Remove itDELETE /v1/account/pin-provider:

curl -X DELETE -H "Authorization: Bearer $JWT" http://127.0.0.1:8180/v1/account/pin-provider
# → 204; future deliveries pin to the server default only

Deleting is idempotent — clearing an already-unconfigured provider still answers 204.

What the server stores, and who can read it

The credentials are sealed (AES-256-GCM) under the operator’s server-wide credential key and kept in the accounts store — the same mechanism as stored mail passwords (see credential_key_file). Only the kind tag is stored in the clear, so the GET route (and the operator) can answer which provider without opening the secret.

Be clear-eyed about the trust statement this implies: the operator’s server can read these credentials — it has to, to pin to your provider at delivery time. That is the design, and it is the opposite of Lockbox-style end-to-end secrecy: sealing here protects the credentials at rest (a stolen database dump without the credential key reveals nothing), not from the operator. Use a scoped, revocable credential — a Pinata JWT restricted to pinning, a Filebase key for a dedicated bucket, an ipfsd auth_token you can rotate — never a root account key.

Nothing about this setting is on-chain. Contrast the no_ipfs opt-out, which is an on-chain mailbox flag because foreign senders must see it before they pin; your pin provider only matters to the one server that delivers your mail, so it stays operator-local.

Tradeoffs

  • Your copy is only as good as your provider. The recipient pin depends on your provider’s availability and your credentials staying valid — an expired Pinata JWT or a deleted bucket silently costs you the extra copies (watch the server’s logs, or spot-check with GET /ipfs/<cid> against your own gateway). The operator pin remains the authoritative one either way.
  • No backfill. Configuring a provider affects mail delivered from then on. To capture your existing history, run sithbit mail pin once against the same provider — it takes the identical Pinata/Filebase/remote credential shapes.
  • The operator holds your provider credentials (sealed at rest, but readable by the running server — see above). Scope and rotate them accordingly.
  • You manage your provider’s lifecycle. The server only ever adds pins to your provider: settlement and deletion release the operator’s pin, never yours. A deleted message’s extra copy stays pinned on your provider until you remove it there yourself.
  • Opt-out excludes you. A mailbox with the no_ipfs opt-out never gets any pin, including this one — the two settings answer opposite wishes, and the opt-out wins.