Skip to content
Back to Blog
Proxmox

LXC Containers in Proxmox VE: Best Practices

Manage LXC containers in Proxmox VE: templates, networking, resource limits, privilege settings, and production-grade configurations.

Oct 2025
11 min read

Introduction

Proxmox LXC containers are system containers that share the host kernel but have their own filesystem, network, and processes. They're ideal for running services that don't need full VM isolation — web servers, databases, monitoring agents — with minimal overhead.

LXC vs KVM in Proxmox

FeatureLXCKVM
OverheadMinimal (< 1%)Moderate (5-10%)
IsolationNamespace-basedFull hardware
Boot timeSeconds10-30 seconds
Use caseLinux servicesAny OS, higher isolation
VMs in containerNoYes

Downloading Container Templates

BASH
# List available templates
pveam available --section system

# Download Ubuntu template
pveam download local ubuntu-22.04-standard_22.04-1_amd64.tar.zst

# Download Alpine (tiny, 3MB)
pveam download local alpine-3.18-default_20230607_amd64.tar.xz

# List downloaded templates
pveam list local

Creating LXC Containers

Via CLI:

BASH
# Create Ubuntu container
pct create 100 local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst   --hostname web-server   --memory 2048   --swap 512   --cores 2   --net0 name=eth0,bridge=vmbr0,ip=192.168.1.100/24,gw=192.168.1.1   --storage local-zfs   --rootfs local-zfs:20   --password SecurePass123   --ssh-public-keys /root/.ssh/id_rsa.pub   --unprivileged 1   --features nesting=1

# Start the container
pct start 100

# Enter the container
pct enter 100

# Or SSH directly
ssh root@192.168.1.100

Container Configuration

BASH
# View current config
pct config 100

# Change memory
pct set 100 --memory 4096

# Resize disk
pct resize 100 rootfs +10G

# Add additional disk
pct set 100 --mp0 local-zfs:5,mp=/data

# Change network
pct set 100 --net0 name=eth0,bridge=vmbr0,ip=192.168.1.101/24,gw=192.168.1.1

Privileged vs Unprivileged Containers

Unprivileged (recommended):
  • UID/GID mapping: container root (0) maps to host user 100000
  • Container can't escape to host even if compromised
  • Some limitations: can't mount NFS, some kernel modules unavailable
Privileged:
  • Container root = host root
  • Required for: Docker-in-LXC, some network functions
  • Security risk — use only when necessary
BASH
# Create privileged container
pct create 101 ... --unprivileged 0

# Enable nesting (for Docker inside LXC)
pct set 100 --features nesting=1

Docker Inside LXC (Nesting)

BASH
# On privileged container with nesting=1
pct set 100 --features nesting=1,keyctl=1
pct start 100
pct enter 100

# Inside the container
apt update && apt install -y docker.io
systemctl enable docker
docker run -d -p 80:80 nginx

Snapshots and Backups

BASH
# Take snapshot
pct snapshot 100 before-update

# List snapshots
pct listsnapshot 100

# Rollback
pct rollback 100 before-update

# Delete snapshot
pct delsnapshot 100 before-update

# Backup container
vzdump 100 --storage backup-storage --mode snapshot

# Restore backup
pct restore 200 /var/lib/vz/dump/vzdump-lxc-100-*.tar.zst   --storage local-zfs

Bind Mounts (Share Host Directories)

BASH
# Share host directory /data/website into container at /var/www
pct set 100 --mp0 /data/website,mp=/var/www

# Shared read-only
pct set 100 --mp0 /data/configs,mp=/etc/myapp,ro=1

Networking: Multiple Interfaces and VLANs

BASH
# Add VLAN interface
pct set 100 --net1 name=eth1,bridge=vmbr0,tag=20,ip=10.20.0.100/24

# View all container networks
pct config 100 | grep net

Mass Deployment Script

BASH
#!/bin/bash
TEMPLATE="local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst"
START_ID=200
COUNT=5

for i in $(seq 1 $COUNT); do
    CT_ID=$((START_ID + i))
    IP="192.168.1.$((100 + i))/24"
    
    pct create $CT_ID $TEMPLATE         --hostname "web-$i"         --memory 1024         --cores 1         --net0 name=eth0,bridge=vmbr0,ip=$IP,gw=192.168.1.1         --storage local-zfs         --rootfs local-zfs:10         --unprivileged 1         --start 1
    
    echo "Created CT $CT_ID: web-$i ($IP)"
done