s3d binds one Sia account per process, so the server runs one s3d per person (pithos-hosted), started on demand and flushed and stopped when idle. Only the connected s3d data folder moves between PC and server; the Sia recovery phrase never leaves the PC and nothing is re-uploaded to Sia. Because the server holds the connection key, local Pithos encrypts names and contents before they leave the machine, with keys from the Theseus vault (or a local key file elsewhere). What s3d cannot do on its own, the gateway now enforces: public folders, expiring share links and S3 keys for other people limited to one folder with read, add-only or edit rights. Files those reach are stored readable, since visitors have no key, and go back to encrypted when the rule is removed. Sign-up needs a BNS name signature, a deposit or an invite, with a per-IP limit.
39 lines
1.4 KiB
JavaScript
39 lines
1.4 KiB
JavaScript
#!/usr/bin/env node
|
|
// pithos-hosted entry: node hosted/main.js --config /etc/pithos-hosted.json
|
|
|
|
import fs from 'node:fs';
|
|
import { createHosted } from './server.js';
|
|
|
|
const DEFAULTS = {
|
|
listen: '127.0.0.1:8720',
|
|
publicUrl: 'https://s3.silentmode.st',
|
|
root: '/var/lib/pithos-hosted',
|
|
s3dBinary: null,
|
|
portBase: 21000,
|
|
maxRunning: 30,
|
|
idleMinutes: 30,
|
|
bufferLimitBytes: 2 * 1024 ** 3,
|
|
maxDataBytes: 4 * 1024 ** 3,
|
|
downloadCapBytes: 50 * 1024 ** 3,
|
|
trustProxy: false,
|
|
gate: { bns: { api: 'https://navigate.st' }, deposit: null, invites: [], perIpPerDay: 3 },
|
|
};
|
|
|
|
const i = process.argv.indexOf('--config');
|
|
const file = i > 0 ? process.argv[i + 1] : process.env.PITHOS_HOSTED_CONFIG;
|
|
if (!file) { console.error('usage: pithos-hosted --config <file.json>'); process.exit(2); }
|
|
const cfg = { ...DEFAULTS, ...JSON.parse(fs.readFileSync(file, 'utf8')) };
|
|
if (!cfg.s3dBinary || !fs.existsSync(cfg.s3dBinary)) { console.error(`s3dBinary not found: ${cfg.s3dBinary}`); process.exit(2); }
|
|
cfg.publicUrl = cfg.publicUrl.replace(/\/$/, '');
|
|
|
|
const hosted = await createHosted(cfg);
|
|
let stopping = false;
|
|
for (const sig of ['SIGTERM', 'SIGINT']) {
|
|
process.on(sig, async () => {
|
|
if (stopping) return;
|
|
stopping = true;
|
|
console.log(`${sig}: flushing and stopping every s3d`);
|
|
await hosted.close().catch((e) => console.error(e));
|
|
process.exit(0);
|
|
});
|
|
}
|