pithos/hosted/README.md
Local Dev 9727ce79d3 Pithos: document hosting on Silent Mode and the gateway
Records what was built against the plan (names are encrypted from v1, rights
for other people are folder-scoped S3 keys), how to run pithos-hosted, and
that paid storage belongs to Hestia, a separate product.
2026-10-04 01:44:23 +02:00

3.3 KiB

pithos-hosted

The server half of Pithos's On Silent Mode: one s3d per person, each on that person's own Sia account, behind a gateway that adds sign-in, per-folder access and traffic limits. The client half (encryption, moving drives) is in ../core/hosted.js and ../core/hosted-routes.js.

What it serves

Path Who What
/hosted/v1/challenge, /hosted/v1/session anyone Ed25519 sign-in; first sign-in needs a sign-up proof
/hosted/v1/me, /rules, /data/... session account, access rules, moving the s3d data folder in and out
/api/... session the owner's Pithos API, forwarded to their s3d's control server (an allowlist; object routes are refused so nothing bypasses client-side encryption)
/p/<account>/<drive>/<path> anyone files under a public rule
/l/<token> anyone one file under a share link, until it expires
everything else S3 keys path-style S3. Owner keys go straight to their s3d, which checks the signature; keys minted for other people are verified here, held to their folder and rights, and re-signed with the owner's key

s3d processes listen on loopback only (portBase + 2 * slot). Each one starts on the account's first request and is stopped after idleMinutes, leftovers flushed to Sia first; at most maxRunning run at once.

State is files under root: users/<id>/ (account, s3d.yml, data, rules, usage), sessions.json (token hashes), gate.json, keys.json, grants.json, links.json. Back up that folder and you have backed up the service.

Sign-up gate

gate in the config enables any of:

  • bns: { api }: the user signs pithos-hosted signup <account id> with the wallet that owns a BNS name; api is a BNS gateway answering /api/name/<name> with the owner. One slot per name.
  • deposit: { address, minSats, confirmations, electrum: { host, port, tls } }: a BCH payment to address carrying OP_RETURN pithos:<account id>. One slot per transaction. Refunds are an operator decision.
  • invites: ["code", ...]: one use each.

perIpPerDay limits sign-ups per client address (set trustProxy behind nginx so X-Forwarded-For is used).

Running it

cd /opt/pithos && npm install --omit=dev --omit=optional
cd hosted && npm install --omit=dev
cp deploy/pithos-hosted.example.json /etc/pithos-hosted.json   # edit it
node main.js --config /etc/pithos-hosted.json

deploy/ has a systemd unit and an nginx site for s3.silentmode.st (streamed bodies, Host passed through: s3d checks signatures against the host the client signed). The s3d binary must be the version Pithos pins (core/binary.js), the same on both sides of a move.

Stopping the service flushes every running s3d first, so give systemd time (TimeoutStopSec=300).

Tests

npm test here covers SigV4 verification, rules and the sign-up gate. The full path (move up, encrypt, share, grant, move back) needs a real s3d; it was exercised against a mock indexer during development.

Not yet

  • Signed streaming uploads (STREAMING-AWS4-HMAC-SHA256-PAYLOAD) from shared keys are refused; owner keys are unaffected.
  • Shared keys and links reach readable copies only. Sharing encrypted files with a person (wrapping the folder key to theirs) is the next step.
  • No quotas here: storage is each person's own Sia account. Paid storage is Hestia, a separate product.