Public files were addressed by a 32-character account id, and a public folder answered with JSON, so a link was unusable to send to anyone. Accounts that signed up with a BNS name can now be addressed by it (/p/alice.x/<drive>/<folder>/), a public folder opened in a browser is a page with its files, small pictures and a player (tools still get JSON), and every link and redirect on it is relative so navigate.st/s3/ serves the same pages. Pithos shows the navigate.st/s3 address when a folder is made public. |
||
|---|---|---|
| .. | ||
| deploy | ||
| test | ||
| auth.js | ||
| electrum.js | ||
| gate.js | ||
| main.js | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| rules.js | ||
| server.js | ||
| sigv4.js | ||
| store.js | ||
| supervisor.js | ||
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 signspithos-hosted signup <account id>with the wallet that owns a BNS name;apiis 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 toaddresscarrying OP_RETURNpithos:<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.