# How to Configure the LXC Backend in Microsoft MXC: Complete Setup Guide

> Configure the LXC backend in Microsoft MXC by setting containment to lxc and defining your container's distribution and release. Get the complete setup guide here.

- Repository: [Microsoft/mxc](https://github.com/microsoft/mxc)
- Tags: how-to-guide
- Published: 2026-06-07

---

**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:

```bash
sudo apt install lxc lxc-utils liblxc-dev

```

For Fedora or RHEL systems:

```bash
sudo dnf install lxc lxc-devel

```

For Arch Linux:

```bash
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`](https://github.com/microsoft/mxc/blob/main/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`](https://github.com/microsoft/mxc/blob/main/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`](https://github.com/microsoft/mxc/blob/main/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`](https://github.com/microsoft/mxc/blob/main/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`](https://github.com/microsoft/mxc/blob/main/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`](https://github.com/microsoft/mxc/blob/main/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.

```json
{
    "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:

```bash
./lxc-exec config.json

```

Enable verbose diagnostics for troubleshooting:

```bash
./lxc-exec --debug config.json

```

For embedded tooling scenarios, pass the configuration as base64:

```bash
./lxc-exec --config-base64 <base64-encoded-config>

```

These CLI options are documented in [`docs/lxc-support/lxc-backend.md`](https://github.com/microsoft/mxc/blob/main/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.

```typescript
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`](https://github.com/microsoft/mxc/blob/main/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:

```bash
./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`](https://github.com/microsoft/mxc/blob/main/src/core/wxc_common/src/models.rs)** – Defines `ContainmentBackend`, `LxcConfig`, `LifecycleConfig`, and policy structs used by the JSON parser.
- **[`src/core/lxc/src/main.rs`](https://github.com/microsoft/mxc/blob/main/src/core/lxc/src/main.rs)** – Implements the native `lxc-exec` binary that creates containers, applies bind-mounts and iptables rules, and manages execution.
- **[`docs/lxc-support/lxc-backend.md`](https://github.com/microsoft/mxc/blob/main/docs/lxc-support/lxc-backend.md)** – Human-readable guide covering prerequisites, schema definitions, and usage examples.
- **[`tests/configs/basic_lxc.json`](https://github.com/microsoft/mxc/blob/main/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 `lxc` object with `distribution` and `release` fields that map to LXC templates.
- **Control security boundaries** through `filesystem` and `network` policies defined in `ContainerPolicy`.
- **Manage persistence** via the `lifecycle.destroyOnExit` boolean; manual deletion uses `./lxc-exec --delete`.
- **Execute containers** using either the `lxc-exec` CLI 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`](https://github.com/microsoft/mxc/blob/main/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`](https://github.com/microsoft/mxc/blob/main/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`](https://github.com/microsoft/mxc/blob/main/src/core/wxc_common/src/models.rs).