signalk-container 1.17.0 → 1.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -14,7 +14,7 @@ Instead of each plugin implementing its own container orchestration, they delega
14
14
  - **Update detection** -- centralized "is there a newer image?" service for all consumer plugins. Auto-detects semver vs floating tags (`:latest`, `:main`), offline-tolerant with persistent cache, emits Signal K notifications, visible inline in the config panel. See the [developer guide](doc/plugin-developer-guide.md#update-detection).
15
15
  - **Resource limits editor** -- interactive UI in the config panel for setting CPU/memory/PID caps per container. Values are applied live via `podman update` when possible (no downtime), falls back to recreate when needed. Stored overrides are minimized against the consumer plugin's defaults so a future default bump flows through automatically. See the [developer guide](doc/plugin-developer-guide.md#resource-limits).
16
16
  - **Reset to plugin default** -- one-click restore of a container's original resource limits, clearing any user override.
17
- - **Per-process ulimits** -- `ContainerConfig.ulimits` pins per-process limits (`nofile`, `nproc`, …) on a container. A containerized process inherits these from the runtime, not the host sysctl, so raising the host `fs.file-max` alone does not lift a database's open-files limit; setting `ulimits` does. See the [developer guide](doc/plugin-developer-guide.md#per-process-ulimits-nofile-).
17
+ - **Per-process ulimits** -- `ContainerConfig.ulimits` pins per-process limits (`nofile`, `nproc`, …) on a container. A containerized process inherits these from the runtime, not the host sysctl, so raising the host `fs.file-max` alone does not lift a database's open-files limit; setting `ulimits` does. A `nofile` request over the host ceiling is clamped (not rejected) so the container still starts. See the [developer guide](doc/plugin-developer-guide.md#per-process-ulimits-nofile-) and, for raising the host limit, [Raising the open-files limit](#raising-the-open-files-limit-nofile).
18
18
  - **Image management** -- scheduled pruning of dangling images (weekly/monthly)
19
19
  - **Zero-config data dir sharing** -- `signalkDataMount` mounts the SignalK data directory into any managed container automatically, whether Signal K runs bare-metal, in Docker (named volume), or in Podman (named volume or bind mount). No host paths to configure.
20
20
  - **Zero-config config root sharing** -- `signalkConfigRootMount` mounts the entire SignalK installation config (`~/.signalk/`) — for backup, audit, or config-sync tools that need the whole tree, not the per-plugin subdirectory.
@@ -23,6 +23,7 @@ Instead of each plugin implementing its own container orchestration, they delega
23
23
  - **Per-volume host-source policy** -- volumes accept `{ source, ifMissing: "skip" | "abort" }` for user-managed (USB drives, NFS) or deployment-required (TLS certs) mounts. Plugins subscribe to `onVolumeIssue` events for `'skipped'`, `'aborted'`, and `'recovered'` actions; signalk-container auto-recreates the container when a previously-missing source reappears. See the [developer guide](doc/plugin-developer-guide.md#optional-and-required-volumes).
24
24
  - **Container log streaming** -- click **Logs** on any managed-container card to open a live-streaming popup of the container's stdout+stderr (combined, the same shape `podman logs <name>` produces). Plugin authors can also wire `onContainerLog` in `ensureRunning` options to forward the same stream into their plugin's `app.debug` channel — visible in the Signal K server log when debug is enabled. Multiple subscribers share a single underlying log stream. See the [developer guide](doc/plugin-developer-guide.md#streaming-container-logs-into-your-plugins-debug-channel).
25
25
  - **Host-UID ownership alignment** -- managed containers run by default under the Signal K host user's UID/GID (via `--user host:host` on Docker/rootful Podman, `--userns=keep-id` on rootless Podman). Files created on bind mounts are owned by the same identity that runs Signal K, with no `chmod` sweeps. Override per container via `ContainerConfig.user` for images with a non-root `USER` directive, or `user: false` to opt out. See the [developer guide](doc/plugin-developer-guide.md#host-uid-ownership).
26
+ - **Data-directory teardown** -- `containers.removeManagedData(name, hostPath)` removes a managed container _and_ deletes its bind-mount data, even on rootless Podman where a container process running as a non-root in-container UID writes files owned by a host **subuid** the Signal K user can't `rm`. The host-side delete is tried first (docker / rootful); on EACCES it falls back to an in-userns wipe using the container's own image (no extra pull). Use it for plugin uninstall cleanup. See the [developer guide](doc/plugin-developer-guide.md#removemanageddataname-hostpath-options-promisevoid).
26
27
  - **Image compliance probes** -- `containers.doctor.imageRunsAsUser(image, user?)` runs the image under the live UID mapping and verifies it can write `/tmp` as the host caller. Surfaces UID-compatibility problems _before_ a container wedges in a restart loop. See the [developer guide](doc/plugin-developer-guide.md#containersdoctorimagerunsasuserimage-user-promiseimageproberesult).
27
28
  - **Podman image qualification** -- automatically prefixes `docker.io/` for short image names
28
29
  - **Docker `host.containers.internal` parity** -- signalk-container adds the `host-gateway` mapping for Docker automatically (Podman has it natively). User-supplied `extraHosts` overrides are respected.
@@ -272,6 +273,91 @@ The deployment doctor at `/api/doctor/deployment` also detects this
272
273
  scenario and surfaces the same kernel-cmdline fix in its `remediation`
273
274
  array, so you don't have to guess which layer is broken first.
274
275
 
276
+ ### Raising the open-files limit (`nofile`)
277
+
278
+ Some managed containers ask for a high per-process open-files limit
279
+ (`RLIMIT_NOFILE`). QuestDB is the common case — it recommends
280
+ `nofile=1048576` and otherwise logs an open-files warning and risks WAL
281
+ corruption under heavy ingestion.
282
+
283
+ A containerized process inherits `nofile` from the **container runtime**,
284
+ not from the host's `fs.file-max` sysctl — so raising `fs.file-max` does
285
+ **not** help here. And under **rootless Podman** a container can never
286
+ raise its hard limit above the limit of the user that runs the runtime.
287
+ When a plugin requests more than the host allows, signalk-container clamps
288
+ the request to the host ceiling so the container still starts (you'll see
289
+ an advisory in the requesting plugin's config panel, e.g. QuestDB's
290
+ "open-files limit capped by the host"). To grant the full value, raise the
291
+ host limit.
292
+
293
+ **Check the limit the container actually got:**
294
+
295
+ ```bash
296
+ # podman, or `docker exec` on Docker
297
+ podman exec <sk-container> cat /proc/1/limits | grep -i "open files"
298
+ # Max open files 524288 524288 ← the per-process cap in effect
299
+ ```
300
+
301
+ **Rootless Podman** runs under the systemd user session, so the lever is the
302
+ user manager's open-files limit, which a rootless container can never exceed.
303
+ There are two places to set it; on stock Debian / Raspberry Pi OS you usually
304
+ need the **second**. Editing `/etc/security/limits.conf` does **not** help —
305
+ `pam_limits` only touches login shells, not the user manager that parents the
306
+ podman socket. `LimitNOFILE` takes a `soft:hard` form; a single number sets
307
+ soft = hard, and the container's hard ceiling is the user manager's _hard_
308
+ limit.
309
+
310
+ **1. Per-user-manager drop-in.** One-time, requires sudo:
311
+
312
+ ```bash
313
+ sudo mkdir -p /etc/systemd/system/user@.service.d
314
+ sudo tee /etc/systemd/system/user@.service.d/nofile.conf <<'EOF'
315
+ [Service]
316
+ LimitNOFILE=1048576
317
+ EOF
318
+ sudo systemctl daemon-reload
319
+ ```
320
+
321
+ The new limit only applies once the **user manager itself restarts** — and
322
+ `daemon-reload` does **not** restart an already-running `user@<uid>.service`.
323
+ On a headless boat the SK user has linger enabled (`loginctl enable-linger`),
324
+ so logging out and back in does not tear it down. Force a fresh user manager,
325
+ then restart the container:
326
+
327
+ ```bash
328
+ sudo systemctl restart user@$(id -u <sk-user>).service # or just reboot
329
+ ```
330
+
331
+ **2. System-wide default (Raspberry Pi OS / openplotter, and the reliable
332
+ fallback).** Stock Debian / Pi OS ships `/etc/systemd/system.conf` with a
333
+ commented `#DefaultLimitNOFILE=1024:524288` — that 524288 _hard_ default is
334
+ what bounds the per-unit request when step 1 doesn't take. Raise the system
335
+ (PID 1) manager's default directly:
336
+
337
+ ```bash
338
+ sudo sed -i 's/^#\?DefaultLimitNOFILE=.*/DefaultLimitNOFILE=1048576:1048576/' /etc/systemd/system.conf
339
+ sudo systemctl daemon-reexec # NOT daemon-reload — manager-global defaults
340
+ # are only re-read when PID 1 re-executes itself
341
+ sudo reboot # respawns the lingering user@.service + podman
342
+ # under the raised default
343
+ ```
344
+
345
+ **Rootful Podman / Docker** read the limit from the daemon's own service.
346
+ For Docker, set `LimitNOFILE=1048576` in a `docker.service` drop-in
347
+ (`/etc/systemd/system/docker.service.d/nofile.conf`), `daemon-reload`, and
348
+ restart the daemon.
349
+
350
+ The value cannot exceed the kernel's absolute per-process cap, `fs.nr_open`
351
+ (`cat /proc/sys/fs/nr_open` — typically ~1 billion, so not a practical limit).
352
+ Verify (either path):
353
+
354
+ ```bash
355
+ systemctl show user@$(id -u <sk-user>).service -p LimitNOFILE
356
+ # LimitNOFILE=1048576 ← the user manager now allows it
357
+ <runtime> exec <sk-container> cat /proc/1/limits | grep -i "open files"
358
+ # Max open files 1048576 1048576 ← the container actually got it
359
+ ```
360
+
275
361
  ### Watch out for systemd auto-restart (Quadlet / `Restart=always`)
276
362
 
277
363
  If you run Signal K via a podman Quadlet (`*.container` in
@@ -1,5 +1,5 @@
1
1
  import type Docker from "dockerode";
2
- import { ContainerConfig, ContainerInfo, ContainerRuntimeInfo, ContainerState, HealthCheckOptions, VolumeIssue, VolumeSpec } from "./types.js";
2
+ import { ContainerConfig, ContainerInfo, ContainerRuntimeInfo, ContainerState, EnsureRunningOptions, UlimitClamp, VolumeIssue, VolumeSpec } from "./types.js";
3
3
  import { StreamingProcessHandle } from "./runtime.js";
4
4
  import { type ContainerClient } from "./client.js";
5
5
  /**
@@ -126,6 +126,11 @@ export declare function safeInvokeVolumeIssue(handler: ((event: VolumeIssue) =>
126
126
  * is needed.
127
127
  */
128
128
  export declare function safeInvokeContainerLog(handler: ((line: string) => void | Promise<void>) | undefined, line: string, reportError: (err: unknown) => void): void;
129
+ /**
130
+ * Invoke an `onUlimitClamped` callback safely. Same shape and rationale
131
+ * as `safeInvokeVolumeIssue` — see that helper's doc.
132
+ */
133
+ export declare function safeInvokeUlimitClamped(handler: ((event: UlimitClamp) => void | Promise<void>) | undefined, event: UlimitClamp, reportError: (err: unknown) => void): void;
129
134
  /**
130
135
  * Spawn `podman logs -f --tail=N sk-<name>` (or `docker logs -f`)
131
136
  * and emit each line to `onLine`. Returns a stop-handle; the caller
@@ -446,7 +451,7 @@ export declare function ulimitsForRun(ulimits: ContainerConfig["ulimits"], nofil
446
451
  * without touching the network.
447
452
  */
448
453
  type PullFn = (runtime: ContainerRuntimeInfo, image: string, onProgress?: (msg: string) => void) => Promise<void>;
449
- export declare function ensureRunning(runtime: ContainerRuntimeInfo, name: string, config: ContainerConfig, debug: (msg: string) => void, options?: HealthCheckOptions, client?: ContainerClient,
454
+ export declare function ensureRunning(runtime: ContainerRuntimeInfo, name: string, config: ContainerConfig, debug: (msg: string) => void, options?: EnsureRunningOptions, client?: ContainerClient,
450
455
  /**
451
456
  * Prior `ContainerConfig` from the previous `ensureRunning` call within
452
457
  * this signalk-container lifetime, if any. Used to detect "unset" drift
@@ -459,6 +464,55 @@ prior?: ContainerConfig, _postRecreate?: boolean, _pull?: PullFn): Promise<void>
459
464
  export declare function startContainer(runtime: ContainerRuntimeInfo, name: string, client?: ContainerClient): Promise<void>;
460
465
  export declare function stopContainer(runtime: ContainerRuntimeInfo, name: string, client?: ContainerClient): Promise<void>;
461
466
  export declare function removeContainer(runtime: ContainerRuntimeInfo, name: string, client?: ContainerClient): Promise<void>;
467
+ /**
468
+ * Reject host paths that must never be recursively wiped. The guard is the
469
+ * cheap, always-correct floor (empty / `/` / a non-absolute path); the
470
+ * caller layers any deployment-specific "must be under the Signal K tree"
471
+ * check on top, where it has the data/config roots to compare against.
472
+ */
473
+ export declare function assertWipablePath(hostPath: string): void;
474
+ /**
475
+ * Result of one wipe-job run, mirroring the bits of `ContainerJobResult`
476
+ * that `removeManagedData` reasons about. Keeps `containers.ts` free of a
477
+ * `jobs.ts` import (jobs.ts already imports from here — the cycle would be
478
+ * real) while staying fully testable via an injected runner.
479
+ */
480
+ export interface WipeJobOutcome {
481
+ ok: boolean;
482
+ error?: string;
483
+ }
484
+ /**
485
+ * Delete a managed container's bind-mount data, working around the
486
+ * rootless-Podman subuid-ownership trap.
487
+ *
488
+ * Sequence:
489
+ * 1. Remove the container `name` (idempotent — a missing container is fine)
490
+ * so nothing holds the mount.
491
+ * 2. Try a direct host-side `fs.rm(hostPath, {recursive, force})`. On
492
+ * docker / rootful Podman the files are host-owned and this succeeds.
493
+ * 3. On EACCES/EPERM (the rootless-Podman case — files are owned by a
494
+ * subuid the host user can't touch) run `runWipeJob`: a one-shot helper
495
+ * that bind-mounts `hostPath` and `rm -rf`s its CONTENTS from inside the
496
+ * userns as in-container root, then retry the host-side delete to drop
497
+ * the now-empty host-owned parent dir.
498
+ *
499
+ * `runWipeJob(image, hostPath)` is injected so the runtime logic stays out
500
+ * of the `jobs.ts` import cycle and so unit tests can drive every branch
501
+ * without a real runtime. The wrapper in `index.ts` wires it to `runJob`
502
+ * with the container's own (already-present) image.
503
+ *
504
+ * `wipeImage` is the container's own image, captured from `inspect` BEFORE
505
+ * removal so the helper reuses bits already on disk — no registry pull on a
506
+ * possibly-offline boat. `null` when the container was already gone; the
507
+ * fallback then can't run, so a still-undeletable dir surfaces as an error.
508
+ */
509
+ export declare function removeManagedData(runtime: ContainerRuntimeInfo, name: string, hostPath: string, runWipeJob: (image: string, hostPath: string) => Promise<WipeJobOutcome>, client?: ContainerClient, onRemoved?: () => void): Promise<void>;
510
+ /**
511
+ * Container path the wipe helper mounts the data directory at — re-exported
512
+ * for the wrapper that builds the `runJob` config and for tests asserting the
513
+ * mount/command shape.
514
+ */
515
+ export declare const WIPE_MOUNT_PATH = "/sk-wipe-target";
462
516
  export declare function listContainers(runtime: ContainerRuntimeInfo, client?: ContainerClient): Promise<ContainerInfo[]>;
463
517
  export declare function pruneImages(runtime: ContainerRuntimeInfo, client?: ContainerClient): Promise<{
464
518
  imagesRemoved: number;
@@ -1 +1 @@
1
- {"version":3,"file":"containers.d.ts","sourceRoot":"","sources":["../src/containers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"containers.d.ts","sourceRoot":"","sources":["../src/containers.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,8 @@
1
1
  import * as net from "node:net";
2
+ import * as path from "node:path";
2
3
  import { PassThrough } from "node:stream";
3
4
  import { existsSync, readFileSync } from "node:fs";
5
+ import { rm } from "node:fs/promises";
4
6
  import { isContainerized, makeLineSplitter, userMappingFlags, } from "./runtime.js";
5
7
  import { demuxToText, demuxBufferToText, getClient, safe, safeInspect, } from "./client.js";
6
8
  import { resourcePayloadForRun } from "./resources.js";
@@ -209,6 +211,20 @@ export function safeInvokeContainerLog(handler, line, reportError) {
209
211
  reportError(err);
210
212
  }
211
213
  }
214
+ /**
215
+ * Invoke an `onUlimitClamped` callback safely. Same shape and rationale
216
+ * as `safeInvokeVolumeIssue` — see that helper's doc.
217
+ */
218
+ export function safeInvokeUlimitClamped(handler, event, reportError) {
219
+ if (!handler)
220
+ return;
221
+ try {
222
+ void Promise.resolve(handler(event)).catch(reportError);
223
+ }
224
+ catch (err) {
225
+ reportError(err);
226
+ }
227
+ }
212
228
  /**
213
229
  * Spawn `podman logs -f --tail=N sk-<name>` (or `docker logs -f`)
214
230
  * and emit each line to `onLine`. Returns a stop-handle; the caller
@@ -1324,7 +1340,7 @@ export function ulimitsForRun(ulimits, nofileCeiling, onClamp) {
1324
1340
  * Replaces the former `buildRunArgs` flag-array builder; the same fields
1325
1341
  * map onto the structured create payload (top-level vs `HostConfig`).
1326
1342
  */
1327
- function buildCreateOptions(name, config, runtime, healthcheck, debug = () => { }) {
1343
+ function buildCreateOptions(name, config, runtime, healthcheck, debug = () => { }, onClamp = () => { }) {
1328
1344
  const fullName = prefixedName(name);
1329
1345
  const imageRef = qualifyImage(config.digest
1330
1346
  ? `${config.image}@${config.digest}`
@@ -1413,8 +1429,12 @@ function buildCreateOptions(name, config, runtime, healthcheck, debug = () => {
1413
1429
  // rootless container asking for more than the calling user's hard limit
1414
1430
  // is rejected by crun and never starts, so we lower it (and log) rather
1415
1431
  // than let the container fail.
1416
- const ulimits = ulimitsForRun(config.ulimits, readNofileHardCeiling(runtime), (requested, granted) => debug(`nofile ulimit ${requested} exceeds this host's hard limit; clamped to ${granted}. ` +
1417
- `Raise the limit for the user running the container runtime to use a higher value.`));
1432
+ const ulimits = ulimitsForRun(config.ulimits, readNofileHardCeiling(runtime), (requested, granted) => {
1433
+ const reason = `nofile ulimit ${requested} exceeds this host's hard limit; clamped to ${granted}. ` +
1434
+ `Raise the limit for the user running the container runtime to use a higher value.`;
1435
+ debug(reason);
1436
+ onClamp({ ulimit: "nofile", requested, granted, reason });
1437
+ });
1418
1438
  if (ulimits)
1419
1439
  hostConfig.Ulimits = ulimits;
1420
1440
  const options = {
@@ -1565,7 +1585,7 @@ prior, _postRecreate = false, _pull = pullImage) {
1565
1585
  const healthcheck = config.healthcheck !== undefined
1566
1586
  ? null
1567
1587
  : await getImageHealthcheck(runtime, imageRef, client);
1568
- const createOpts = buildCreateOptions(name, config, runtime, healthcheck, debug);
1588
+ const createOpts = buildCreateOptions(name, config, runtime, healthcheck, debug, (event) => safeInvokeUlimitClamped(options?.onUlimitClamped, event, (err) => debug(`ensureRunning(${name}): onUlimitClamped handler threw: ${err instanceof Error ? err.message : String(err)}`)));
1569
1589
  const created = await createAndStart(client, createOpts);
1570
1590
  if (!created.ok && created.conflict) {
1571
1591
  // getContainerState reported "missing" because `inspect` failed,
@@ -1685,6 +1705,118 @@ export async function removeContainer(runtime, name, client = getClient()) {
1685
1705
  throw new Error(`Failed to remove ${fullName}: ${result.error.userMessage}`);
1686
1706
  }
1687
1707
  }
1708
+ /**
1709
+ * Container path the wipe helper mounts the data directory at. Arbitrary —
1710
+ * the only requirement is that it not collide with image-baked paths the
1711
+ * helper's `rm` might depend on; a dedicated top-level dir avoids that.
1712
+ */
1713
+ const WIPE_MOUNT = "/sk-wipe-target";
1714
+ /** Posix error codes that signal "the host user can't delete this" and so
1715
+ * warrant the in-userns fallback rather than a hard failure. */
1716
+ const OWNERSHIP_ERROR_CODES = new Set(["EACCES", "EPERM"]);
1717
+ /** True for the EACCES/EPERM ownership errors that the in-userns wipe can fix.
1718
+ * Anything else (ENOENT, ENOTEMPTY from a live mount, …) is not an ownership
1719
+ * problem and should surface unchanged. */
1720
+ function isOwnershipError(err) {
1721
+ const code = err?.code;
1722
+ return code !== undefined && OWNERSHIP_ERROR_CODES.has(code);
1723
+ }
1724
+ /**
1725
+ * Reject host paths that must never be recursively wiped. The guard is the
1726
+ * cheap, always-correct floor (empty / `/` / a non-absolute path); the
1727
+ * caller layers any deployment-specific "must be under the Signal K tree"
1728
+ * check on top, where it has the data/config roots to compare against.
1729
+ */
1730
+ export function assertWipablePath(hostPath) {
1731
+ // Require an absolute path: a relative value would `path.resolve` to a
1732
+ // cwd-relative dir and quietly pass the root check, risking an rm -rf of
1733
+ // the wrong tree. The data/config sources signalk-container deals with are
1734
+ // always absolute, so reject anything else outright. Normalize first so a
1735
+ // root-equivalent like `/..` collapses to the root and is rejected too.
1736
+ const normalized = path.normalize(hostPath || "");
1737
+ if (!hostPath ||
1738
+ hostPath.trim() === "" ||
1739
+ !path.isAbsolute(hostPath) ||
1740
+ normalized === path.parse(normalized).root) {
1741
+ throw new Error(`removeManagedData: refusing to delete unsafe path ${JSON.stringify(hostPath)}`);
1742
+ }
1743
+ }
1744
+ /**
1745
+ * Delete a managed container's bind-mount data, working around the
1746
+ * rootless-Podman subuid-ownership trap.
1747
+ *
1748
+ * Sequence:
1749
+ * 1. Remove the container `name` (idempotent — a missing container is fine)
1750
+ * so nothing holds the mount.
1751
+ * 2. Try a direct host-side `fs.rm(hostPath, {recursive, force})`. On
1752
+ * docker / rootful Podman the files are host-owned and this succeeds.
1753
+ * 3. On EACCES/EPERM (the rootless-Podman case — files are owned by a
1754
+ * subuid the host user can't touch) run `runWipeJob`: a one-shot helper
1755
+ * that bind-mounts `hostPath` and `rm -rf`s its CONTENTS from inside the
1756
+ * userns as in-container root, then retry the host-side delete to drop
1757
+ * the now-empty host-owned parent dir.
1758
+ *
1759
+ * `runWipeJob(image, hostPath)` is injected so the runtime logic stays out
1760
+ * of the `jobs.ts` import cycle and so unit tests can drive every branch
1761
+ * without a real runtime. The wrapper in `index.ts` wires it to `runJob`
1762
+ * with the container's own (already-present) image.
1763
+ *
1764
+ * `wipeImage` is the container's own image, captured from `inspect` BEFORE
1765
+ * removal so the helper reuses bits already on disk — no registry pull on a
1766
+ * possibly-offline boat. `null` when the container was already gone; the
1767
+ * fallback then can't run, so a still-undeletable dir surfaces as an error.
1768
+ */
1769
+ export async function removeManagedData(runtime, name, hostPath, runWipeJob, client = getClient(),
1770
+ // Invoked exactly once, the instant the container is removed (before the data
1771
+ // delete). Lets the caller tear down container-scoped state (ports, log
1772
+ // broker) only when removal actually happened — not on a pre-removal failure
1773
+ // such as a non-404 inspect error, when the container is still running.
1774
+ onRemoved = () => { }) {
1775
+ assertWipablePath(hostPath);
1776
+ // Capture the image before removal so the in-userns fallback can reuse it
1777
+ // (guaranteed present locally — the container was just running it).
1778
+ const fullName = prefixedName(name);
1779
+ const info = await safeInspect(() => client.getContainer(fullName).inspect());
1780
+ const wipeImage = typeof info?.Config?.Image === "string" ? info.Config.Image : null;
1781
+ await removeContainer(runtime, name, client);
1782
+ onRemoved();
1783
+ // Docker / rootful Podman: bind-mount files are host-owned, plain rm works.
1784
+ try {
1785
+ await rm(hostPath, { recursive: true, force: true });
1786
+ return;
1787
+ }
1788
+ catch (err) {
1789
+ if (!isOwnershipError(err))
1790
+ throw err;
1791
+ }
1792
+ // Rootless-Podman subuid case: the host user can't delete subuid-owned
1793
+ // files. Wipe the dir contents from inside the userns (as in-container
1794
+ // root, which owns them) using the container's own image, then retry the
1795
+ // host-side delete to drop the now-empty host-owned parent.
1796
+ if (!wipeImage) {
1797
+ throw new Error(`removeManagedData: ${hostPath} is not deletable by the Signal K user ` +
1798
+ `and the container's image is unknown (it was already removed), so the ` +
1799
+ `in-userns cleanup helper cannot run. Delete ${hostPath} manually.`);
1800
+ }
1801
+ const wipe = await runWipeJob(wipeImage, hostPath);
1802
+ if (!wipe.ok) {
1803
+ throw new Error(`removeManagedData: in-userns wipe of ${hostPath} failed: ${wipe.error ?? "unknown error"}`);
1804
+ }
1805
+ try {
1806
+ await rm(hostPath, { recursive: true, force: true });
1807
+ }
1808
+ catch (err) {
1809
+ const code = err.code ?? "unknown";
1810
+ throw new Error(`removeManagedData: ${hostPath} still not removable after in-userns wipe (${code}). ` +
1811
+ `Delete it manually.`, { cause: err });
1812
+ }
1813
+ }
1814
+ /**
1815
+ * Container path the wipe helper mounts the data directory at — re-exported
1816
+ * for the wrapper that builds the `runJob` config and for tests asserting the
1817
+ * mount/command shape.
1818
+ */
1819
+ export const WIPE_MOUNT_PATH = WIPE_MOUNT;
1688
1820
  export async function listContainers(runtime, client = getClient()) {
1689
1821
  const result = await safe(() => client.listContainers({
1690
1822
  all: true,