I use Proxmox mainly because it gives me a very nice playground for VMs, containers, storage tests and the occasional “why is this not booting anymore?” evening session.
One feature that is easy to overlook at first is LXC containers.
When people hear “container”, they often immediately think of Docker. But Proxmox LXC containers are a bit different. They feel more like tiny Linux servers than application containers. You get a root filesystem, a hostname, network config, resource limits and a console. Basically a small Linux system without the full VM overhead. And that is pretty useful in a homelab.
What is an LXC container?
An LXC container is an operating-system-level container.
That means it does not emulate virtual hardware like a full VM. Instead, it shares the Linux kernel of the Proxmox host and uses Linux features like namespaces, cgroups and AppArmor for isolation. This makes LXC containers very lightweight. They start quickly, use fewer resources and are perfect for many small Linux services.
LXC vs VM in Proxmox
In Proxmox you normally have two main options:
| Option | Best for |
|---|---|
| VM / KVM | Full isolation, different operating systems, Windows, Docker hosts, kernel-level testing |
| LXC | Lightweight Linux services, small tools, internal apps, quick test systems |
I usually think about it like this:
- Use a VM when I need strong isolation or a full operating system.
- Use an LXC container when I just need a lightweight Linux box to run a service.
Good LXC candidates:
- Pi-hole / AdGuard
- small web server
- monitoring tools
- reverse proxy
- lightweight database test system
- internal scripts
- tiny Debian/Ubuntu utility box etc.
Better as VM:
- Windows Server ( it’s called Linux Containers for a reason )
- Docker host with many containers
- Kubernetes nodes
- untrusted workloads
- anything where kernel isolation really matters
LXC is great, but it is not magic security dust. All containers still share the host kernel. So do not treat it like a full VM if you are running something sketchy from the dark corners of GitHub at 1 AM.
Create your first LXC container
In the Proxmox GUI, the process is pretty simple.
Go to:
Node → local storage → CT Templates
Then click Templates and download a Linux template, for example Debian or Ubuntu.
After that click Create CT in the top right corner.
Typical settings:
- CT ID:
101 - Hostname:
web01 - Template: Debian or Ubuntu template
- Disk: 8 GB or more
- CPU: 1–2 cores
- Memory: 1024–2048 MB
- Network:
vmbr0 - IP: DHCP for testing, static for production-like services
- Unprivileged container: yes, if possible
For most homelab services I would start with an unprivileged container. Only use privileged containers when you actually need them.
Create an LXC container from the CLI / Proxmox Shell
First update the template list:
pveam update
Search eg. for a Debian template:
pveam available | grep debian
Download the template:
pveam download local debian-12-standard_<version>_amd64.tar.zst
Then create the container:
pct create 101 local:vztmpl/debian-12-standard_<version>_amd64.tar.zst \
--hostname web01 \
--rootfs local-lvm:8 \
--cores 2 \
--memory 2048 \
--swap 512 \
--net0 name=eth0,bridge=vmbr0,ip=dhcp \
--unprivileged 1
Replace the template name with the actual file you downloaded.
Start and access the container
Start it:
pct start 101
Open a shell inside it:
pct enter 101
Or use:
pct console 101
Check the container status:
pct status 101
List all containers:
pct list
At this point you basically have a small Linux server and you can install whatever service you want. Don’t forget to update it!
Set a static IP address
For quick tests DHCP is fine, for real services, I prefer static IPs.
Example:
pct set 101 --net0 name=eth0,bridge=vmbr0,ip=192.168.10.50/24,gw=192.168.10.1
Then restart the container:
pct restart 101
Inside the container, check:
ip a
ip r
If DNS is broken, check:
cat /etc/resolv.conf
Change CPU and memory
One nice thing about LXC containers is that resource changes are easy.
Set memory to 2 GB:
pct set 101 --memory 2048
Set swap to 512 MB:
pct set 101 --swap 512
Set CPU cores:
pct set 101 --cores 2
Check the config:
pct config 101
You can also view the config file directly on the Proxmox host:
cat /etc/pve/lxc/101.conf
You can edit this file directly, but I recommend changing settings through the Proxmox GUI or pct whenever possible. It reduces the risk of syntax or configuration mistakes.
Resize the container disk
If the container runs out of space, you can extend the root disk.
Add 10 GB:
pct resize 101 rootfs +10G
Check inside the container:
df -h
Usually this is picked up automatically for LXC containers.
Shrinking disks is a different story and should not be treated as a casual “let me just make this smaller” operation. Make a backup first. Actually, make two if this is important.
Add a bind mount
Sometimes you want the container to access a directory from the Proxmox host.
Example:
pct set 101 -mp0 /mnt/pve/data/appdata,mp=/mnt/appdata
This mounts the host path:
/mnt/pve/data/appdata
inside the container as:
/mnt/appdata
This is useful for app data, shared folders or media directories.
But be careful: Bind mounts are also a nice way to accidentally expose host data to a container. Do not mount half your host filesystem into a random container and then act surprised when permissions become spicy.
Snapshots and backups
Snapshots are useful before updates.
In the GUI:
Container → Snapshots → Take Snapshot
From CLI:
pct snapshot 101 before-upgrade
Rollback:
pct rollback 101 before-upgrade
But snapshots are not backups! Snapshots help when you break something locally.
Backups help when your storage breaks, your node dies, or you delete the wrong thing while being “almost sure” this was the test container.
For a proper backup you can use Proxmox vzdump:
vzdump 101 --mode snapshot --storage <backup-storage> --compress zstd
If you use Proxmox Backup Server, even better. PBS is one of the best things in the Proxmox ecosystem and feels like it was designed by people who have also accidentally destroyed things before.
Restore an LXC backup
A container backup can be restored with:
pct restore 102 /path/to/vzdump-lxc-101.tar.zst --storage local-lvm
This restores the backup as container ID 102.
I like restoring to a new ID first when testing. That way the original container stays untouched.
Because “just restoring over production” is how a calm evening turns into a learning experience.
Migrate an LXC container
In a Proxmox cluster, containers can be migrated to another node.
From the GUI:
Right click container → Migrate
From CLI:
pct migrate 101 target-node
Depending on your storage and configuration, the container may need to be stopped or restarted during migration.
So do not assume every LXC migration is magically live and invisible. Test it before relying on it.
My usual LXC best practices
For my own setup, I would keep it simple:
- Use unprivileged containers by default.
- Use static IPs for important services.
- Keep containers small and focused.
- Do not put every service into one giant container.
- Use bind mounts carefully.
- Back up containers before major changes.
- Prefer VMs for Docker-heavy workloads.
- Document the container ID, IP and purpose.
Example naming:
101-dns01
102-nginx01
103-monitoring01
104-test-debian
Future-you will be thankful.
My Verdict
LXC containers are one of those Proxmox features that sounds a bit boring at first, but becomes surprisingly useful once you actually start using it. And honestly, boring infrastructure is usually the best kind of infrastructure.
They are fast, lightweight and perfect for small Linux-based services in a homelab. Not every service needs a full VM with virtual hardware, its own kernel and a dramatic boot sequence. Sometimes you just need a clean little Linux container that starts quickly, does its job and stays out of the way.
For me, the rule is simple: use LXC for small, trusted Linux services — and use VMs when things get complex, exposed or messy.