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)
132 lines
3.5 KiB
TypeScript
132 lines
3.5 KiB
TypeScript
/**
|
|
* setup/ollama.ts — Provision the Ollama jail for local inference.
|
|
*
|
|
* Creates the jail if missing, installs ollama, enables the service,
|
|
* and starts it. Fully idempotent — safe to rerun.
|
|
*/
|
|
import { execSync, spawnSync } from 'child_process';
|
|
|
|
import {
|
|
FEATURE_OLLAMA,
|
|
FEATURE_OLLAMA_HPP,
|
|
LOCAL_LLM_PROVIDER,
|
|
OLLAMA_INTERNAL_DOMAIN,
|
|
OLLAMA_JAIL_IP,
|
|
RUNTIME_ID,
|
|
SUBNET_BASE,
|
|
} from '../src/config.js';
|
|
import { logger } from '../src/logger.js';
|
|
import { loadPackageList, mountPkgCacheInJail } from './packages.js';
|
|
import { getPlatform } 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> {
|
|
const explicitJailName = (process.env.OLLAMA_JAIL_NAME || '').trim();
|
|
const hostname = OLLAMA_INTERNAL_DOMAIN;
|
|
const runBastille = (args: string[]) => bastille(...args);
|
|
|
|
if (!FEATURE_OLLAMA && LOCAL_LLM_PROVIDER !== 'ollama') {
|
|
emitStatus('SETUP_OLLAMA', {
|
|
STATUS: 'skipped',
|
|
REASON: 'feature_disabled',
|
|
LOG,
|
|
});
|
|
logger.info(
|
|
'Ollama skipped — FEATURE_OLLAMA disabled and provider not ollama',
|
|
);
|
|
return;
|
|
}
|
|
|
|
if (getPlatform() !== 'freebsd') {
|
|
emitStatus('SETUP_OLLAMA', {
|
|
STATUS: 'failed',
|
|
ERROR: 'unsupported_platform',
|
|
LOG,
|
|
});
|
|
process.exit(1);
|
|
}
|
|
|
|
try {
|
|
const jailName = explicitJailName || `${RUNTIME_ID}-ollama`;
|
|
|
|
const exists = jailExists(jailName);
|
|
|
|
if (!exists) {
|
|
const release = detectFreeBSDRelease();
|
|
const gateway = process.env.WARDEN_GATEWAY || `${SUBNET_BASE}.1`;
|
|
const bridge = process.env.WARDEN_BRIDGE || 'warden0';
|
|
|
|
logger.info(
|
|
{ jailName, ip: OLLAMA_JAIL_IP, release },
|
|
'Creating Ollama jail',
|
|
);
|
|
const create = bastille(
|
|
'create',
|
|
// thin jail (no -T): model assets live outside the base userland.
|
|
'-B',
|
|
'-g',
|
|
gateway,
|
|
jailName,
|
|
release,
|
|
`${OLLAMA_JAIL_IP}/24`,
|
|
bridge,
|
|
);
|
|
if (!create.ok) {
|
|
throw new Error(`bastille create failed: ${create.output}`);
|
|
}
|
|
bastille('config', jailName, 'set', 'host.hostname', hostname);
|
|
bastille('restart', jailName);
|
|
} else {
|
|
logger.info(
|
|
{ jailName },
|
|
'Ollama jail already exists, skipping creation',
|
|
);
|
|
}
|
|
|
|
mountPkgCacheInJail(jailName);
|
|
const packages = loadPackageList('ollama-jail.txt');
|
|
if (FEATURE_OLLAMA_HPP) packages.push('ollama-hpp');
|
|
const pkg = bastille('pkg', jailName, 'install', '-y', ...packages);
|
|
if (!pkg.ok) {
|
|
logger.warn(
|
|
{ output: pkg.output },
|
|
'Ollama package install had warnings',
|
|
);
|
|
}
|
|
|
|
maybeEnableTailscaleInJail(runBastille, jailName, jailName);
|
|
|
|
bastille('sysrc', jailName, 'ollama_enable=YES');
|
|
const start = bastille('service', jailName, 'ollama', 'restart');
|
|
if (!start.ok) {
|
|
logger.warn(
|
|
{ output: start.output },
|
|
'Ollama service start had warnings',
|
|
);
|
|
}
|
|
|
|
emitStatus('SETUP_OLLAMA', {
|
|
STATUS: 'success',
|
|
JAIL_NAME: jailName,
|
|
JAIL_IP: OLLAMA_JAIL_IP,
|
|
OLLAMA_HPP: FEATURE_OLLAMA_HPP ? 'YES' : 'NO',
|
|
LOG,
|
|
});
|
|
} catch (error) {
|
|
const message = error instanceof Error ? error.message : String(error);
|
|
emitStatus('SETUP_OLLAMA', {
|
|
STATUS: 'failed',
|
|
ERROR: message,
|
|
LOG,
|
|
});
|
|
throw error;
|
|
}
|
|
}
|