LXC and LXD: System Containers

Khimananda Oli 9 min read Database
LXC and LXD: System Containers

By Khimananda Oli | Last reviewed: August 2026

LXC and LXD: System Containers provide a distinct middle ground between traditional virtual machines and application containers like Docker. While application containers package a single process, system containers run a complete Linux distribution with its own init system, networking stack, and user space. This makes secure server provisioning faster and more resource-efficient than spinning up full KVM instances, while maintaining the isolation boundaries required for multi-tenant hosting or legacy workload migration.

System Containers (LXC/LXD)Full Guest OS (Ubuntu/Debian)systemd + SSH + AptDedicated Init & NetworkingPersistent FilesystemKernel Namespaces/CgroupsShared Host KernelApp Containers (Docker)Single Process/BinaryEphemeral LayersNo Init SystemUnion FS OverlayKernel Namespaces/CgroupsShared Host KernelVirtual Machines (KVM)Full Guest OSIndependent KernelHardware EmulationVirtual Block DevicesHypervisor LayerHost Hardware
LXC and LXD system containers share the host kernel like Docker but provide full OS semantics unlike ephemeral app containers.

What are LXC and LXD: System Containers and how do they differ from Docker?

The distinction between system containers and application containers is fundamental to choosing the right tool. LXC (Linux Containers) is the low-level userspace interface for the kernel's containment features: namespaces, cgroups, and seccomp. It provides the raw primitives to isolate processes. LXD (pronounced "lex-dee") sits on top of LXC as a system container manager, offering a REST API, image store, snapshot management, and clustering capabilities that make it viable for production infrastructure.

Docker and similar OCI runtimes focus on packaging a single application and its dependencies into an immutable artifact. They typically lack a full init system, rely on union filesystems for ephemeral layers, and expect configuration via environment variables or mounted configs. In contrast, LXC and LXD: System Containers behave like traditional servers. You can SSH into them, install packages with apt, manage services with systemctl, and persist data natively. This makes them ideal for lifting-and-shifting legacy applications that assume a full OS environment, or for creating secure, multi-user development sandboxes where developers need root access within their isolated boundary.

A common mistake I see in Nepal-based hosting environments is trying to force stateful, complex applications into Docker containers when a system container would be operationally simpler. If your workload requires cron daemons, syslog, multiple interdependent services, or expects to write to standard filesystem paths without volume mounts, you are fighting the application container model. System containers embrace these requirements while still providing the density benefits of containerization.

How do you install and configure LXD for production workloads?

Setting up LXD correctly from the start prevents significant operational pain later. On Ubuntu 24.04 LTS and newer, LXD ships as a snap package, which ensures you receive upstream updates independently of the base OS release cycle. For production systems, always use the stable channel and avoid mixing snap and PPA installations.

# Install LXD stable channel
sudo snap install lxd --channel=latest/stable

# Initialize with production-safe defaults
sudo lxd init --auto --storage-backend=zfs --storage-size=100GiB

# Verify daemon status and version
lxc version
lxc info

The initialization step above uses ZFS as the storage backend, which is critical for production. ZFS provides copy-on-write snapshots, instant cloning, and compression — features that make LXC and LXD: System Containers genuinely powerful for testing, staging, and rollback workflows. Without ZFS (or btrfs), you lose atomic snapshots and must rely on slower file-copy operations.

Configuring network bridges and profiles

Default LXD installations create a NAT bridge (lxdbr0). For production, you often need containers on your physical LAN with routable IPs. Create a dedicated bridge profile before launching containers:

# Create a managed bridge connected to physical NIC
lxc network create br-physical ipv4.address=192.168.10.1/24 \
  ipv4.nat=false parent=enp3s0 type=bridge

# Create a production profile using the physical bridge
lxc profile create prod-network
lxc profile device add prod-network eth0 nic name=eth0 \
  network=br-physical type=nic

# Apply profile to existing container
lxc profile add my-container prod-network

Always separate your container profiles by concern: one for networking, one for resource limits, one for security policies. This composability mirrors infrastructure-as-code principles and makes your server hardening strategy auditable and reproducible. Never modify the default profile directly; create explicit named profiles for each workload class.

How do you manage storage, snapshots, and backups in LXD?

Storage management is where LXC and LXD: System Containers shine compared to both VMs and application containers. With a ZFS or btrfs backend, snapshots are metadata-only operations that complete in milliseconds regardless of container size. This enables workflows that are impractical elsewhere: pre-upgrade snapshots, per-feature branch test environments cloned from golden images, and instant rollbacks.

# Create a snapshot before risky changes
lxc snapshot web-prod pre-migration-20260812

# Restore instantly if migration fails
lxc restore web-prod pre-migration-20260812

# Clone a container for staging (copy-on-write, no data duplication)
lxc copy web-prod web-staging --refresh

# List all snapshots with timestamps
lxc list web-prod --format=json | jq '.[].snapshots'

For backup strategies, distinguish between local snapshots (fast, same-storage-pool) and exported backups (portable, cross-host). Exported backups compress the entire container including metadata and are suitable for offsite disaster recovery. Integrate export commands into your existing backup automation rather than treating LXD as a separate silo.

# Export container to portable archive
lxc export web-prod /backup/lxd/web-prod-20260812.tar.gz --optimized-storage

# Import on different host
lxc import /backup/lxd/web-prod-20260812.tar.gz web-prod-restored

The --optimized-storage flag is essential: it leverages the storage driver's native send/receive mechanism instead of tarballing the entire filesystem. On ZFS, this means only changed blocks are transferred, reducing backup windows from hours to minutes for large containers.

Production Containerweb-prod (running)Snapshotpre-migration (COW)Staging Cloneweb-staging (instant)Restored StateRollback targetExported Backup.tar.gz (offsite)lxc snapshotlxc copylxc restorelxc export
LXD snapshot workflow: instant COW snapshots enable safe migrations, staging clones, and rapid rollbacks for system containers.

When should you choose LXC and LXD: System Containers over VMs or Kubernetes?

Choosing between system containers, VMs, and orchestration platforms depends on workload characteristics, not hype. The following comparison reflects real trade-offs observed across production deployments in 2026:

CriterionLXC/LXD System ContainersVirtual Machines (KVM)Kubernetes Pods
Boot TimeSeconds30–120 secondsSub-second (if image cached)
Memory OverheadNear-zero (shared kernel)512MB+ per guest OSMinimal (pause/containerd)
OS CompatibilityLinux only (same kernel ABI)Any OS (Windows, BSD, Linux)Linux only (OCI runtime)
Persistence ModelNative filesystem, block devicesVirtual disks, passthroughVolumes, CSI drivers
Security IsolationNamespaces + AppArmor/seccompHardware-assisted (VT-x/EPT)Namespaces + network policies
Operational ComplexityLow (like managing servers)Medium (hypervisor + guest mgmt)High (cluster ops, CRDs, operators)
Best ForLegacy apps, dev sandboxes, dense hostingUntrusted tenants, non-Linux, complianceMicroservices, auto-scaling apps

Choose LXC and LXD: System Containers when you need the density of containers with the operational familiarity of VMs. They excel for CI runner fleets, database testing environments, multi-user development platforms, and hosting legacy monoliths that cannot be easily refactored into microservices. Avoid them when you need Windows guests, hardware-level isolation for untrusted code, or elastic auto-scaling driven by HTTP request rates — those are VM and Kubernetes domains respectively.

In Nepalese infrastructure contexts where budget constraints limit hardware procurement, system containers offer 3–5x higher density than VMs on the same physical server. This directly translates to cost savings for SMEs running multiple client environments on limited hardware. However, never sacrifice security isolation for density: always enable AppArmor profiles, restrict privileged containers, and audit namespace escapes regularly.

How do you secure and harden LXD system containers for production?

Security in LXC and LXD: System Containers requires defense-in-depth because they share the host kernel. A container escape compromises the entire host. Apply these hardening measures as baseline requirements, not optional enhancements:

  • Never run privileged containers unless absolutely necessary. Use security.privileged=false (default) and map UIDs/GIDs with security.idmap.isolated=true to prevent root-in-container from mapping to root-on-host.
  • Enable AppArmor confinement for every container. LXD ships default profiles; customize them for workloads requiring specific syscalls. Audit denials with aa-logprof.
  • Restrict device access explicitly. Remove default device permissions and whitelist only required GPUs, USB devices, or block devices per-profile.
  • Enforce resource limits via cgroups v2. Set CPU, memory, and PID limits to prevent noisy-neighbor issues and fork bombs. Use limits.cpu=2 and limits.memory=4GiB as starting points.
  • Keep the host kernel updated. Container security is kernel security. Subscribe to Ubuntu Security Notices and apply livepatches with Canonical Livepatch to avoid reboot windows.
  • Network segmentation: Place containers handling sensitive data on isolated bridges with firewall rules. Do not expose management APIs (LXD socket) to untrusted networks.

For compliance-sensitive environments (SOC 2, ISO 27001), document your container security policies as code. Store LXD profiles and network configurations in Git, review changes via pull requests, and automate drift detection. This aligns container management with broader DevSecOps practices and provides auditors with verifiable evidence of security controls.

Start: New WorkloadNeeds non-Linux OS?Use Virtual MachineSingle process / stateless?Use Docker / OCIRequires auto-scaling / mesh?Use KubernetesLXC/LXD System ContainerYesNoYesNoYesNo
Decision framework: select LXC and LXD system containers when workloads require full OS semantics without VM overhead or Kubernetes complexity.

Practical next steps for adopting LXC and LXD: System Containers

LXC and LXD: System Containers remain a vital tool in the 2026 infrastructure toolkit, particularly for teams needing VM-like behavior with container-like efficiency. Start by deploying LXD on a non-production host, experiment with ZFS snapshots and profile composition, and validate your security hardening checklist before touching production. Document your patterns, version-control your profiles, and integrate container lifecycle management into your existing monitoring and backup pipelines. If you need guidance on architecting containerized infrastructure that meets compliance requirements or integrates with your current observability stack, reach out to discuss your specific environment.

Frequently Asked Questions

LXC is the low-level userspace interface for Linux kernel container features. LXD is a system container manager built on top of LXC that provides a unified CLI, REST API, image management, storage pools, and network bridges for easier orchestration in 2026.

No. Docker runs single application processes with ephemeral storage. LXD system containers run full Linux distributions with init systems, persistent storage, and multiple services, behaving like virtual machines but sharing the host kernel for higher density and lower overhead.

Run sudo snap install lxd to get the latest stable channel. After installation, execute sudo lxd init to configure storage pools, networking, and clustering interactively. The snap package includes all required dependencies and receives automatic security updates without manual apt intervention.

Yes. LXD uses official image servers to launch containers running Ubuntu, Debian, Alpine, Fedora, Rocky Linux, or Arch regardless of the host distribution. The container userspace is isolated, so only kernel compatibility matters, which works across most modern Linux variants.

Yes. Canonical supports LXD for production OpenStack deployments, CI runners, and multi-tenant hosting. It offers live migration, ZFS storage integration, GPU passthrough, and role-based access control. Many organizations use it as a lightweight alternative to KVM for stateful services.

LXD manages storage pools using ZFS, Btrfs, Ceph, or directory backends. Containers attach to these pools via copy-on-write snapshots for fast provisioning. Storage volumes persist independently of container lifecycle, enabling database files and application data to survive restarts and migrations safely.

Unprivileged containers map root inside to an unprivileged user outside, preventing host escape. Risks remain if you disable AppArmor, mount sensitive host paths, or grant excessive capabilities. Always use default security profiles and avoid nesting unless explicitly hardened with custom Seccomp rules.

Use lxc-migrate or distrobuilder to convert existing installations into LXD images. Alternatively, rsync filesystem contents into a new container and reinstall services. Test thoroughly before cutover since hardware-specific configurations often require adjustment for the containerized environment and missing kernel modules.

Yes. Add nvidia or intel GPU devices via lxc config device add. Install matching drivers inside the container. This enables CUDA or OpenCL acceleration for machine learning inference while maintaining container isolation. Verify driver versions match host and container kernels exactly.

Typically 50 to 100 MB baseline per idle system container. Overhead depends on running services, not LXD itself. Unlike VMs, containers share the host kernel and libraries where possible, allowing hundreds of instances on hardware that supports only dozens of virtual machines.

Yes. LXD supports native clustering with up to 50 nodes. Nodes share configuration, images, and storage via distributed consensus. Workloads automatically reschedule on node failure when using shared Ceph or ZFS pools. Initialize clustering with lxd cluster enable during setup.

Use lxc config device add to create proxy devices mapping host ports to container ports. Alternatively, configure LXD managed bridges with iptables NAT rules. For production, place containers behind a reverse proxy like Caddy or Nginx rather than exposing ports directly.

Containers share the host kernel, so reboots apply new kernels to all containers simultaneously. No individual container kernel updates are needed. Schedule maintenance windows accordingly and test critical workloads after kernel upgrades since ABI changes can occasionally break older container applications.

Use lxc snapshot for point-in-time copy-on-write backups on ZFS or Btrfs. Export full containers with lxc export for portable archives. Restore snapshots instantly or import exports to recover. Automate scheduled snapshots via cron or systemd timers for disaster recovery compliance.

Podman targets OCI application containers without init systems. LXD provides full systemd support, persistent networking, block storage management, and VM-like behavior needed for databases, mail servers, or legacy apps requiring complete OS environments rather than single-process isolation patterns.