fix: create jail-exec dir with correct permissions at provision time
The controlplane writes prompts to /var/tmp/jail-exec/ inside each worker jail. Previously this directory didn't exist and the jail root had no traverse permission for the agent user, causing EACCES. Now ensureJailExecDir() is called during: - provisionJail() in bastille-helpers.ts (all jails) - agent-jails.ts after pi install (worker jails) - verify-agent-jails.ts checks writability The function creates the dir, sets o+rx on the path components, and chowns to the agent user. Runs as root during setup. For clawdie-iso: the ISO runs the Clawdie-AI installer, so this fix covers both repos with no changes needed in clawdie-iso. --- Build: pass | Tests: 1533 passed, 5 failed (unchanged)
This commit is contained in:
parent
615d61db1d
commit
f78acb9123
3 changed files with 50 additions and 0 deletions
|
|
@ -23,6 +23,7 @@ import { commandExists, getPlatform, isRoot } from './platform.js';
|
|||
import { emitStatus } from './status.js';
|
||||
import {
|
||||
bastille,
|
||||
ensureJailExecDir,
|
||||
jailExists,
|
||||
detectFreeBSDRelease,
|
||||
jailRoot,
|
||||
|
|
@ -231,6 +232,9 @@ export async function run(args: string[]): Promise<void> {
|
|||
|
||||
ensurePiInstalled(jailName);
|
||||
|
||||
// Ensure jail-exec staging dir is writable by the agent user
|
||||
ensureJailExecDir(jailName, AGENT_NAME);
|
||||
|
||||
const chsh = bastille(
|
||||
'cmd',
|
||||
jailName,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { execSync, spawnSync } from 'child_process';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
|
|
@ -88,6 +89,35 @@ export interface ProvisionResult {
|
|||
created: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the jail-exec staging directory exists inside a jail and is writable
|
||||
* by the agent user. Called during provisioning so the controlplane can write
|
||||
* prompts into the jail at runtime.
|
||||
*
|
||||
* The directory is: /usr/local/bastille/jails/<name>/root/var/tmp/jail-exec
|
||||
* On the host, this must be readable/writable by the agent user (e.g. mevy).
|
||||
* Inside the jail, it appears at /var/tmp/jail-exec.
|
||||
*/
|
||||
export function ensureJailExecDir(jailName: string, agentUser: string): void {
|
||||
const jailExecHostPath = `/usr/local/bastille/jails/${jailName}/root/var/tmp/jail-exec`;
|
||||
fs.mkdirSync(jailExecHostPath, { recursive: true });
|
||||
// Ensure the agent user can traverse into the jail root and write to jail-exec.
|
||||
// This requires root (setup runs as root).
|
||||
try {
|
||||
execSync(`chmod o+rx /usr/local/bastille/jails/${jailName}/root`, { stdio: 'ignore' });
|
||||
execSync(`chmod o+rx /usr/local/bastille/jails/${jailName}/root/var`, { stdio: 'ignore' });
|
||||
execSync(`chmod o+rx /usr/local/bastille/jails/${jailName}/root/var/tmp`, { stdio: 'ignore' });
|
||||
} catch {
|
||||
// May fail if paths already have correct perms — non-fatal
|
||||
}
|
||||
try {
|
||||
execSync(`chown -R ${agentUser}:${agentUser} ${jailExecHostPath}`, { stdio: 'ignore' });
|
||||
} catch {
|
||||
// Non-fatal — agent user may not exist yet in the jail
|
||||
}
|
||||
logger.info({ jailName, path: jailExecHostPath }, 'jail-exec dir ready');
|
||||
}
|
||||
|
||||
export async function provisionJail(
|
||||
jailDef: JailDefinition,
|
||||
role: string,
|
||||
|
|
@ -175,5 +205,9 @@ export async function provisionJail(
|
|||
const runBastille = (args: string[]) => bastille(...args);
|
||||
maybeEnableTailscaleInJail(runBastille, jailName, jailName);
|
||||
|
||||
// Ensure jail-exec staging dir is writable by the agent user
|
||||
const agentUser = opts.agentName;
|
||||
ensureJailExecDir(jailName, agentUser);
|
||||
|
||||
return { jailName, ip, created: !exists };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,6 +165,18 @@ export function verifyJail(
|
|||
}
|
||||
result.envFileExists = true;
|
||||
|
||||
// 2b. jail-exec staging dir writable by agent user
|
||||
const jailExecPath = path.join(jailRoot(jailName), 'root', 'var', 'tmp', 'jail-exec');
|
||||
if (!fs.existsSync(jailExecPath)) {
|
||||
result.notes.push(`jail-exec dir not found at ${jailExecPath} — run: sudo npx tsx setup/agent-jails.ts`);
|
||||
} else {
|
||||
try {
|
||||
fs.accessSync(jailExecPath, fs.constants.W_OK);
|
||||
} catch {
|
||||
result.notes.push(`jail-exec dir not writable by current user: ${jailExecPath}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Parse keys
|
||||
const content = fs.readFileSync(envPath, 'utf-8');
|
||||
const presentKeys = parseEnvKeys(content);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue