Your Proxmox host runs ten LXCs — a Pi-hole, a database container, a reverse proxy, Authentik, Gitea, and six more. Everything works until one container decides to consume all available RAM or peg every CPU core. Suddenly your DNS starts timing out, the reverse proxy returns 502s, and the database container gets OOM-killed before the culprit even notices.
This is the noisy-neighbor problem in virtualization. Proxmox provides per-container resource limits out of the box, but most homelab setups leave them at defaults — which effectively means no limits at all.
This guide covers every LXC resource control available in Proxmox VE 8.x+: CPU pinning and cgroup CPU quotas, memory and swap caps, disk I/O throttling, and ZFS storage quotas. Every config includes the Proxmox CLI command, the UI path, and runtime verification.
Why Default LXC Resource Limits Aren’t Enough
When you create an LXC in Proxmox, the defaults are:
|
|
The only real constraint is the rootfs disk size. CPU and memory are shared freely. On a busy host with 16 GB RAM and eight LXCs, a single misbehaving container can exhaust memory and trigger the OOM killer. The kernel picks a victim — and it’s rarely the one you wanted killed.
Proxmox exposes LXC resource controls through two layers:
- cgroups (v1 and v2) — kernel-level CPU, memory, and I/O limits enforced by the container runtime
- Storage quotas — ZFS, LVM, or directory-level size restrictions on the root filesystem
The commands in this guide use pct set, which maps directly
to cgroup parameters. All configs persist across container
restarts and host reboots.
CPU Resource Controls
Proxmox LXCs support three CPU controls: CPU units (weight), CPU limits (ceiling), and CPU pinning (affinity).
CPU Units — Relative Weight
CPU units set proportional weight, not a hard cap. A container with 2048 units gets roughly twice the CPU time of a container with 1024 units when both are busy. When only one container is active, it can burst to 100%.
|
|
The default of 1024 is reasonable for general-purpose containers. Reserve higher weights for latency-sensitive services (DNS, reverse proxy, databases). Assign lower weights to batch or testing containers.
| Use case | CPU units |
|---|---|
| Latency-critical (DNS, proxy, auth) | 2048 |
| Standard workload (Gitea, dashboards) | 1024 |
| Background/batch (backup tools, sync) | 512 |
| Testing/experimental | 256 |
CPU Limit — Hard Cap
CPU limit (cpulimit) enforces a hard ceiling as a percentage of
a single core. A limit of 50 means the container cannot exceed
50% of one core — or 400 for four full cores.
|
|
CPUs across all containers on the host should sum to roughly the total available cores × 1.0-1.5 overhead. On an 8-core host with ten containers, keep each under 6-8 cores to allow headroom for Proxmox itself.
CPU Pinning — Affinity
CPU pinning locks a container to specific physical cores. This prevents cache thrashing when containers migrate between cores and ensures consistent performance for real-time workloads.
|
|
Alternatively, set CPU affinity in the container’s config file:
|
|
When to pin:
- Database containers that benefit from dedicated L2/L3 cache
- Real-time audio or video processing
- Containers with hard real-time requirements
When not to pin: Most general workloads. Pinning reduces scheduler flexibility and can leave cores idle while other containers wait.
Verify CPU assignments:
|
|
Memory and Swap Limits
Memory limits prevent a single container from starving the host. Proxmox enforces memory caps through cgroup memory controllers.
Hard Memory Limit
Set a hard cap that the container cannot exceed. When reached, the container’s processes start getting OOM-killed rather than the host deciding victims.
|
|
If you set --memory 0 (default), the container can use all
host memory. On a 16 GB host with eight containers, that means
any single one can eat 14+ GB before the OOM killer fires.
Swap Limit
Swap works differently in LXCs than in VMs. The swap limit controls the amount of swap the container can use on the host.
|
|
Most homelab containers don’t need swap. Databases should never swap. Disable swap for critical LXCs:
|
|
Practical Memory Budget for a Homelab Host
On an 8-core, 32 GB RAM Proxmox host with ten LXCs:
|
|
Sum allocated: ~16 GB. The host reserve of 4+ GB covers ZFS ARC, Proxmox services, and the kernel. Leave at least 20% headroom.
Memory Hot-Plug for LXCs
Proxmox supports live memory changes on running containers without restart:
|
|
This works because cgroup limits are dynamic. The container kernel sees available memory shrink but handles it gracefully unless it was already using more than the new limit.
Disk I/O Throttling
CPU and memory limits prevent compute contention, but disk I/O is often the real bottleneck. Ten containers fighting over a single NVMe drive can cause latency spikes even if CPU is idle.
IOPS Limits
Set read and write IOPS limits per container:
|
|
This uses cgroup I/O controllers (io.max v2 or blkio.throttle
v1). The limit applies to the container’s rootfs device.
Bandwidth Limits
Cap read and write throughput by bytes per second:
|
|
Always round to reasonable values for your storage hardware:
| Drive type | Sequential read | Sequential write | Random IOPS |
|---|---|---|---|
| NVMe (Gen 4) | 5000 MB/s | 4000 MB/s | 500K+ |
| SATA SSD | 500 MB/s | 450 MB/s | 80K |
| HDD (7200 RPM) | 180 MB/s | 150 MB/s | 150 |
| ZFS mirror (NVMe) | 3000 MB/s | 2000 MB/s | 300K+ |
For ZFS pools, leave at least 20% I/O headroom for the ARC flush, ZIL writes, and scrub operations.
I/O Priority by Container Type
A practical priority scheme for a 7-container homelab on NVMe:
|
|
The backup container is the key one to restrict. During nightly backups, restic and rclone can saturate the disk and degrade everything else. A 10K read / 5K write IOPS limit and ~250 MB/s read / 125 MB/s write bandwidth cap keeps backups slightly slower but prevents disruption.
ZFS Quotas and Refquota
For containers on ZFS storage — the default Proxmox
configuration — two quota types apply: quota limits the
total space including snapshots, while refquota limits only
the container’s active data (excluding snapshots).
|
|
Use refquota for containers where snapshot churn could fill
the volume. A Gitea container with 10 GB of git data and 50 GB
of weekly snapshots should have at least a 20 GB refquota plus
enough quota headroom for snapshots:
|
|
This container can use 20 GB of active data. Snapshots can accumulate up to 40 GB before hitting the 60 GB quota wall — which gives you time to prune old snapshots.
View ZFS Quota Usage
|
|
Resize ZFS Disk on the Fly
Need to grow a container’s disk? Proxmox resizes the ZFS subvolume online:
|
|
Shrinking ZFS volumes requires the filesystem inside to be
smaller than the target. Always pct exec 100 -- df -h first
to verify actual usage.
Comprehensive Resource Profile
Combine everything into a single profile for a container:
|
|
The backup container profile is the most restrained: low CPU weight so it yields to everything else, minimal IOPS to avoid disrupting database and media reads, and small RAM since backup operations are streaming, not memory-bound.
Monitoring Resource Pressure
After setting limits, verify they work under load:
|
|
The memory.pressure file shows PSI (Pressure Stall Information).
A some avg10 value over 50 means the container is frequently
waiting on memory. Raise the limit or investigate the workload.
For CPU pressure:
|
|
A full avg10 over 10 indicates the container is CPU-bound and
hitting its cgroup ceiling. Consider raising --cpulimit or
pinning the container to dedicated cores.
Proxmoz UI vs CLI — When to Use Each
Most resource limits can be set from the Proxmox web UI:
Container → Resources → Add (or double-click an existing row):
- Memory, Swap, CPU units, CPU limit — all available in the UI
- I/O limits — available in the UI under “IO Limit” and “IO Bandwidth”
- CPU pinning — not available in the UI, must use CLI or
edit
lxc.cgroup2in/etc/pve/lxc/<CTID>.conf
For bulk operations across containers, use the CLI:
|
|
Or better, script it with a config file:
|
|
Run this from a cron job or Ansible to enforce consistency.
Summary
A methodical approach to LXC resource management prevents the noisy-neighbor problem in dense Proxmox homelabs:
- CPU — Set
cpuunitsfor proportional weight; usecpulimitfor hard caps on noisy containers; pin only for databases and real-time workloads - Memory — Always set a hard
--memorylimit on every container; disable swap for databases and latency-sensitive services - I/O — Cap backup workers to 10K IOPS to prevent nightly contention; leave database and media containers with higher limits
- Disk — Use
refquotafor active data limits andquotafor total-with-snapshots; resize from CLI withpct resize
Start with conservative limits: 2 GB RAM, 2 CPU cores, 50 GB
disk for most containers. Monitor pressure indicators with
pct top and cgroup PSI files. Adjust upward only when the
container shows genuine need.
Every container gets a hard limit. No container gets to steal resources from the rest of your lab.