Remove completed controlplane agent-id migration, simplify jail-name resolution to current canonical names, and drop SUDO_UID ownership fallback from service setup. --- Build: pass | Tests: pass — 2370 passed (704 files)
146 lines
3.8 KiB
TypeScript
146 lines
3.8 KiB
TypeScript
/**
|
|
* setup/jails.ts — Provision the worker jail(s).
|
|
*
|
|
* Current main uses a persistent worker jail as a baseline sandbox. The agent
|
|
* runtime may still execute on the host depending on profile, but creating the
|
|
* worker jail keeps the FreeBSD jail layout consistent and ready.
|
|
*/
|
|
import { execSync, spawnSync } from 'child_process';
|
|
|
|
import { AGENT_INTERNAL_DOMAIN, SUBNET_BASE } from '../src/config.js';
|
|
import { logger } from '../src/logger.js';
|
|
import { loadPackageList, mountPkgCacheInJail } from './packages.js';
|
|
import { commandExists, getPlatform, isRoot } from './platform.js';
|
|
import { emitStatus } from './status.js';
|
|
import { maybeEnableTailscaleInJail } from './tailscale.js';
|
|
import {
|
|
bastille,
|
|
jailExists,
|
|
detectFreeBSDRelease,
|
|
} from './bastille-helpers.js';
|
|
|
|
const LOG = 'logs/setup.log';
|
|
|
|
export async function run(args: string[]): Promise<void> {
|
|
if (getPlatform() !== 'freebsd') {
|
|
emitStatus('SETUP_JAILS', {
|
|
STATUS: 'failed',
|
|
ERROR: 'unsupported_platform',
|
|
LOG,
|
|
});
|
|
process.exit(1);
|
|
}
|
|
if (!isRoot()) {
|
|
emitStatus('SETUP_JAILS', {
|
|
STATUS: 'failed',
|
|
ERROR: 'requires_root',
|
|
LOG,
|
|
});
|
|
throw new Error('setup_jails_requires_root');
|
|
}
|
|
if (!commandExists('bastille')) {
|
|
emitStatus('SETUP_JAILS', {
|
|
STATUS: 'failed',
|
|
ERROR: 'missing_bastille',
|
|
LOG,
|
|
});
|
|
throw new Error('missing_bastille');
|
|
}
|
|
|
|
const doCreate =
|
|
args.includes('--create') || args.includes('--create-worker');
|
|
if (!doCreate) {
|
|
emitStatus('SETUP_JAILS', {
|
|
STATUS: 'skipped',
|
|
REASON: 'missing_flag',
|
|
LOG,
|
|
});
|
|
logger.info('Jails step skipped — pass --create');
|
|
return;
|
|
}
|
|
|
|
const workerJail = 'worker';
|
|
const workerIp =
|
|
process.env.WORKER_JAIL_IP_START ||
|
|
process.env.WORKER_JAIL_IP ||
|
|
`${SUBNET_BASE}.101`;
|
|
|
|
const gateway = process.env.WARDEN_GATEWAY || `${SUBNET_BASE}.1`;
|
|
const bridge = process.env.WARDEN_BRIDGE || 'warden0';
|
|
const release = detectFreeBSDRelease();
|
|
|
|
try {
|
|
if (!jailExists(workerJail)) {
|
|
logger.info(
|
|
{ jail: workerJail, ip: workerIp, release },
|
|
'Creating worker jail',
|
|
);
|
|
const create = bastille(
|
|
'create',
|
|
// thin jail (no -T): worker jails do not need a copied base userland.
|
|
'-B',
|
|
'-g',
|
|
gateway,
|
|
workerJail,
|
|
release,
|
|
`${workerIp}/24`,
|
|
bridge,
|
|
);
|
|
if (!create.ok) {
|
|
throw new Error(`bastille create failed: ${create.output}`);
|
|
}
|
|
bastille(
|
|
'config',
|
|
workerJail,
|
|
'set',
|
|
'host.hostname',
|
|
`worker.${AGENT_INTERNAL_DOMAIN}`,
|
|
);
|
|
bastille('restart', workerJail);
|
|
} else {
|
|
logger.info(
|
|
{ jail: workerJail },
|
|
'Worker jail already exists, skipping creation',
|
|
);
|
|
}
|
|
|
|
mountPkgCacheInJail(workerJail);
|
|
const pkgs = loadPackageList('worker-jail.txt');
|
|
const pkg = bastille('pkg', workerJail, 'install', '-y', ...pkgs);
|
|
if (!pkg.ok) {
|
|
logger.warn(
|
|
{ output: pkg.output },
|
|
'Worker jail package install had warnings',
|
|
);
|
|
}
|
|
|
|
const chsh = bastille(
|
|
'cmd',
|
|
workerJail,
|
|
'chsh',
|
|
'-s',
|
|
'/usr/local/bin/bash',
|
|
'root',
|
|
);
|
|
if (!chsh.ok) {
|
|
logger.warn(
|
|
{ output: chsh.output },
|
|
'chsh to bash failed in worker jail',
|
|
);
|
|
}
|
|
|
|
const runBastille = (args: string[]) => bastille(...args);
|
|
maybeEnableTailscaleInJail(runBastille, workerJail, workerJail);
|
|
|
|
emitStatus('SETUP_JAILS', {
|
|
STATUS: 'success',
|
|
WORKER_JAIL_NAME: workerJail,
|
|
WORKER_JAIL_IP: workerIp,
|
|
LOG,
|
|
});
|
|
} catch (err) {
|
|
const message = err instanceof Error ? err.message : String(err);
|
|
emitStatus('SETUP_JAILS', { STATUS: 'failed', ERROR: message, LOG });
|
|
throw err;
|
|
}
|
|
}
|