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
// Pithos desktop: an Electron window over the same control server the web
// console runs. The server binds a random loopback port and the window signs
// in with the one-time secret, so nothing else on the machine can drive it.
const { app , BrowserWindow , shell , Menu , dialog } = require ( 'electron' ) ;
const path = require ( 'node:path' ) ;
const { pathToFileURL } = require ( 'node:url' ) ;
let pithos ;
let win ;
2026-10-04 20:45:04 +02:00
// Taskbar pins and notifications group under Pithos, not Electron.
if ( process . platform === 'win32' ) app . setAppUserModelId ( 'st.silentmode.pithos' ) ;
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
if ( ! app . requestSingleInstanceLock ( ) ) {
app . quit ( ) ;
} else {
app . on ( 'second-instance' , ( ) => {
if ( win ) { if ( win . isMinimized ( ) ) win . restore ( ) ; win . focus ( ) ; }
} ) ;
app . whenReady ( ) . then ( start ) . catch ( ( err ) => {
dialog . showErrorBox ( 'Pithos failed to start' , String ( err ? . stack || err ) ) ;
app . quit ( ) ;
} ) ;
}
async function start ( ) {
const { createPithos } = await import ( pathToFileURL ( path . join ( _ _dirname , '..' , 'core' , 'server.js' ) ) . href ) ;
pithos = await createPithos ( {
host : '127.0.0.1' ,
port : 0 ,
hostName : 'desktop' ,
configFile : process . env . S3D _CONFIG _FILE || undefined ,
// The pinned s3d release installs here, outside the (read-only) app bundle.
binDir : path . join ( app . getPath ( 'userData' ) , 'bin' ) ,
openExternal : ( url ) => shell . openExternal ( url ) ,
Pithos: open the app in a browser, also from the pithos.sia website
Pithos runs on the user's computer, so the pithos.sia website could only
describe it. Two ways in now:
- Open in browser (Theseus, desktop) opens the current page in the default
browser with a one-time sign-in link (60 s, single use), unlike the
host's reusable ?t= link.
- The website links to http://127.0.0.1:47621/open?path=/<user>/<drive>.
Any page or local program could follow that link, so the host first
asks the user in its own window (a native dialog on the desktop,
Theseus's approval prompt with the vault unlocked). Only loopback Host
names are accepted, one question at a time, and the website learns
nothing either way.
Sessions started this way are marked external, so the browser does not
get host-only controls such as Back to sidebar.
2026-10-05 01:47:12 +02:00
// The pithos.sia website's "Open my Pithos" lands here; the user decides.
confirmBrowserOpen : async ( ) => {
if ( ! win ) return false ;
if ( win . isMinimized ( ) ) win . restore ( ) ;
win . show ( ) ;
win . focus ( ) ;
const r = await dialog . showMessageBox ( win , {
type : 'question' ,
buttons : [ 'Open in browser' , 'Cancel' ] ,
defaultId : 1 ,
cancelId : 1 ,
title : 'Open Pithos in your browser?' ,
message : 'Open Pithos in your browser?' ,
detail : 'A browser on this computer asked to open Pithos, usually from "Open my Pithos" on the pithos.sia website. Allow it only if you just clicked that. That browser then has the same access as this window until you quit Pithos.' ,
} ) ;
return r . response === 0 ;
} ,
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
} ) ;
Menu . setApplicationMenu ( process . platform === 'darwin' ? Menu . buildFromTemplate ( [
{ role : 'appMenu' } , { role : 'editMenu' } , { role : 'viewMenu' } , { role : 'windowMenu' } ,
] ) : null ) ;
win = new BrowserWindow ( {
width : 1180 ,
height : 800 ,
minWidth : 380 ,
minHeight : 500 ,
title : 'Pithos' ,
backgroundColor : '#0f1214' ,
autoHideMenuBar : true ,
webPreferences : { contextIsolation : true , nodeIntegration : false , sandbox : true } ,
} ) ;
const origin = new URL ( pithos . url ) . origin ;
// Keep the window on the console; anything else goes to the system browser.
win . webContents . on ( 'will-navigate' , ( e , url ) => {
if ( new URL ( url ) . origin !== origin ) {
e . preventDefault ( ) ;
if ( url . startsWith ( 'https://' ) ) shell . openExternal ( url ) ;
}
} ) ;
win . webContents . setWindowOpenHandler ( ( { url } ) => {
Pithos: open HTML files as a page, or read them as text
An .html file in a drive could only be read as source. It can now also be
opened as a web page in a new tab (Theseus tab, browser tab, or the system
browser from the desktop app), with the CSS, images, scripts and pages
beside it loading as they would from a website.
The page is served under a sandbox CSP without allow-same-origin, so its
scripts run in an opaque origin: they cannot read the Pithos session or
reach its API, only the files of the folder the page link covers. Links
are random, last an hour from last use (12 hours at most), and refuse
paths that leave the folder. Pages decrypt on the fly for drives hosted
on Silent Mode.
2026-10-04 03:49:23 +02:00
// HTML files opened as pages go to the system browser: the link carries
// its own ticket, and the page is sandboxed by the server.
const u = new URL ( url ) ;
if ( u . origin === origin && u . pathname . startsWith ( '/page/' ) ) shell . openExternal ( url ) ;
else if ( url . startsWith ( 'https://' ) ) shell . openExternal ( url ) ;
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
return { action : 'deny' } ;
} ) ;
win . loadURL ( pithos . authUrl ) ;
win . on ( 'closed' , ( ) => { win = null ; } ) ;
}
let quitting = false ;
app . on ( 'before-quit' , ( e ) => {
if ( quitting || ! pithos ) return ;
// Stop s3d cleanly so its upload buffer and database are flushed to disk.
e . preventDefault ( ) ;
quitting = true ;
pithos . close ( ) . finally ( ( ) => app . quit ( ) ) ;
} ) ;
app . on ( 'window-all-closed' , ( ) => app . quit ( ) ) ;