#!/usr/bin/env node // Web console: serves the Pithos UI in a browser. // // pithos-web loopback only, prints a sign-in link // pithos-web --listen 0.0.0.0:8700 remote access; requires PITHOS_PASSWORD // (or --password-file) and a TLS proxy in front // // Flags: --listen host:port, --config , --s3d , --bin-dir , // --password-file , --allow-host (repeatable) import fs from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { createPithos } from '../core/server.js'; const HERE = path.dirname(fileURLToPath(import.meta.url)); function parseArgs(argv) { const out = { allowHosts: [] }; for (let i = 0; i < argv.length; i++) { const a = argv[i]; const next = () => { if (i + 1 >= argv.length) fail(`${a} needs a value`); return argv[++i]; }; switch (a) { case '--listen': out.listen = next(); break; case '--config': out.config = next(); break; case '--s3d': out.s3d = next(); break; case '--bin-dir': out.binDir = next(); break; case '--password-file': out.passwordFile = next(); break; case '--allow-host': out.allowHosts.push(next().toLowerCase()); break; case '-h': case '--help': console.log(fs.readFileSync(fileURLToPath(import.meta.url), 'utf8').split('\n').slice(1, 11).map((l) => l.replace(/^\/\/ ?/, '')).join('\n')); process.exit(0); default: fail(`unknown flag ${a}`); } } return out; } function fail(msg) { console.error(`pithos-web: ${msg}`); process.exit(2); } const args = parseArgs(process.argv.slice(2)); const [host, portStr] = splitHostPort(args.listen || '127.0.0.1:8700'); const loopback = ['127.0.0.1', 'localhost', '::1'].includes(host); let password = process.env.PITHOS_PASSWORD || ''; if (args.passwordFile) password = fs.readFileSync(args.passwordFile, 'utf8').trim(); if (!loopback && password.length < 12) fail('listening beyond loopback needs PITHOS_PASSWORD or --password-file (12+ characters)'); const pithos = await createPithos({ host, port: Number(portStr), configFile: args.config, binary: args.s3d, binDir: args.binDir || HERE, password: password || undefined, allowedHosts: args.allowHosts, hostName: 'web', }); console.log(`Pithos web console on ${pithos.url}`); if (loopback) console.log(`Sign in: ${pithos.authUrl}`); else console.log('Sign in with the configured password. Put a TLS reverse proxy in front of this port.'); console.log(`s3d config: ${pithos.daemon.configFile}`); console.log(`s3d binary: ${pithos.daemon.binary || '(not found - install it from the console)'}`); const shutdown = async () => { console.log('stopping...'); await pithos.close(); process.exit(0); }; process.on('SIGINT', shutdown); process.on('SIGTERM', shutdown); function splitHostPort(s) { const m = s.match(/^\[?([^\]]+?)\]?:(\d+)$/); if (!m) fail(`--listen wants host:port, got ${s}`); return [m[1], m[2]]; }