How to Configure the LXC Backend in Microsoft MXC: Complete Setup Guide
To configure the LXC backend in Microsoft MXC, set containment: "lxc" in your JSON configuration and provide an lxc object specifying the Linux distribution and release for the container root filesystem.
Microsoft MXC (eXecution Container) enables secure code execution through Linux containers via its LXC backend. When you configure the LXC backend in MXC, the runner invokes the lxc-exec binary to create isolated environments with granular filesystem and network controls. This guide covers the complete configuration process based on the source implementation in the microsoft/mxc repository.
Prerequisites for LXC Backend Installation
Before configuring the LXC backend, install LXC and development libraries on your Linux host. Root privileges are typically required unless you configure unprivileged LXC containers.
For Debian or Ubuntu systems:
sudo apt install lxc lxc-utils liblxc-dev
For Fedora or RHEL systems:
sudo dnf install lxc lxc-devel
For Arch Linux:
sudo pacman -S lxc
These prerequisites enable the lxc-exec binary to interface with the host's LXC libraries as documented in docs/lxc-support/lxc-backend.md.
Architectural Components of the LXC Backend
The LXC implementation in MXC relies on several core structures defined in the source code.
ContainmentBackend::Lxc – The wire name "lxc" in your configuration triggers the MXC runner to invoke the LXC-specific execution path. This enum variant is defined in src/core/wxc_common/src/models.rs at lines 18-22.
LxcConfig – This struct captures the container image parameters. Located in src/core/wxc_common/src/models.rs at lines 56-64, it requires distribution and release fields that map directly to LXC template names.
LifecycleConfig – Controls container persistence through the destroy_on_exit boolean. When enabled, the container is automatically destroyed after script execution. See src/core/wxc_common/src/models.rs lines 5-8.
ContainerPolicy – Enforces security boundaries via bind-mounts and network rules. This includes read-only, read-write, and denied path specifications, implemented in src/core/wxc_common/src/models.rs at lines 27-38.
lxc-exec binary – The platform-specific wrapper located at src/core/lxc/src/main.rs that orchestrates container creation, policy application, script execution, and teardown.
Step-by-Step LXC Backend Configuration
1. Create the JSON Configuration File
Define a configuration file that selects the LXC backend and specifies the container environment. The lxc object is mandatory when containment is set to "lxc" and maps directly to the LxcConfig struct.
{
"schemaVersion": "0.6.0-alpha",
"containerId": "my-lxc-sandbox",
"containment": "lxc",
"lxc": {
"distribution": "alpine",
"release": "3.21"
},
"filesystem": {
"readwritePaths": ["/tmp/output"],
"readonlyPaths": ["/opt/tools"],
"deniedPaths": ["/etc/shadow"]
},
"network": {
"defaultPolicy": "block",
"allowedHosts": ["api.github.com"]
},
"lifecycle": {
"destroyOnExit": true
},
"script": "echo 'Hello from LXC'; uname -a"
}
The distribution and release values must correspond to valid LXC template names available on your host system.
2. Execute via Command Line Interface
Run the configuration using the lxc-exec binary built from the src/core/lxc crate.
Standard execution:
./lxc-exec config.json
Enable verbose diagnostics for troubleshooting:
./lxc-exec --debug config.json
For embedded tooling scenarios, pass the configuration as base64:
./lxc-exec --config-base64 <base64-encoded-config>
These CLI options are documented in docs/lxc-support/lxc-backend.md at lines 6-18.
3. Execute via TypeScript SDK
The MXC TypeScript SDK automatically selects lxc-exec when running on Linux hosts and the policy specifies LXC containment.
import { spawnSandbox, SandboxPolicy } from '@microsoft/mxc-sdk';
const policy: SandboxPolicy = {
filesystem: {
readwritePaths: ['/tmp/output'],
readonlyPaths: ['/opt/tools'],
},
network: {
allowOutbound: false,
},
};
const pty = spawnSandbox('echo hello from LXC', policy);
pty.onData(d => console.log(d));
pty.onExit(e => console.log('Exit code:', e.exitCode));
The SDK handles the JSON serialization and binary invocation as described in docs/lxc-support/lxc-backend.md at lines 22-38.
4. Manage Container Lifecycle
When destroyOnExit is set to false, containers persist after execution. Manually remove them using:
./lxc-exec --delete --containername my-lxc-sandbox
This command references the containerId specified in your original configuration.
Key Source Files for LXC Configuration
Understanding these files helps with advanced troubleshooting and custom builds:
src/core/wxc_common/src/models.rs– DefinesContainmentBackend,LxcConfig,LifecycleConfig, and policy structs used by the JSON parser.src/core/lxc/src/main.rs– Implements the nativelxc-execbinary that creates containers, applies bind-mounts and iptables rules, and manages execution.docs/lxc-support/lxc-backend.md– Human-readable guide covering prerequisites, schema definitions, and usage examples.tests/configs/basic_lxc.json– Minimal working configuration example used by the test suite.tests/scripts/run_lxc_*.sh– Shell scripts demonstrating end-to-end LXC test harness execution.
Summary
- Enable LXC backend by setting
containment: "lxc"in your MXC JSON configuration. - Specify container image using the
lxcobject withdistributionandreleasefields that map to LXC templates. - Control security boundaries through
filesystemandnetworkpolicies defined inContainerPolicy. - Manage persistence via the
lifecycle.destroyOnExitboolean; manual deletion uses./lxc-exec --delete. - Execute containers using either the
lxc-execCLI directly or the TypeScript SDK, which auto-detects Linux hosts.
Frequently Asked Questions
What LXC template names are valid for the distribution and release fields?
Valid values depend on templates installed on your host system. Common options include alpine with releases like 3.21, ubuntu with noble or jammy, and debian with bookworm. The lxc section maps directly to the LxcConfig struct in src/core/wxc_common/src/models.rs, which passes these values to the standard LXC template creation tools.
How do I troubleshoot LXC container startup failures?
Run the lxc-exec binary with the --debug flag to enable verbose logging: ./lxc-exec --debug config.json. This outputs detailed information about container creation, bind-mount operations, and network policy application. Check docs/lxc-support/lxc-backend.md for platform-specific prerequisites that might be missing.
Can I use unprivileged LXC containers with MXC?
Yes, but the host must be configured for unprivileged LXC usage with proper UID/GID mappings and subordinate ID ranges. The lxc-exec binary respects standard LXC configuration files, though the microsoft/mxc test suite assumes root privileges for full network and filesystem policy enforcement.
What happens when destroyOnExit is set to false?
The container remains on the host after script execution completes, allowing you to inspect the filesystem state or restart the container manually. You must subsequently delete it using ./lxc-exec --delete --containername <containerId> to free resources. This setting corresponds to the LifecycleConfig struct defined in src/core/wxc_common/src/models.rs.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →