LXC vs VM in Proxmox: When to Use Each
By LK Wood IV · 2026-06-13 · ~12 min read · St. Louis County, MO
The single most common question I see from people setting up Proxmox for the first time: “Should I use a container or a VM for this?” The answer is not “it depends” — that’s the non-answer. The answer is a decision tree with clear rules, and once you internalize it, you’ll stop second-guessing every workload.
Here’s what I use in my own homelab, why, and where the lines are.
What Proxmox actually gives you
Proxmox VE is a hypervisor that supports two completely different virtualization approaches from the same interface.
KVM/QEMU virtual machines are full hardware emulation. The VM gets its own virtualized CPU, RAM, storage controller, and network card. It runs its own kernel. From inside the VM, there is no way to tell you’re not on bare metal (unless you’re inspecting CPUID flags). The hypervisor isolates the VM at the hardware level.
LXC containers share the host kernel. There is no hardware emulation. The container gets its own filesystem namespace, PID namespace, and network namespace — it looks like a separate Linux system from the inside — but it’s the same kernel call table as the host. The “container OS” is just a userland: /bin, /etc, /home, and the processes running on top of the shared kernel.
This single architectural difference drives everything else in the comparison.
Performance: where each wins
LXC advantages
Containers have near-zero virtualization overhead. A process running inside an LXC container makes system calls directly to the host kernel — no VMexit, no QEMU device emulation, no virtio driver overhead. For IO-heavy workloads like a NAS service, a database, or a file sync daemon, this matters.
Storage IO: An LXC container on a local ext4 or ZFS dataset reads and writes with basically host-native throughput. A VM’s virtio-blk or virtio-scsi driver adds a thin translation layer — in practice, a few percent overhead on sequential reads/writes. For random IO on NVMe at high queue depths, the VM overhead becomes more measurable.
Network: LXC containers using a veth pair and a Linux bridge (the default Proxmox setup) have near-native throughput. VMs go through virtio-net, which is excellent but adds ~1–3% overhead versus bare metal depending on packet size and rate.
Memory: A container doesn’t need memory for a guest kernel, QEMU, or virtio device state. A bare Debian LXC uses 30–60MB RAM before you run any services. A Debian VM with the same services uses 200–400MB. On a mini PC with 16GB RAM, that difference is significant if you’re running 10 services.
Boot time: LXC containers start in under a second. A VM boots in 5–15 seconds depending on BIOS/UEFI simulation.
VM advantages
Full kernel control. Each VM runs its own kernel. You can run Ubuntu 24.04 in one VM, Alpine 3.19 in another, and a custom-compiled kernel in a third — without any of them affecting each other or the host. LXC containers are locked to the host kernel version.
GPU passthrough. Passing a GPU through to an LXC container is possible but limited — you’re sharing the host kernel’s GPU driver with the container. Passing through to a VM via VFIO gives the VM exclusive access to the hardware and its own driver. If you’re doing GPU inference, GPU transcoding, or gaming VMs, use a VM.
Windows and non-Linux guests. LXC is Linux-only. Want a Windows Server VM for Active Directory, a Windows gaming VM, or anything non-Linux? KVM/QEMU, full stop.
Stronger isolation. Shared kernel means a kernel exploit in one container affects all containers and the host. A VM’s exploit surface is bounded by QEMU and KVM — materially harder to escape from. For anything running untrusted or public-facing code, this matters.
Kernel modules. If your workload needs a kernel module that’s not loaded on the host — WireGuard kernel module, ZFS on a different version, a custom NIC driver — a VM is the only real option. You can load modules in an LXC with allow_dangerous_writes, but you’re still touching the host kernel.
Resource overhead numbers
Here’s a concrete comparison running on a Beelink SEi12 Pro (N150, 16GB RAM, 512GB NVMe) running Proxmox VE 8.x:
| Metric | LXC (Debian 12, idle) | VM (Debian 12, idle, virtio) |
|---|---|---|
| RAM used by guest | ~55 MB | ~280 MB |
| CPU overhead | <1% | 1–3% |
| Storage IO vs bare metal | ~98% | ~94–97% |
| Network throughput vs bare metal | ~99% | ~97% |
| Boot time | 0.5–1.5 seconds | 8–20 seconds |
| Backup size (Debian + 1 app) | ~400 MB | ~2.0 GB |
Numbers are representative of Proxmox 8.x with virtio drivers. The storage IO gap closes significantly when using virtio-blk with io_uring.
What I actually run in LXC vs VM
In my own Proxmox setup, the split is roughly:
LXC containers:
- Home Assistant (isolated HAOS-style config on a Debian container)
- Vaultwarden (no kernel needs, pure userspace app)
- Nginx reverse proxy
- Uptime Kuma
- Immich photo server
- Pi-hole DNS
- Gitea
- Prometheus + Grafana stack
- Any service that’s “just a process” — no special kernel requirements, no GPU, trusted code
Virtual machines:
- TrueNAS Scale (needs its own ZFS kernel, storage needs isolation)
- Windows 11 (gaming and testing)
- Any LLM inference node with RTX 5080 GPU passthrough
- OPNsense (firewall OS — needs network kernel control and isolation is mandatory)
- Any publicly-exposed service handling user data
The pattern: if the workload is a Linux service that doesn’t need kernel modules, GPU access, or strong isolation, it’s an LXC container. If it needs any of those, it’s a VM.
The decision tree
New workload in Proxmox?
│
├─ Is it Windows or non-Linux? → VM
│
├─ Does it need GPU passthrough? → VM
│
├─ Does it need a specific kernel version or custom module? → VM
│
├─ Is it running untrusted or public-facing code? → VM (strongly recommended)
│
├─ Does it need ZFS as a storage backend (not just a ZFS dataset)? → VM
│
└─ Everything else → LXC container
(Linux service, trusted code, no GPU, no custom kernel)
When in doubt, start with a VM. You can always move a workload from a VM to a container later. Moving from a container to a VM when you discover you need GPU passthrough three months later is more annoying.
Proxmox-specific gotchas
LXC and NFS. Mounting NFS inside an LXC container requires features: mount=nfs in the container options. Without it, the kernel will reject NFS mounts inside the container namespace. Proxmox makes this a simple toggle.
LXC and Docker. Docker inside LXC requires features: nesting=1,keyctl=1. This works for most Compose stacks. Kubernetes inside LXC is possible but painful — just use a VM for K8s.
Unprivileged vs privileged containers. Proxmox creates LXC containers as unprivileged by default — UIDs inside the container are remapped to high UIDs on the host, limiting damage from a container breakout. Privileged containers run as root on the host. Use unprivileged containers unless you have a specific reason not to (some hardware passthrough scenarios require privileged mode).
Memory balloons for VMs. Proxmox supports KVM memory ballooning — VMs can return unused RAM to the host dynamically. Enable the balloon device in the VM hardware settings and set minimum/maximum RAM. This makes VMs more RAM-efficient when idle, closing part of the gap with LXC.
Snapshots. Both LXC and VMs support Proxmox snapshots. LXC snapshots require the storage to support snapshots (ZFS datasets or LVM-thin, not raw directories). VM snapshots work on any QEMU-compatible storage.
Backup behavior
Proxmox Backup Server handles both, but differently:
LXC backups suspend or stop the container, archive the container filesystem as a tar.zst, and optionally take a live snapshot (vzdump with --mode snapshot). Resulting backup is small — a Debian + one service is typically 300–600 MB.
VM backups use QEMU’s dirty-bitmap tracking to do incremental block-level snapshots. Initial backup is larger (full disk size, compressed); incrementals are small. Live VM backup works without stopping the VM using QEMU’s native snapshot capability.
Both integrate with PBS deduplication — if you’re running 10 nearly-identical Debian LXC containers, PBS deduplicates the common chunks and your backup storage footprint stays manageable. See the Proxmox Backup Server guide for the full setup.
When to run both for the same service
Some setups make sense as a hybrid. A common pattern:
- Run TrueNAS Scale as a VM (needs ZFS, storage isolation)
- Mount TrueNAS shares into LXC containers via NFS/SMB (Nextcloud, Immich, media servers)
The VM handles storage integrity and its kernel; the containers handle the application layer efficiently. This is cleaner than running everything inside TrueNAS jails and avoids the overhead of running a full VM for each application.
Summary
LXC containers are faster, lighter, and simpler to manage for standard Linux services. VMs are the right choice when you need kernel isolation, GPU passthrough, Windows, or strong security boundaries. Most homelabs run a mix — lighter services in containers, anything that needs hardware ownership or serious isolation in VMs.
Proxmox makes both first-class. The overhead of using either is low. The cost of choosing wrong is usually “rebuild and migrate the data” — not catastrophic, but avoidable if you think through the decision tree before deploying.
Running a Proxmox cluster? The Proxmox VM Capacity Planner calculates exactly how many VMs or containers your host can run given your RAM, cores, and ZFS ARC allocation. The Power & Cost Calculator shows what those nodes cost to run 24/7. The UPS sizing guide covers keeping them alive through a power outage.