diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-08-22 12:29:32 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-08-22 12:29:32 +0200 |
| commit | 6d1ece3156c3ee7ce3fe1c19aabeb45b34d6436a (patch) | |
| tree | 1a739d995b97e0d7fddb632b62d6f13da75348a7 /packages/meshbay-client/src | |
| parent | 79130a9d4eb95db35b1d84f14f9b1b18d18299a7 (diff) | |
| download | meshbay-6d1ece3156c3ee7ce3fe1c19aabeb45b34d6436a.tar.gz | |
feat: node:start auto-provisions config and unlock key
When the wizard calls node:start with {hubUrl, username}, the handler
writes a minimal node.toml and a random unlock.key if they don't exist.
The daemon then creates the keystore on first start using the unlock
file — fully non-interactive.
Existing configs are left untouched: if node.toml or unlock.key already
exist, provisioning is skipped and the node starts as before.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-client/src')
| -rw-r--r-- | packages/meshbay-client/src/main.js | 35 | ||||
| -rw-r--r-- | packages/meshbay-client/src/preload.js | 2 |
2 files changed, 35 insertions, 2 deletions
diff --git a/packages/meshbay-client/src/main.js b/packages/meshbay-client/src/main.js index 22e0162..8dcc2ae 100644 --- a/packages/meshbay-client/src/main.js +++ b/packages/meshbay-client/src/main.js @@ -744,7 +744,36 @@ function registerBridge() { } catch { return null; } } - ipcMain.handle('node:start', async () => { + function provisionNode(hubUrl, username) { + const configDir = path.join(os.homedir(), '.config', 'meshbay'); + fs.mkdirSync(configDir, { recursive: true }); + + const configFile = nodeConfigPath(); + if (!fs.existsSync(configFile)) { + const toml = [ + '[hub]', + `url = "${hubUrl}"`, + `username = "${username}"`, + '', + '[node]', + 'quic_port = 19010', + 'ui_port = 18000', + '', + '[keystore]', + `unlock_file = "${path.join(configDir, 'unlock.key')}"`, + '', + ].join('\n'); + fs.writeFileSync(configFile, toml, { mode: 0o600 }); + } + + const unlockFile = path.join(configDir, 'unlock.key'); + if (!fs.existsSync(unlockFile)) { + const key = crypto.randomBytes(32).toString('base64url'); + fs.writeFileSync(unlockFile, key + '\n', { mode: 0o600 }); + } + } + + ipcMain.handle('node:start', async (_e, opts) => { const already = await probeNode(); if (already) return { started: true, ...already }; @@ -752,6 +781,10 @@ function registerBridge() { throw new Error('Automatic node start is only supported on Linux'); } + if (opts && opts.hubUrl && opts.username) { + provisionNode(opts.hubUrl, opts.username); + } + const deadline = Date.now() + 15000; const configFile = nodeConfigPath(); let launched = false; diff --git a/packages/meshbay-client/src/preload.js b/packages/meshbay-client/src/preload.js index c8553a5..f240995 100644 --- a/packages/meshbay-client/src/preload.js +++ b/packages/meshbay-client/src/preload.js @@ -87,7 +87,7 @@ contextBridge.exposeInMainWorld('meshbay', { node: { detect: () => ipcRenderer.invoke('node:detect'), installed: () => ipcRenderer.invoke('node:installed'), - start: () => ipcRenderer.invoke('node:start'), + start: (opts) => ipcRenderer.invoke('node:start', opts), call: (method, path, body) => ipcRenderer.invoke('node:call', method, path, body), pairingCode: () => ipcRenderer.invoke('node:pairing-code'), setPairingCode: (code) => ipcRenderer.invoke('node:set-pairing-code', code), |