pithos/README.md
Local Dev 6b8eeaf82b Pithos: a control panel for s3d, the Sia S3 gateway
s3d is driven entirely by a CLI and a two-route admin API, which keeps
Sia storage out of reach for anyone who does not live in a terminal.
Pithos wraps it: install the pinned s3d release (checksum verified),
start/stop and logs, indexer login, users and access keys, a bucket and
object browser with share links and public-read policies, and the
upload pipeline stats.

One control server (core/) serves one UI (ui/), and three hosts run it:
a web console, an Electron desktop window and a Theseus add-on, so a
feature lands everywhere at once. The server binds loopback, rejects
foreign Host headers, and signs views in with a one-time secret that
becomes a SameSite=Strict cookie. s3d login reads the recovery phrase
with term.ReadPassword, so it is driven through a pty, with a console
window fallback where the pty module is not shipped.
2026-10-03 19:02:50 +02:00

130 lines
5.1 KiB
Markdown

# Pithos
A control panel for [s3d](https://github.com/SiaFoundation/s3d), the Sia
Foundation's S3 gateway. s3d itself is managed through a CLI and a two-route
admin API; Pithos puts a UI over all of it:
- **Gateway**: install the pinned s3d release (SHA-256 checked), start, stop,
restart, live logs, edit `s3d.yml`.
- **Sia connection**: register s3d with an indexer (sia.storage or your own
indexd) with an existing recovery phrase or a freshly generated one, and
approve the connection in the browser.
- **Users & keys**: create and delete users, issue and revoke access keys,
copy ready-made `aws`, `rclone` and env-var config.
- **Buckets**: browse as any user, create and delete buckets, upload by
drag-and-drop, download, delete files and folders, presigned share links,
public-read policies.
- **Upload pipeline**: pending, uploaded, unpinned and failed objects from
`/stats/uploads`, plus "flush now".
## One core, three hosts
```
core/ control server: s3d process, CLI wrapper, SigV4 S3 client, admin API, HTTP API
ui/ the single-page UI the server serves (plain JS, no build step)
bin/pithos-web.js web console -> your browser
desktop/main.cjs desktop app -> an Electron window
theseus/ Theseus add-on -> a Theseus tab
```
Every host runs the same `createPithos()` server on a loopback port and
points a view at it. A feature added to `core/` + `ui/` lands in all three.
### Web console
```bash
npm install
node bin/pithos-web.js
```
It prints a one-time sign-in link for `127.0.0.1:8700`. To reach it from
another machine, set a password and put a TLS reverse proxy in front:
```bash
PITHOS_PASSWORD='long random secret' node bin/pithos-web.js --listen 0.0.0.0:8700 --allow-host pithos.example.org
```
Other flags: `--config <s3d.yml>`, `--s3d <binary>`, `--bin-dir <dir>`,
`--password-file <file>`.
### Desktop
```bash
npm run desktop
```
The window signs in with the server's one-time secret; nothing else on the
machine can drive the API. Quitting stops s3d cleanly. Installed s3d builds
go to the app's user-data folder.
### Theseus
```bash
node scripts/build-theseus-addon.mjs
```
builds `dist/theseus-addon/pithos/` (about 0.9 MB). Copy it into
`TheseusNavigator/bundled-addons/` to bundle it, or publish it as a
community extension. The dock menu has *Open Pithos* and *Stop s3d*.
The add-on leaves out the pty module (12 MB of native code), so on Windows
the indexer login runs in its own console window and Pithos picks up the
result when it closes.
## Which s3d instance it manages
The same one a hand-run `s3d` would use: `S3D_CONFIG_FILE` if set, otherwise
`%APPDATA%\s3d\s3d.yml` (Windows), `~/Library/Application Support/s3d/s3d.yml`
(macOS), `/etc/s3d/s3d.yml` (Linux). Every s3d call Pithos makes gets
`S3D_CONFIG_FILE` pinned, so the daemon and the CLI calls always agree.
If another s3d process is already serving that config (a service, or one
started by hand), the overview shows it as *external* and reads its stats,
but Pithos won't start a second copy.
Pithos needs **s3d v0.2.0 or newer**: `users list` and `keys list` arrived
in 0.2.0. Older builds get an upgrade banner.
## Security model
- The server binds loopback by default and refuses Host headers other than
its own address (DNS-rebinding guard). Binding beyond loopback requires a
password of at least 12 characters.
- Sessions are HttpOnly, SameSite=Strict cookies. Every non-GET request also
needs an `x-pithos: 1` header, so a cross-site form cannot drive the API.
- The recovery phrase is only written to the s3d login process's terminal.
It is never stored, logged or sent anywhere else. A generated phrase is
shown once and must be acknowledged.
- Downloads are served with a sandboxing CSP and `nosniff`, so a stored HTML
object cannot run script on the console's origin.
- s3d keeps access-key secrets in plain text in its own SQLite database.
Pithos shows them to whoever is signed in to the console, so treat console
access as root on the gateway.
## How it talks to s3d
| Need | Mechanism |
| --- | --- |
| users, keys, version, registration check | `s3d users …`, `s3d keys …`, `s3d version`, `s3d login` with stdin closed |
| indexer login | `s3d login` in a pseudo-terminal (it reads the phrase with `term.ReadPassword`) |
| buckets and objects | the S3 API, signed with SigV4 as the chosen user's first access key |
| stats, flush | the admin API (`/stats/uploads`, `/objects/flush`) with the configured admin password |
`test/sigv4.test.js` cross-checks the signer against the AWS CLI on awkward
keys and prefixes and on presigned URLs (`npm test`).
## Limits and next steps
- Uploads are single PUTs, capped at 5 GiB (s3d's part limit). Multipart
uploads from the browser would lift that.
- Object versioning, lifecycle rules and multipart-upload cleanup are not in
the UI yet.
- Desktop installers (electron-builder) are not set up yet.
- Multi-tenant mode, where end users sign in with a wallet and each get
their own s3d user and quota, is the planned follow-up. It is the
Hestia direction in `Hephaestus/DESIGN-hestia.md`.
## License
MPL-2.0. s3d is MIT, © The Sia Foundation.