diff --git a/src/commands/fuse.ts b/src/commands/fuse.ts index b111696..35b1ae1 100644 --- a/src/commands/fuse.ts +++ b/src/commands/fuse.ts @@ -259,9 +259,9 @@ async function mountLinux( config: { database: { path: string } pipeline: { stages: string[] } - mount: { readonly?: boolean } + mount: { readonly?: boolean; allow_other?: boolean } }, - opts: { readonly?: boolean }, + opts: { readonly?: boolean; allowOther?: boolean }, ) { const helperPath = join(homedir(), '.crm', 'bin', 'crm-fuse') @@ -326,6 +326,12 @@ async function mountLinux( if (opts.readonly || config.mount.readonly) { fuseArgs.unshift('-o', 'ro') } + if (opts.allowOther || config.mount.allow_other) { + // `user_allow_other` must be enabled in /etc/fuse.conf for this to work + // when the mount is invoked by a non-root user. The mount call will fail + // loudly if it isn't. + fuseArgs.unshift('-o', 'allow_other') + } const fuseProc = spawn(helperPath, fuseArgs, { stdio: 'ignore', @@ -437,6 +443,10 @@ export function registerFuseCommands(program: Command) { .description('Mount CRM as virtual filesystem') .argument('[mountpoint]', 'Mount point directory') .option('--readonly', 'Mount read-only') + .option( + '--allow-other', + 'Allow processes running as a different uid (e.g. root) to access the mount. Linux-only; requires user_allow_other in /etc/fuse.conf when invoked by a non-root user.', + ) .action(async (mountpoint, opts) => { const { config } = await getCtx() const mp = mountpoint || config.mount.default_path diff --git a/src/config.ts b/src/config.ts index 6d82785..137ff45 100644 --- a/src/config.ts +++ b/src/config.ts @@ -12,6 +12,13 @@ export interface CRMConfig { mount: { default_path: string readonly: boolean + /** + * Mount with `-o allow_other` so processes running as a different uid + * (e.g. root, container orchestrators) can read/write the FUSE filesystem. + * Requires `user_allow_other` in /etc/fuse.conf when the mount is invoked + * by a non-root user. Linux-only; ignored by the macOS NFS path. + */ + allow_other: boolean max_recent_activity: number search_limit: number } @@ -44,6 +51,7 @@ function defaultConfig(): CRMConfig { mount: { default_path: join(homedir(), 'crm'), readonly: false, + allow_other: false, max_recent_activity: 10, search_limit: 20, },