▤ Homelab

Virtual machines or LXC containers: when to use which

Differences between virtual machines and LXC system containers in a homelab: isolation, performance, memory, security and practical cases to choose well.

On platforms such as Proxmox VE, every time you create a new service the same question comes up: virtual machine or LXC container? Both look like small independent computers, with their own IP address and their own system, but they work very differently. Understanding the difference avoids wasted resources and nasty surprises.

Two different ways of isolating

A virtual machine emulates an entire computer: virtual processor, memory, disk, network card, firmware. Inside it runs a complete operating system with its own kernel. The hypervisor, helped by the processor's hardware extensions, keeps it separate from the host and from other virtual machines.

An LXC container emulates nothing. It is a set of processes running directly on the host's kernel, isolated through Linux kernel mechanisms such as namespaces (which give the container its own view of processes, network, users and filesystem) and cgroups (which limit its CPU and memory use). From the inside it looks like a complete Linux system, but the kernel is the host's.

LXC containers are also called "system containers", to distinguish them from application containers like Docker's: an LXC container hosts an entire distribution with its init system, services and package manager, whereas an application container usually runs a single process.

Practical comparison

Aspect Virtual machine LXC container
Kernel its own shared with the host
Supported systems Linux, Windows, BSD and others Linux only
Boot tens of seconds a few seconds
Memory reserved as a block used as needed
Isolation strong good, but thinner
Hardware access PCIe device passthrough sharing of host devices
Live migration supported usually with a restart

When to choose an LXC container

Containers are ideal for lightweight Linux services that do not need a particular kernel:

  • a local DNS server or ad blocker;
  • a reverse proxy;
  • a test database;
  • small web services and monitoring tools.

The main advantage is efficiency. A container that does little uses little memory, because it does not have to keep a whole operating system running with its cache and base services. On a machine with 16 GB of RAM you can run far more containers than virtual machines.

Another advantage is hardware sharing: for example, the host's integrated graphics can be made available to several containers at once for video transcoding, something that with virtual machines requires exclusive passthrough or GPU virtualisation technologies.

When to choose a virtual machine

A virtual machine is the right choice when:

  • you need a non-Linux system, such as Windows or a BSD-based firewall;
  • you need a specific kernel, with particular modules or a version different from the host's;
  • you want to run Docker simply and in a fully supported way;
  • you host services exposed to the Internet or software you trust little, where stronger isolation is worthwhile;
  • you need exclusive passthrough of a device, such as a disk controller or network card.

On Docker inside LXC, a clarification: it is possible, by enabling nesting and a few options, but it is a more fragile setup that can break with updates. Many people prefer a small virtual machine dedicated to Docker, hosting all the application containers.

Privileged and unprivileged containers

Proxmox creates unprivileged containers by default: the root user inside the container maps, on the host, to an unprivileged user, thanks to user ID mapping. If a process managed to escape the container, it would find itself with very limited permissions.

Privileged containers make the inner root and the host's root the same. They are sometimes more convenient, for example for mounting network shares, but they greatly reduce isolation. The prudent rule is to use unprivileged containers unless there is a specific reason, and to solve permission problems with user mapping rather than by switching to privileged ones.

A sample split

In a typical homelab, a reasonable split could be:

  • LXC: local DNS, reverse proxy, monitoring server, development database;
  • VM: virtual firewall or router, a Docker machine for application services, a Windows test machine, services exposed to the outside.

In my work I prefer to start with a container and move to a virtual machine only when a concrete reason emerges: it is the simplest way to avoid filling memory with operating systems that do almost nothing.

In short

  • A virtual machine emulates a complete computer with its own kernel; an LXC container shares the host's kernel.
  • Containers are lighter, boot in seconds and use memory only when needed.
  • For Windows, special kernels, passthrough, Docker and exposed services, a virtual machine is the better fit.
  • Unprivileged containers are the safer default.
  • Starting with a container and moving to a virtual machine only for concrete reasons avoids wasting RAM.
MM
Marco Marzaduri

Marco Marzaduri works in cybersecurity, digital forensics and web development. A computer science graduate, he combines rigorous technical analysis with attention to the people who use technology.

Read also