node-lxc
    Preparing search index...

    node-lxc

    node-lxc

    Node.js native bindings for LXC (Linux Containers) — a complete, production-ready wrapper around liblxc built with N-API.

    npm version license Node.js ≥ 12 Platform: Linux

    • Full lifecycle control — create, start, stop, reboot, shutdown, destroy
    • Async-first — all blocking operations return Promises backed by a libuv thread pool
    • Interactive console — non-blocking console sessions with EventEmitter interface
    • Rich configuration API — get, set, clear, and bulk-read container configuration
    • Snapshot support — create, list, restore, and destroy snapshots
    • CRIU integration — checkpoint, restore, and live-migrate containers
    • Mount injection — bind-mount paths into running containers without restart
    • Resource metrics — async cgroup stat reads (memory, CPU, block I/O)
    • Network management — attach/detach interfaces, query IPs and interfaces
    • Device hotplug — add/remove device nodes into running containers
    • Seccomp support — retrieve seccomp notification file descriptors
    • Memory-safe — no leaks; all heap buffers freed, all async captures by value
    • TypeScript — full type declarations included
    • Node.js ≥ 12.17
    • LXC ≥ 4.0 (runtime library only)

    Install LXC on Debian/Ubuntu:

    sudo apt install lxc
    

    Verify your kernel supports LXC features:

    lxc-checkconfig
    
    npm install node-lxc
    

    Pre-built binaries are included for the following platforms — no compilation step required:

    Architecture GNU triplet
    x86-64 x86_64-linux-gnu
    ARM64 aarch64-linux-gnu

    Other Linux architectures must be built from source.

    import { Container, GetVersion } from "node-lxc";

    console.log("LXC", GetVersion()); // e.g. "5.0.2"

    // Create and start a container
    const c = new Container("my-container");

    await c.create({
    template: "download",
    argv: ["--dist", "ubuntu", "--release", "jammy", "--arch", "amd64"],
    });

    c.setConfigItem("lxc.net.0.type", "veth");
    c.setConfigItem("lxc.net.0.link", "lxcbr0");
    c.setConfigItem("lxc.net.0.flags", "up");

    await c.start();
    console.log(c.state); // "RUNNING"
    console.log(c.initPID); // e.g. 12345

    // Run a command and get the exit code
    const code = await c.exec({ argv: ["/bin/sh", "-c", "echo hello"] });
    console.log(code); // 0

    await c.shutdown(30);
    await c.destroy();
    import {
    GetVersion, // → string
    GetGlobalConfigItem, // (key: string) → string
    ListAllContainers, // (lxcpath?: string) → string[]
    ListAllDefinedContainers, // (lxcpath?: string) → string[]
    ListAllActiveContainers, // (lxcpath?: string) → string[]
    ConfigItemIsSupported, // (key: string) → boolean
    HasApiExtension, // (extension: string) → boolean
    GetWaitStates, // () → string[]
    } from "node-lxc";
    const c = new Container(name: string, configPath?: string, alt_file?: string);
    
    Parameter Description
    name Container name
    configPath LXC container directory (defaults to lxc.lxcpath)
    alt_file Alternate configuration file path
    await c.create({ template?, argv?, bdevtype?, bdev_specs?, flags? });
    await c.start(useinit?, argv?);
    await c.stop();
    await c.reboot(timeout?); // → Promise<boolean>
    await c.shutdown(timeout?); // → Promise<boolean>
    await c.freeze();
    await c.unfreeze();
    await c.destroy({ include_snapshots?, force? });
    await c.clone(options); // → Promise<Container>
    c.name                   // string
    c.defined // boolean
    c.running // boolean
    c.state // ContainerState ("RUNNING" | "STOPPED" | ...)
    c.initPID // number (-1 if not running)
    c.error // { num: number, string: string | null }
    c.daemonize // boolean (get/set)
    c.configPath // string (get/set)
    c.configFileName // string
    c.mayControl() // → boolean
    await c.initPIDFd() // → number (pidfd)
    await c.devptsFd() // → number
    c.getConfigItem(key)              // → string | null
    c.setConfigItem(key, value)
    c.clearConfigItem(key)
    c.clearConfig()
    c.getRunningConfigItem(key) // → string | null (live, running container)
    c.getKeys(prefix?) // → string[]
    c.getConfigItems(prefix?) // → Record<string, string | null>
    await c.loadConfig(alt_file)
    await c.save(alt_file)
    // Run a command; returns its exit code
    await c.exec({ argv: string[], ...lxc_attach_options }) // → number

    // Run a command and capture all output
    const { exitCode, stdout, stderr } = await c.execOutput({ argv: ["/bin/hostname"] });

    // Run a command and stream output as events
    const session = await c.execAsync({ argv: ["/usr/bin/top", "-b", "-n1"] });
    session
    .on("stdout", (chunk: Buffer) => process.stdout.write(chunk))
    .on("stderr", (chunk: Buffer) => process.stderr.write(chunk))
    .on("exit", (code: number) => console.log("exit:", code));
    session.kill(); // send SIGTERM
    session.kill(9); // send SIGKILL

    // Open a shell; returns the shell's exit code
    await c.attach(options?) // → number

    // Non-blocking async console session (EventEmitter)
    const session = await c.consoleAsync(ttynum?) // → ConsoleSession
    session.on("data", (chunk: Buffer) => { ... });
    session.on("close", () => { ... });
    session.write(data);
    session.resize(cols, rows);
    session.close();

    // Blocking console (connects current stdio)
    await c.console(ttynum, [stdinfd, stdoutfd, stderrfd], escape);

    // Raw TTY allocation
    const [ttyfd, ptxfd] = await c.consoleGetFds(ttynum?);
    const stats: ContainerStats = await c.stats();
    // {
    // "memory.usage_in_bytes": string | null,
    // "memory.limit_in_bytes": string | null,
    // "memory.memsw.usage_in_bytes": string | null,
    // "cpuacct.usage": string | null,
    // "cpu.stat": string | null,
    // "blkio.throttle.io_service_bytes": string | null,
    // }
    await c.getInterfaces()                              // → string[]
    await c.getIPs(iface, "inet") // → string[] (IPv4)
    await c.getIPs(iface, "inet6", scope) // → string[] (IPv6)
    await c.attachInterface(dev, dst_dev?)
    await c.detachInterface(dev, dst_dev?)
    await c.addDeviceNode(src_path, dest_path?)
    await c.removeDeviceNode(src_path, dest_path?)
    c.getCGroupItem(subsys) // → string | undefined
    c.setCGroupItem(subsys, value)
    await c.snapshot(commentfile)                      // → number (snap index)
    await c.snapshotList() // → lxc_snapshot[]
    await c.snapshotRestore(snapname, newname?)
    await c.snapshotDestroy(snapname)
    await c.snapshotDestroy(true) // destroy all
    await c.mount(source, target, filesystemtype, mountflags, mnt)
    await c.umount(source, mountflags, mnt)
    await c.checkpoint(directory, stop?, verbose?)
    await c.restore(directory, verbose?)
    await c.migrate(cmd: LXC_MIGRATE, options?)
    await c.seccompNotifyFd()        // → number
    await c.seccompNotifyFdActive() // → number
    await c.consoleLog({ clear?, read?, read_max? })  // → string
    

    The examples/ directory contains runnable scripts for common use cases:

    Script Description
    examples/create/ Create a container from a template
    examples/start/ Start a container
    examples/execute/ Run a command in a container
    examples/attach/ Open a shell in a container
    examples/console_async/ Non-blocking console session
    examples/clone/ Clone a container
    examples/checkpoint/ CRIU checkpoint/restore
    examples/concurrent_create/ Concurrent container creation
    examples/stats/ Read cgroup resource metrics
    examples/images/ Browse available LXC images

    Run any example with ts-node:

    npm run example:create
    npm run example:execute
    npm run example:console_async

    Required additional dependencies:

    Tool Version
    liblxc-dev same as LXC
    g++ ≥ 7
    cmake any recent
    sudo apt install lxc lxc-dev g++ cmake
    

    Clone and build:

    git clone https://github.com/SourceRegistry/node-lxc.git
    cd node-lxc
    npm install
    npx node-gyp configure && npx node-gyp build
    npx tsc --build
    npm test
    

    The test suite uses Node.js's built-in node:test runner. Tests that require root access (container create/start/stop/destroy) are automatically skipped unless the process is running as root.

    To run the full integration test suite:

    sudo npm test
    

    Bug reports and pull requests are welcome on GitHub.

    Please ensure:

    • New C++ code uses std::unique_ptr<char[]> for heap buffers
    • Async lambda captures use by-value ([this, var] not [this, &var])
    • All public API changes include TypeScript type updates and JSDoc

    Apache 2.0 © 2026 ProjectSource V.O.F.