From 00a908306de9bb50cf6b50a7973b1e25e2784435 Mon Sep 17 00:00:00 2001 From: Operator & Claude Code Date: Sat, 2 May 2026 08:20:32 +0200 Subject: [PATCH] Honor configured ZFS pool everywhere MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Codex caught zroot hardcodes in setup/sanoid.ts and setup/db.ts; same pattern remained in three more shipping locations: - scripts/backup.ts: jail and shared dataset paths - src/tenant-registry.ts: default tenant dataset list - setup/sanoid.ts: npm-global retention candidate Add zfsPool() helper to maintenance-snapshots.ts (where the analogous buildHostDbDatasets reads ZFS_POOL) and use it in all three. Operators running on non-default pools no longer get silently-wrong dataset paths in backup, tenant provisioning, or sanoid retention. Co-Authored-By: Claude Opus 4.7 --- Build: pass | Tests: pass — Tests 2099 passed (2099) --- scripts/backup.ts | 10 ++++++---- setup/sanoid.ts | 7 ++++--- src/maintenance-snapshots.ts | 6 +++++- src/tenant-registry.ts | 3 ++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/scripts/backup.ts b/scripts/backup.ts index 43e7014..1b91341 100644 --- a/scripts/backup.ts +++ b/scripts/backup.ts @@ -44,6 +44,7 @@ import { } from '../src/config.js'; import { formatDisplayDate, formatSnapshotStamp } from '../src/display-date.js'; import { hostd } from '../src/hostd/client.js'; +import { zfsPool } from '../src/maintenance-snapshots.js'; // ── CLI args ────────────────────────────────────────────────────────────────── @@ -151,17 +152,18 @@ function datasetExists(datasets: ZfsDatasetInfo[], name: string): boolean { } function buildSnapshotTargets(): string[] { + const pool = zfsPool(); const targets = [ - `zroot/${ZFS_PREFIX}/jails/${TENANT_ID}-db`, - `zroot/${ZFS_PREFIX}/jails/${TENANT_ID}-git`, - `zroot/${ZFS_PREFIX}/jails/${TENANT_ID}-cms`, + `${pool}/${ZFS_PREFIX}/jails/${TENANT_ID}-db`, + `${pool}/${ZFS_PREFIX}/jails/${TENANT_ID}-git`, + `${pool}/${ZFS_PREFIX}/jails/${TENANT_ID}-cms`, ]; const datasets = listZfsDatasets(); const homeDataset = detectHomeDataset(datasets, AGENT_HOME); if (homeDataset) targets.push(homeDataset); - const npmGlobalDataset = `zroot/${ZFS_PREFIX}/shared/npm-global`; + const npmGlobalDataset = `${pool}/${ZFS_PREFIX}/shared/npm-global`; if (datasetExists(datasets, npmGlobalDataset)) { targets.push(npmGlobalDataset); } diff --git a/setup/sanoid.ts b/setup/sanoid.ts index 4142e4d..88999e1 100644 --- a/setup/sanoid.ts +++ b/setup/sanoid.ts @@ -18,7 +18,7 @@ import { } from '../src/config.js'; import { readEnvFile } from '../src/env.js'; import { logger } from '../src/logger.js'; -import { buildHostDbDatasets } from '../src/maintenance-snapshots.js'; +import { buildHostDbDatasets, zfsPool } from '../src/maintenance-snapshots.js'; import { commandExists, getPlatform, isRoot } from './platform.js'; import { emitStatus } from './status.js'; @@ -277,8 +277,9 @@ export async function run(_args: string[]): Promise { : homeDataset && homePolicy === 'minimal' ? 'operator_home_minimal' : null; - const npmGlobalDataset = datasetExists(datasets, `zroot/${prefix}/shared/npm-global`) - ? `zroot/${prefix}/shared/npm-global` + const npmGlobalCandidate = `${zfsPool()}/${prefix}/shared/npm-global`; + const npmGlobalDataset = datasetExists(datasets, npmGlobalCandidate) + ? npmGlobalCandidate : null; const conf = buildSanoidConf(datasets, { homeDataset, homeTemplate, npmGlobalDataset }); diff --git a/src/maintenance-snapshots.ts b/src/maintenance-snapshots.ts index aa382a5..20d6912 100644 --- a/src/maintenance-snapshots.ts +++ b/src/maintenance-snapshots.ts @@ -26,8 +26,12 @@ export type HostdLike = ( params?: Record, ) => Promise; +export function zfsPool(): string { + return (process.env.ZFS_POOL || 'zroot').trim() || 'zroot'; +} + export function buildHostDbDatasets(): { data: string; wal: string } { - const pool = (process.env.ZFS_POOL || 'zroot').trim() || 'zroot'; + const pool = zfsPool(); const prefix = (ZFS_PREFIX || '').trim(); return { data: `${pool}/${prefix}/pgdata`, diff --git a/src/tenant-registry.ts b/src/tenant-registry.ts index b0239a1..146593e 100644 --- a/src/tenant-registry.ts +++ b/src/tenant-registry.ts @@ -6,6 +6,7 @@ import { Document, isMap, parse, parseDocument, stringify } from 'yaml'; import { z } from 'zod'; import { normalizeDbIdentifierBase } from './db-identifiers.js'; +import { zfsPool } from './maintenance-snapshots.js'; import { canonicalDatasetPath, datasetsOverlap, @@ -437,7 +438,7 @@ export function deriveTenantRecord( tenantWorkerJailName(id, 'db'), tenantWorkerJailName(id, 'git'), ], - datasets: options.datasets || [`zroot/${id}-ai`], + datasets: options.datasets || [`${zfsPool()}/${id}-ai`], }; }