Holesail URL Persist

This commit is contained in:
Raven Scott
2026-04-22 04:21:32 -04:00
parent 1b7381c137
commit eebf6a0e23
6 changed files with 47 additions and 4 deletions
+1
View File
@@ -5,6 +5,7 @@ Authoritative **version alignment** with protocol and telemetry schema numbers l
## Maintenance
- **`bare-os-www` initd** — Stock static HTTP server for **`~/.www`** on **`127.0.0.1:8088`** ( **`bare-os-www-initd.js`**, **`bare-os-www-holesail.js`** ); managed **Holesail** entry **`bare-www-<port>`** with **`host: 127.0.0.1`**; **`ensureBareOsWwwHomeDefaults`** after **`login`** (creates **`~/.www`** when missing); **`maybeRestartBareOsWwwAfterIdentity`** restarts the unit after unlock/register/`applyLoginKeys` and after **`logout`** so the listener tracks the current session **`HOME`** (not a stale closed-over **`ctx`**). Handbook [ch.4 § bare-os-www](../../handbook/04-the-booter-runtime.md#bare-os-www-static-http-for-www); env **`BARE_OS_WWW_*`** in [environment appendix](../../docs/reference/environment-and-posix-appendix.md).
- **Managed Holesail (`bare-holesail-managed.js`)** — When a **server** row in **`~/.holesail/state.json`** has no **`key`**, the booter persists the minted **`hs://…`** URL from the running **`Holesail`** instance after **`ready()`**, and **`holesail start …`** backfills the same when the process was already live. Restores stable tunnel URLs across boot and login.
- **Shell completion / Fish REPL:** canonical documentation is [`docs/reference/shell-completion-and-repl-editor.md`](../../docs/reference/shell-completion-and-repl-editor.md) (engine in **`lib/completion-engine.js`**, UI in **`lib/fish-readline.js`**, **`BARE_OS_FISH`**, **`BARE_OS_COMPACT_MENU`**).
- **`baretop` snapshot**: **`ctx.bareOsReadBareTopSnapshot({ lite: true })`** returns a reduced **`files`** map (see **`BARE_TOP_SNAPSHOT_LITE_ENTRIES`** in **`packages/bare-os-coreutils/lib/baretop-snapshot.js`**). Full batch includes **`securityPosture`** → **`/proc/bare_os/security_posture.json`**. **`metrics_live`** JSON uses **`schema: 4`** with embedded **`processTable`** when present; kernel counters include optional **`vfs.readfile.samples`** ( **`BARE_OS_VFS_READ_METRICS`** ), **`initd.unit_failed_final`**, and **`shell.pipeline_last_stages`** gauge from the shell.
- **`/proc/bare_os/net_summary.json`**: **`schemaVersion` 2** adds scalar **`replicationQueueDepth`**, firewall session totals, optional **`BARE_OS_BSD_SOCKET_BRIDGE_STATS_JSON`** merge into **`bsdSocketGuestBridge`**; **`peer_firewall_stats`** field alignment documented in **`bare-os-protocol`** channel handler.
@@ -187,6 +187,32 @@ export function bareHolesailManagedDebugEnabled(ctx, env) {
return bareHolesailEnvTruthy(env.BARE_OS_HOLESAIL_DEBUG)
}
/**
* After a managed **server** is in `managedInstances`, write the minted `hs://…` URL into
* `state.json` when `key` is missing so reboot / login restores the same tunnel identity.
* @param {Record<string, unknown>} ctx
* @param {Record<string, string | undefined>} env
* @param {string} id
*/
async function persistManagedServerHsUrlIfMissing(ctx, env, id) {
const url = bareHolesailManagedRuntimeUrl(id).trim()
if (!url) return
const { state } = await bareHolesailManagedReadState(ctx, env)
const cur = state.connections[id]
if (!cur || typeof cur !== 'object') return
const row = /** @type {Record<string, unknown>} */ (cur)
if (!bareHolesailEnvTruthy(row.server)) return
if (String(row.key ?? '').trim()) return
row.key = url
state.connections[id] = row
await bareHolesailManagedWriteState(ctx, env, state)
const rec = managedInstances.get(id)
if (rec && rec.entry && typeof rec.entry === 'object') {
/** @type {Record<string, unknown>} */ (rec.entry).key = url
}
logLine(ctx, `managed: persisted server key for ${id}`)
}
/**
* @param {Record<string, unknown>} ctx
* @param {string} id
@@ -202,6 +228,14 @@ async function startManagedInstance(ctx, env, id, entry) {
const hs = new Holesail(norm.entry)
await hs.ready()
managedInstances.set(id, { hs, entry: norm.entry })
if (norm.entry.server) {
try {
await persistManagedServerHsUrlIfMissing(ctx, env, id)
} catch (e) {
const msg = (e && /** @type {{ message?: string }} */ (e).message) || String(e)
logLine(ctx, `managed: persist key ${id} skipped: ${msg}`)
}
}
logLine(ctx, `managed: started ${id}`)
if (bareHolesailManagedDebugEnabled(ctx, env)) {
try {
@@ -355,6 +389,14 @@ export async function bareHolesailManagedStartOne(ctx, env, id) {
if (!norm.ok) throw new Error(norm.err)
if (!norm.entry.enabled) throw new Error(`holesail: ${idOk.id} is disabled`)
await startManagedInstance(ctx, env, idOk.id, norm.entry)
if (norm.entry.server) {
try {
await persistManagedServerHsUrlIfMissing(ctx, env, idOk.id)
} catch (e) {
const msg = (e && /** @type {{ message?: string }} */ (e).message) || String(e)
logLine(ctx, `managed: persist key ${idOk.id} (startOne): ${msg}`)
}
}
}
/**
@@ -21,7 +21,7 @@ Use when the user asks about **Holesail** in this repo: exposing TCP/UDP through
## Managed vs single-tunnel mode
- **Managed (default)** — **`BARE_OS_HOLESAIL_MANAGED=1`**. Persisted tunnel list in **`BARE_OS_HOLESAIL_STATE`** (default **`~/.holesail/state.json`**, on the **personal** drive under the session **`$HOME`**). On unit start, each **enabled** entry gets its own **`holesail`** instance. Operator CLI: **`holesail list`**, **`add`**, **`remove`**, **`start`**, **`stop`**, **`restart`**, **`enable`**, **`disable`**, plus **`path`** (prints resolved state path) and **`help`**.
- **Managed (default)** — **`BARE_OS_HOLESAIL_MANAGED=1`**. Persisted tunnel list in **`BARE_OS_HOLESAIL_STATE`** (default **`~/.holesail/state.json`**, on the **personal** drive under the session **`$HOME`**). On unit start, each **enabled** entry gets its own **`holesail`** instance. **Server** rows without **`key`** receive the minted **`hs://…`** string in **`state.json`** after **`ready()`** so the URL survives reboot/login (**`bare-holesail-managed.js`**). Operator CLI: **`holesail list`**, **`add`**, **`remove`**, **`start`**, **`stop`**, **`restart`**, **`enable`**, **`disable`**, plus **`path`** (prints resolved state path) and **`help`**.
- **Single tunnel** — Set **`BARE_OS_HOLESAIL_MANAGED=0`**, then exactly one of **`BARE_OS_HOLESAIL_SERVER=1`** or **`BARE_OS_HOLESAIL_CLIENT=1`**, and in client mode **`BARE_OS_HOLESAIL_KEY=…`**. Optional: **`BARE_OS_HOLESAIL_SECURE`**, **`PORT`**, **`HOST`**, **`UDP`**, **`LOG`**.
## Early booter (“kernel-path”) instance
@@ -21,7 +21,7 @@ Use when the user asks about **Holesail** in this repo: exposing TCP/UDP through
## Managed vs single-tunnel mode
- **Managed (default)** — **`BARE_OS_HOLESAIL_MANAGED=1`**. Persisted tunnel list in **`BARE_OS_HOLESAIL_STATE`** (default **`~/.holesail/state.json`**, on the **personal** drive under the session **`$HOME`**). On unit start, each **enabled** entry gets its own **`holesail`** instance. Operator CLI: **`holesail list`**, **`add`**, **`remove`**, **`start`**, **`stop`**, **`restart`**, **`enable`**, **`disable`**, plus **`path`** (prints resolved state path) and **`help`**.
- **Managed (default)** — **`BARE_OS_HOLESAIL_MANAGED=1`**. Persisted tunnel list in **`BARE_OS_HOLESAIL_STATE`** (default **`~/.holesail/state.json`**, on the **personal** drive under the session **`$HOME`**). On unit start, each **enabled** entry gets its own **`holesail`** instance. **Server** rows without **`key`** receive the minted **`hs://…`** string in **`state.json`** after **`ready()`** so the URL survives reboot/login (**`bare-holesail-managed.js`**). Operator CLI: **`holesail list`**, **`add`**, **`remove`**, **`start`**, **`stop`**, **`restart`**, **`enable`**, **`disable`**, plus **`path`** (prints resolved state path) and **`help`**.
- **Single tunnel** — Set **`BARE_OS_HOLESAIL_MANAGED=0`**, then exactly one of **`BARE_OS_HOLESAIL_SERVER=1`** or **`BARE_OS_HOLESAIL_CLIENT=1`**, and in client mode **`BARE_OS_HOLESAIL_KEY=…`**. Optional: **`BARE_OS_HOLESAIL_SECURE`**, **`PORT`**, **`HOST`**, **`UDP`**, **`LOG`**.
## Early booter (“kernel-path”) instance