diff --git a/docs/build-docs.mjs b/docs/build-docs.mjs
new file mode 100644
index 0000000..766a165
--- /dev/null
+++ b/docs/build-docs.mjs
@@ -0,0 +1,171 @@
+// Builds docs/index.html from docs/pithos-docs.md (the Markdown stays the
+// source of truth and is published beside it for AI assistants).
+// node docs/build-docs.mjs
+// Handles the Markdown this page uses: headings, paragraphs, lists (one
+// nested level), fenced code, tables, inline code, bold, italics and links.
+import fs from 'node:fs';
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+const dir = path.dirname(fileURLToPath(import.meta.url));
+const md = fs.readFileSync(path.join(dir, 'pithos-docs.md'), 'utf8').replace(/\r\n/g, '\n');
+
+const esc = (s) => s.replace(/&/g, '&').replace(//g, '>');
+const slug = (s) => s.toLowerCase().replace(/<[^>]+>/g, '').replace(/[`*]/g, '').replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
+function inline(s) {
+ const codes = [];
+ s = s.replace(/`([^`]+)`/g, (_, c) => { codes.push(`${esc(c)}`); return `\u0000${codes.length - 1}\u0000`; });
+ s = esc(s)
+ .replace(/\*\*([^*]+)\*\*/g, '$1')
+ .replace(/(^|[\s(])\*([^*\s][^*]*)\*/g, '$1$2')
+ .replace(/\[([^\]]+)\]\(([^)\s]+)\)/g, '$1');
+ return s.replace(/\u0000(\d+)\u0000/g, (_, i) => codes[+i]);
+}
+
+const lines = md.split('\n');
+const out = [];
+const toc = [];
+let i = 0;
+let title = 'Pithos documentation';
+while (i < lines.length) {
+ const line = lines[i];
+ if (!line.trim()) { i++; continue; }
+ const fence = /^```(\w*)/.exec(line);
+ if (fence) {
+ const buf = [];
+ i++;
+ while (i < lines.length && !lines[i].startsWith('```')) buf.push(lines[i++]);
+ i++;
+ out.push(`
${esc(buf.join('\n'))}`);
+ continue;
+ }
+ const hd = /^(#{1,3}) (.+)$/.exec(line);
+ if (hd) {
+ const level = hd[1].length;
+ const text = hd[2];
+ if (level === 1) { title = text; i++; continue; }
+ const id = slug(text);
+ toc.push({ level, id, text: inline(text) });
+ out.push(`| ${inline(c)} | `).join('')}
|---|
| ${inline(c)} | `).join('')}
${inline(para.join(' '))}
`); +} + +const tocHtml = toc.filter((t) => t.level === 2).map((t) => `${t.text}`).join(''); +const html = ` + + + + + +Pithos is a control panel for s3d, the Sia Foundation's S3 gateway. With it you connect s3d to a Sia storage account, create S3 users and access keys, keep files in drives, play and share them, and watch uploads reach the Sia network. Everything Pithos does can also be done by hand with the s3d command line; this page explains both, so you can set it up yourself or hand the page to an AI assistant and let it guide you.
This page is also published as plain Markdown at pithos.sia/docs/pithos-docs.md for AI assistants.
| Piece | What it is |
|---|---|
| Sia | A decentralized storage network: independent hosts store your data, paid in siacoin. |
| Indexer | A service that rents space from Sia hosts and keeps track of where your data is. sia.storage is the indexer run by the Sia Foundation; you can run your own (indexd). |
| Sia account | Your account at an indexer. It holds the storage you pay for (sia.storage's free plan: 50 GB). |
| s3d | A program on your computer that speaks the S3 protocol and stores everything through your Sia account. |
| S3 user | A login inside your own s3d. Each user owns drives and has access keys. |
| Access key | An access key ID and secret key pair that S3 apps use to sign in as a user. |
| Drive | Top-level storage owned by one S3 user. S3 apps call it a bucket. |
| Folder | Part of a file's name (photos/2026/beach.jpg). Pithos keeps empty folders visible with a small marker. |
| Pithos | This app. It runs s3d for you and puts a screen over all of the above. |
Data flow: your app or Pithos → s3d on your computer → (encrypted, erasure-coded) → Sia hosts, tracked by your indexer account.
+Two things to know early:
+s3d flush or Upload now sends them immediately.127.0.0.1 means "this computer". s3d listens on 127.0.0.1:8000 by default, so links that start with it work only on the machine running s3d. Other devices cannot open them.Pithos comes with Theseus, the Silent Mode browser. Open it from the Pithos icon in the left-hand strip.
+s3d login and opens the indexer's approval page. Approve the app named S3d there.Which Sia account you end up with depends on two things together: the indexer login that approved the connection and the recovery phrase. The same phrase approved from two different logins makes two different accounts.
+The menu is in setup order. In the narrow sidebar it is the ☰ button at the top right; the ⤢ button next to it opens Pithos as a full page.
+.pithoskey file (in Theseus it can be sealed with your vault instead).Edits s3d.yml; s3d reads it at start, so restart to apply. Also: automatic upload of leftovers (on by default, after 10 minutes with no new uploads) and where your drives live.
Live output of s3d and Pithos's own notes (why it started or did not start s3d, flushes, errors).
+pithos.sia/<user>/<drive>/<folder> (and pithos.sia/settings, pithos.sia/account …). The bare pithos.sia is this website.npm install
+node bin/pithos-web.js
+ It prints a one-time sign-in link for http://127.0.0.1:8700. Options:
| Flag | Meaning |
|---|---|
--listen host:port | Address to serve on (default 127.0.0.1:8700). Anything beyond loopback needs a password. |
--config <s3d.yml> | Which s3d config to manage. |
--s3d <binary> | Use this s3d binary. |
--bin-dir <dir> | Where Pithos installs s3d. |
--password-file <file> | Password login (or set PITHOS_PASSWORD, at least 12 characters). |
--allow-host <name[:port]> | Extra Host names allowed (behind a reverse proxy). Repeatable. |
Remote access: PITHOS_PASSWORD='long random secret' node bin/pithos-web.js --listen 0.0.0.0:8700 --allow-host pithos.example.org, behind a TLS reverse proxy.
npm run desktop
+ The window signs itself in; quitting stops s3d.
+The same one a hand-run s3d uses: S3D_CONFIG_FILE if set, otherwise %APPDATA%\s3d\s3d.yml (Windows), ~/Library/Application Support/s3d/s3d.yml (macOS), /etc/s3d/s3d.yml (Linux). If another s3d already serves that config, Pithos shows it as external and does not start a second one.
Pithos needs s3d v0.2.0 or newer. Download it from the s3d releases on GitHub (SiaFoundation/s3d), or let Pithos install it.
+| Command | What it does |
|---|---|
s3d | Start the S3 gateway (runs until stopped). |
s3d version | Print the version. |
s3d config | Interactive setup; writes s3d.yml. |
s3d login | Register this s3d with an indexer (asks for the indexer URL and the recovery phrase, prints an approval link). |
s3d status | Upload pipeline stats from the running s3d. |
s3d flush | Upload everything waiting to Sia now (blocks until done). |
s3d users create <name> / delete <name> / list | Manage S3 users. |
s3d keys create <user> | New access key (prints the ID and secret). --access-key <id> --secret-key <secret> sets them yourself (16-128 and 32-128 characters). |
s3d keys list [user] / keys delete <access-key-id> | List or revoke keys. |
s3d config # set addresses, admin password, data folder
+s3d login # indexer URL (https://sia.storage) + 12-word phrase, then approve
+s3d # start the gateway (leave running, or install as a service)
+s3d users create alice # in another terminal
+s3d keys create alice # note the access key ID and secret
+aws configure --profile s3d # paste the key, region us-east-1
+aws --profile s3d --endpoint-url http://127.0.0.1:8000 s3 mb s3://alice-files
+aws --profile s3d --endpoint-url http://127.0.0.1:8000 s3 cp photo.jpg s3://alice-files/photos/
+s3d flush # send it to Sia now instead of waiting for a full block
+ Keep the recovery phrase offline. It is the only way to reconnect this storage on another machine or after a reinstall; never paste it into a chat or a website you did not open yourself.
+| Windows | macOS | Linux | |
|---|---|---|---|
| Config | %APPDATA%\s3d\s3d.yml | ~/Library/Application Support/s3d/s3d.yml | /etc/s3d/s3d.yml |
| Data (database, files waiting) | %APPDATA%\s3d | ~/Library/Application Support/s3d | /var/lib/s3d |
Environment variables: S3D_CONFIG_FILE (use this config file), S3D_DATA_DIR (data folder).
apiAddress: 127.0.0.1:8000 # S3 API
+apiHTTPSAddress: "" # optional TLS listener (self-signed)
+adminAddress: 127.0.0.1:8001 # admin API (must differ from the S3 addresses)
+adminPassword: change-me # required for status/flush
+directory: /var/lib/s3d # data folder
+sia:
+ diskUsageLimit: 10737418240 # local buffer limit in bytes (default 10 GiB)
+ uploadThreads: 4 # parallel uploads to Sia
+ dataShards: 10 # erasure coding: data shards per slab
+ parityShards: 20 # recovery shards per slab (10-of-30 by default)
+s3:
+ hostBases: [] # host names for virtual-host style buckets
+log:
+ stdout: { enabled: true, level: info }
+ file: { enabled: true, level: info }
+ HTTP Basic auth with an empty user name and adminPassword:
| Request | Result |
|---|---|
GET /stats/uploads | Pending, uploaded, unpinned, failed, orphaned objects and multipart uploads (JSON). |
POST /objects/flush | Upload everything waiting, now. |
POST /snapshots | Back up s3d's database to Sia as a snapshot. |
curl -u :change-me http://127.0.0.1:8001/stats/uploads
+ Any S3 app works. Use the endpoint http://127.0.0.1:8000, region us-east-1, path-style addressing, and an access key from Users & keys.
AWS CLI (~/.aws/config):
[profile s3d]
+region = us-east-1
+endpoint_url = http://127.0.0.1:8000
+s3 =
+ addressing_style = path
+ aws --profile s3d s3 ls
+aws --profile s3d s3 sync ./music s3://my-drive/music
+aws --profile s3d s3 presign s3://my-drive/music/song.mp3 --expires-in 3600
+ rclone (rclone config, or ~/.config/rclone/rclone.conf):
[s3d]
+type = s3
+provider = Other
+access_key_id = YOUR_ACCESS_KEY_ID
+secret_access_key = YOUR_SECRET_KEY
+endpoint = http://127.0.0.1:8000
+region = us-east-1
+force_path_style = true
+ rclone ls s3d:my-drive
+rclone copy ./photos s3d:my-drive/photos --progress
+ Environment variables for SDKs and tools: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION=us-east-1, AWS_ENDPOINT_URL=http://127.0.0.1:8000.
http://<s3d address>/<drive>/<path>. On a default setup that address is reachable only from this computer; for other people s3d needs a public address (for example behind your own server and a TLS proxy).POST /snapshots to keep a copy of s3d's database on Sia.s3d login with the same indexer login and the same phrase, then restore the database snapshot or recreate users and keys.| What you see | What it means / what to do |
|---|---|
| "N files waiting to upload", or "0 B on Sia" | Files are still in the local buffer. Click Upload now (or s3d flush); automatic upload does it after 10 quiet minutes. |
| s3d "stopped" or "crashed" | Overview › Start; read Logs for the reason. "Not registered" means s3d login has not been done for this config. |
A link with 127.0.0.1 does not open elsewhere | Expected: it points to the computer running s3d. |
SignatureDoesNotMatch in an S3 app | Wrong secret, or the app uses virtual-host style; switch to path-style and region us-east-1. |
| "address already in use" | Another program (or another s3d) uses port 8000/8001; change apiAddress/adminAddress or stop the other one. |
| Pithos shows "external" | Another s3d is already running for this config; Pithos reads its stats but leaves it alone. |
| Pithos is locked | Your Theseus vault is locked; Unlock asks for the PIN. |
| A different account than expected | The account is the indexer login plus the phrase. Accounts › Which Sia account this is shows the account key; compare it on sia.storage under My apps › S3d. |
You are helping someone run s3d (the Sia S3 gateway), optionally through Pithos. Facts to rely on:
+127.0.0.1:8000, admin API on 127.0.0.1:8001 (Basic auth, empty user, adminPassword), region us-east-1, path-style addressing.s3d config → s3d login (indexer URL + 12-word phrase, approve the "S3d" app at the indexer) → run s3d → s3d users create → s3d keys create → use any S3 client.s3d flush or POST /objects/flush uploads them now.S3D_CONFIG_FILE, else the OS default path listed above.Rules: never ask the user to paste their recovery phrase or secret keys into the conversation; have them type secrets only into s3d or Pithos on their own machine. Prefer read-only checks (s3d status, s3d users list, aws s3 ls) before changing anything, and confirm before deleting users, keys, drives or files.