Proxmox VE: The Comprehensive Guide
Proxmox VE sits in a rare category of software: it is genuinely enterprise-capable, fully open-source, and free to use without a subscription. VMware ESXi served this role for a decade, but its acquisition by Broadcom and subsequent licensing changes sent a significant fraction of the homelab and small-business market looking for an alternative. Proxmox was already the answer for many; it is now the answer for many more.
What makes Proxmox worth understanding in depth is that it is not just a hypervisor. It is a converged platform that manages KVM virtual machines, LXC containers, ZFS or Ceph storage, software-defined networking, clustering, high availability, and backups from a single web interface and a coherent REST API. The learning curve is real — the defaults are not always obvious, and some decisions made at installation (storage layout, network bridge names) are painful to change later. Understanding the platform before you deploy saves significant time.
This guide covers the full operational picture: installation, storage, networking, VM and container management, clustering, HA, GPU passthrough, backup, and automation. It is long because Proxmox is deep.
What Proxmox VE Is
Proxmox VE runs on Debian Linux (currently Debian 12 Bookworm as of PVE 8.x). On top of Debian it adds:
- KVM hypervisor via
qemu-kvmfor full hardware virtualization. Any OS that runs on x86-64 hardware runs as a KVM VM. - LXC (Linux Containers) for lightweight OS-level containerization. LXC containers share the host kernel and start in under a second. They are not Docker containers — they are more like a lightweight VM with a full Linux userspace.
- ZFS integrated at the kernel level, available as a storage backend since PVE 3 (2014).
- Ceph storage cluster management integrated into the web UI and CLI.
- Corosync clustering for multi-node management and high availability.
pvesm(Proxmox VE Storage Manager) abstracting local and network storage backends.pveamfor container template management.- A REST API covering every operation available in the web UI.
The web interface runs on port 8006 over HTTPS. All configuration lives in /etc/pve/, which is distributed across cluster nodes in real time via pmxcfs (a cluster filesystem backed by Corosync).
Installation
Download the ISO from proxmox.com/en/downloads. Burn to USB with dd or Ventoy. Boot the target machine.
The installer prompts for:
- Target disk: choose the disk for the OS installation. If you intend to use ZFS for VM storage, do not use your only SSD for the OS — use a separate smaller disk or a mirrored pair of cheap SSDs.
- Filesystem:
ext4orzfs(RAID-0, RAID-1, RAID-10, RAIDZ-1/2/3). For a single-node homelab on a single OS disk,ext4is fine. For production with redundancy requirements,ZFS RAID-1(mirror) on two OS disks is safer. - Network configuration: IP, gateway, DNS. Choose a static IP on your management network. This is the address the web UI will be on.
- Hostname: set a fully qualified hostname (
pve1.homelab.local). This matters for clustering — it must be resolvable from other nodes.
Post-install: repository configuration
The default Proxmox installation has the enterprise repository enabled, which requires a paid subscription to use. Without a subscription, apt update fails. Switch to the no-subscription repository:
|
|
The no-subscription repository gets the same packages as the enterprise repository — the subscription is for access to the stable enterprise repo and commercial support, not different software.
Post-install: remove subscription nag
The web UI shows a subscription nag on login. Remove it:
|
|
Note: this change is overwritten on proxmox-widget-toolkit package updates. Re-apply after upgrades.
Post-install: IOMMU for GPU passthrough
If you plan to use PCI passthrough, enable IOMMU now (before you have VMs to migrate):
|
|
iommu=pt (passthrough mode) reduces IOMMU overhead for devices that are not being passed through. Set it regardless of whether you are using passthrough — it improves performance for all VMs.
Storage Backends
Proxmox abstracts storage into storage pools. Each pool has a type, a name, and a set of content types it can hold (disk images, ISO images, container templates, snippets, backups, etc.).
Datacenter → Storage → Add
Local storage (default)
The default installation creates two storage entries:
local(directory at/var/lib/vz/) — holds ISOs, container templates, backups. Type: Directory.local-lvm(LVM thin pool on the OS disk) — holds VM disk images and container volumes. Type: LVM-Thin.
LVM-Thin provides thin provisioning (disk images are sparse until written) and fast snapshots at the LVM level. It is adequate for a single node with a large OS disk but does not survive node failure.
ZFS storage pools
ZFS is the recommended storage backend for serious homelab use. Add drives to a ZFS pool after installation:
|
|
Add the pool to Proxmox:
Datacenter → Storage → Add → ZFS
ID: vmdata
Pool: vmdata
Thin Provision: checked
Content: Disk image, Container
Or via CLI:
|
|
ZFS pools in Proxmox support snapshots natively, which Proxmox uses for VM snapshots and backup. The ARC (ZFS read cache) significantly improves I/O for frequently accessed VM disks — tune zfs_arc_max to leave enough RAM for the VMs themselves.
NFS and SMB/CIFS
For shared storage across multiple nodes (required for live migration of VMs without shared storage), NFS is the common choice:
Datacenter → Storage → Add → NFS
ID: nas-storage
Server: 192.168.1.50
Export: /srv/proxmox
Content: Disk image, ISO image, Backup, Snippets
NFS storage enables VM migration between nodes — the disk image lives on the NFS server rather than on a specific node. All nodes in the cluster can access it simultaneously.
Ceph
Ceph provides distributed block storage across cluster nodes. Each node contributes disks as OSDs (Object Storage Daemons); Ceph replicates data across them for redundancy. For a Proxmox cluster with three or more nodes each having dedicated storage disks, Ceph is the production-grade shared storage option.
Minimum Ceph cluster for homelab: 3 nodes, 1 OSD per node, at least 1 dedicated Ceph network (10GbE recommended).
|
|
The web UI at Datacenter → Ceph shows OSD status, pool utilization, and health in real time.
Networking
Default bridge
The installer creates vmbr0 bridged to the first physical NIC. All VMs on the default network connect to vmbr0 as their uplink and get access to the same L2 segment as the host.
The host’s IP address is on vmbr0, not on the physical NIC directly. This is standard Linux bridging — the physical NIC (eno1 or eth0) has no IP, the bridge has the IP, and packets flow through the bridge.
# /etc/network/interfaces
auto eno1
iface eno1 inet manual
auto vmbr0
iface vmbr0 inet static
address 192.168.1.10/24
gateway 192.168.1.1
bridge-ports eno1
bridge-stp off
bridge-fd 0
VLANs
For multi-tenant or segmented networks, use VLAN-aware bridges. Enable VLAN awareness on vmbr0:
Node → Network → vmbr0 → Edit → VLAN aware: checked
With VLAN awareness enabled, VMs can specify a VLAN tag in their network device configuration. The bridge handles 802.1Q tagging transparently. The physical switch port must be configured as a trunk.
For a dedicated management VLAN (e.g., VLAN 10) and a VM traffic VLAN (e.g., VLAN 20):
# /etc/network/interfaces
auto vmbr0.10
iface vmbr0.10 inet static
address 192.168.10.10/24
gateway 192.168.10.1
auto vmbr0.20
iface vmbr0.20 inet manual
VMs on VLAN 20 set their network device tag to 20 and the bridge forwards appropriately.
Bond (NIC teaming)
For redundancy or additional bandwidth on multi-NIC hosts:
Node → Network → Create → Linux Bond
Name: bond0
Slaves: eno1 eno2
Mode: LACP (802.3ad) — requires switch support
or active-backup — works without switch config
# Then create the bridge on top of bond0
auto vmbr0
iface vmbr0 inet static
bridge-ports bond0
...
LACP requires the switch to be configured with a LAG. active-backup is simpler and provides redundancy without switch configuration — if eno1 fails, traffic moves to eno2 automatically.
Dedicated networks for clustering and storage
For a cluster, separate networks for different traffic types:
- Management/VM network:
vmbr0on the main NIC (192.168.1.x) - Corosync/cluster heartbeat: dedicated NIC or VLAN, low latency required
- Ceph/storage replication: dedicated NIC, high bandwidth (10GbE)
- VM live migration: shared with storage or dedicated
Keeping Corosync traffic off the VM network prevents a traffic spike from causing false node failures.
KVM Virtual Machines
Creating a VM
Upload an ISO to the local storage first:
local → ISO Images → Upload
Then create the VM:
Create VM
General: Node, VM ID (100+), Name
OS: ISO image, Guest OS type (Linux 6.x kernel, Windows 11, etc.)
System:
Machine: q35 (preferred over i440fx for PCIe support and modern features)
BIOS: SeaBIOS (legacy) or OVMF (UEFI — required for Secure Boot and some Windows installs)
SCSI Controller: VirtIO SCSI single (best performance)
Qemu Agent: checked (install qemu-guest-agent in the guest later)
Disks:
Bus: VirtIO Block or SCSI (VirtIO is faster; SCSI supports more features)
Storage: vmdata (your ZFS pool)
Size: as needed
Cache: None (safest with ZFS) or Write Back (faster, less safe)
Discard: checked (TRIM/unmap support — requires thin-provisioned storage)
IO thread: checked (per-disk thread improves multi-disk I/O)
CPU:
Sockets/Cores: as needed
Type: host (exposes all host CPU features; not migratable across different CPU generations)
or x86-64-v2-AES (portable, compatible with most modern x86 hardware)
Memory:
MiB: as needed
Ballooning: checked (allows dynamic memory adjustment with qemu-agent installed)
Network:
Model: VirtIO (best performance)
Bridge: vmbr0
VLAN Tag: set if using VLANs
VirtIO drivers
For Windows VMs, download the VirtIO ISO from the Fedora project and attach it as a second CD-ROM. During installation, load the VirtIO SCSI driver to see the disk. After installation, run the VirtIO installer from the ISO to get network and balloon drivers.
|
|
Cloud-init templates
Cloud-init is the standard mechanism for first-boot configuration of cloud images (hostname, SSH keys, network, users). Proxmox has native cloud-init support — it generates the cloud-init seed as a CDROM attached to the VM.
To create a reusable cloud-init template from an Ubuntu cloud image:
|
|
Clone the template to create new VMs instantly:
|
|
Linked clones start in seconds and consume only the delta from the template. They require the template disk to remain intact — deleting the template breaks all linked clones.
qemu-guest-agent
Install qemu-guest-agent in the guest for accurate IP reporting, proper shutdown/reboot from the Proxmox UI, memory ballooning, and filesystem freeze during snapshots:
|
|
Enable in the VM options:
VM → Options → QEMU Guest Agent → Enabled: checked
LXC Containers
LXC containers share the Proxmox host kernel. They start in under a second, use a fraction of the memory of a VM, and have near-native I/O performance. The trade-off: they must run Linux, they run the host’s kernel (no custom kernel modules in the container), and they have a slightly wider attack surface than a full VM (shared kernel means a container escape is more impactful than a VM escape).
When to use LXC vs KVM
| Criterion | LXC | KVM |
|---|---|---|
| OS | Linux only | Any |
| Boot time | < 1 second | 10–60 seconds |
| Memory overhead | 20–50 MB | 200–500 MB+ |
| Kernel modules | Host kernel only | Guest kernel |
| Isolation | Namespace-based | Hardware-level |
| GPU passthrough | Not supported | Supported |
| Nested virtualization | Limited | Supported |
| Windows | No | Yes |
Use LXC for: lightweight Linux services (DNS, proxy, monitoring agents, databases, web servers), services that do not need custom kernel modules, dev environments where boot speed matters.
Use KVM for: Windows, anything needing GPU passthrough, anything requiring a different kernel version, anything where strong isolation is a security requirement.
Creating an LXC container
Download a container template:
|
|
Via the UI:
Create CT
General: Node, CT ID, Hostname, Password (or SSH key)
Template: local → ubuntu-24.04-standard
Disks: Storage (vmdata), Size
CPU: Cores
Memory: RAM, Swap
Network: Name (eth0), Bridge (vmbr0), IPv4 (DHCP or static)
DNS: inherited from host or custom
Via CLI:
|
|
--unprivileged 1 runs the container with user namespace mapping — UIDs inside the container are mapped to unprivileged UIDs on the host. This is the safe default; privileged containers have root inside the container map to root on the host, which is a security risk.
Privileged vs unprivileged containers
Most containers should be unprivileged. Exceptions where privileged containers are needed:
- Containers that run Docker (Docker inside LXC requires privileged or significant nesting config)
- Containers that need to mount NFS inside the container
- Containers using certain kernel features not available in user namespaces
For Docker inside LXC (privileged):
|
|
For Docker inside LXC (unprivileged — cleaner):
|
|
Bind mounts
Share a directory from the Proxmox host into an LXC container:
|
|
This is how you give a Plex or Jellyfin container in LXC access to media stored on a host-mounted NAS share.
Snapshots and Backups
VM and container snapshots
A snapshot captures the disk state (and optionally RAM state) of a VM at a point in time. With ZFS or LVM-Thin storage, disk snapshots are nearly instant; with directory storage, they are slow and copy the full disk.
|
|
Snapshots are not backups. A snapshot on the same disk as the VM is deleted if the storage fails. Use them for short-term safety (before risky operations) and use a backup solution for durable recovery.
Proxmox Backup Server (PBS)
PBS is a separate appliance (installed on its own machine or VM) that provides deduplicated, incremental, encrypted backups. It is the recommended backup target for Proxmox environments.
PBS works by taking a backup of each changed block since the last run — the first backup is a full backup, subsequent backups are incremental. Deduplication happens across all backups in the datastore, so similar VMs share chunks. Encryption is AES-256-GCM.
Install PBS on a dedicated machine (can be a VM on the same node or a separate box):
|
|
PBS web UI runs on port 8007.
Add PBS as a storage backend in Proxmox:
Datacenter → Storage → Add → Proxmox Backup Server
ID: pbs
Server: 192.168.1.60
Datastore: main
Username: user@pbs
Password: ...
Fingerprint: (copy from PBS → Dashboard → Fingerprint)
Schedule backups:
Datacenter → Backup → Add
Storage: pbs
Schedule: sun 02:00 (or any systemd calendar expression)
Selection: All (or select specific VMs/CTs)
Mode: Snapshot (for running VMs)
Compression: zstd
Encryption: enabled (set encryption key)
Retention: Keep Last 7, Keep Weekly 4, Keep Monthly 6
The retention policy uses garbage collection to remove chunks not referenced by any retained backup.
vzdump for direct backups
vzdump is Proxmox’s backup tool used by both the UI scheduler and PBS. Useful for ad-hoc backups:
|
|
Clustering
A Proxmox cluster is a group of nodes managed as a single unit. You can create and manage VMs on any node from any node’s web UI, migrate VMs between nodes, and — with shared storage — enable high availability.
Requirements
- Minimum 3 nodes for reliable quorum (2 nodes cannot handle one failure without external quorum device)
- All nodes must resolve each other’s hostnames
- Low-latency network for Corosync (< 2ms recommended; separate physical link preferred)
- Same Proxmox version on all nodes
- Same time (NTP synchronized)
Creating the cluster
On the first node:
|
|
On each additional node:
|
|
Verify:
|
|
With a cluster in place, the web UI shows all nodes in the left panel. VMs can be created on any node and migrated between them.
Corosync redundancy
Configure a second Corosync link for redundancy. Both links must be alive for the node to be healthy; losing one generates a warning but the cluster continues operating:
|
|
Quorum and split-brain
Quorum requires more than half of nodes to be reachable. In a 3-node cluster, losing 1 node leaves 2 nodes with quorum (2 > 3/2). In a 2-node cluster, losing 1 node leaves 1 node without quorum — the remaining node pauses to prevent split-brain (both nodes believing they are the primary and potentially corrupting shared data).
For 2-node clusters, add a QDevice (Quorum Device) — a lightweight arbitrator that breaks ties without being a full cluster member:
|
|
Live migration
Migrate a running VM between nodes:
|
|
Online migration transfers RAM state over the migration network while the VM runs. At the end, a brief pause synchronizes the last dirty pages. The pause is typically under 1 second for VMs under moderate memory write pressure.
For online migration to work without shared storage, Proxmox copies the disk from the source node to the destination over the migration network (offline copy-then-start, not true live migration). True live migration with zero downtime requires shared storage (NFS, Ceph) accessible from all nodes.
High Availability
Proxmox HA automatically restarts VMs and containers on another node if their current node fails. HA requires a cluster with shared storage.
Enabling HA for a VM
Datacenter → HA → Resources → Add
VM: 101
State: started
Group: (optional — restrict to specific nodes)
Max Restart: 3
Max Relocate: 1
Or via CLI:
|
|
When the node hosting VM 101 becomes unavailable, pve-ha-crm (cluster resource manager) detects the failure via Corosync, fences the failed node if necessary (via IPMI/BMC), and starts the VM on another node.
Fencing (STONITH)
Without fencing, HA is unsafe. If a node loses network connectivity but is still running, it might still be writing to shared storage while HA starts the VM on another node — two instances writing to the same disk simultaneously corrupts data. Fencing ensures the failed node is powered off before HA starts the VM elsewhere.
Configure fencing via IPMI/BMC:
Datacenter → HA → Fencing → Add
Plugin: ipmi
Node: pve2
Address: 192.168.1.201 (IPMI address)
Username: admin
Password: ...
Without working fencing in production, HA is a liability not an asset.
GPU Passthrough
PCI passthrough assigns a physical GPU (or any PCIe device) exclusively to a VM. The VM gets direct hardware access — no virtualization overhead, full performance, full driver support.
Verify IOMMU groups
After enabling IOMMU (described in the installation section), check that your GPU is in its own IOMMU group:
|
|
If the GPU shares an IOMMU group with other devices (common on consumer-grade motherboards), you must pass through all devices in the group, or apply the ACS override patch (which has security implications).
Bind GPU to VFIO driver
The GPU must be detached from the host driver and handed to VFIO before a VM can use it:
|
|
Add GPU to VM
VM → Hardware → Add → PCI Device
Device: 0000:01:00.0 (your GPU)
All Functions: checked (passes GPU + audio together)
ROM-Bar: checked
PCI-Express: checked (for x16 bandwidth)
For NVIDIA GPUs in VMs, you must hide the KVM hypervisor flag (NVIDIA drivers refuse to load if they detect they are running in a VM):
|
|
Or in the VM config file (/etc/pve/qemu-server/101.conf):
cpu: host,hidden=1
args: -cpu host,kvm=off
Install NVIDIA drivers normally inside the VM — it sees the GPU as bare metal hardware.
Automation: REST API and Terraform
REST API
Every Proxmox operation is available via REST API. Get an API token:
User → API Tokens → Add
User: root@pam
Token ID: automation
Privilege Separation: unchecked (inherits user permissions)
Use the token:
|
|
Terraform with the Proxmox provider
The bpg/proxmox Terraform provider is the most complete and actively maintained option:
|
|
|
|
|
|
Useful CLI Commands
|
|
Honest Trade-offs
What Proxmox does well. The convergence of VMs, containers, storage, networking, clustering, HA, and backup in a single platform with a coherent UI is genuinely valuable. ZFS integration is first-class. The API is complete. For a homelab or SMB environment, it is an extraordinary amount of capability for zero licensing cost. The community is large and the documentation (the official admin guide, pve.proxmox.com/pve-docs) is thorough.
Subscription model. Proxmox is free to use but the stable enterprise repository and official support require a subscription (€105–€1,050/node/year depending on tier). The no-subscription repository works fine for homelab use and most small deployments. For production environments where upstream response time matters, a subscription is worth considering — it is cheap compared to VMware licensing.
LXC security caveats. Unprivileged LXC containers are reasonably secure but the shared kernel is a broader attack surface than a KVM VM. Container escapes, while uncommon, are not impossible and have a higher impact than VM escapes. For workloads handling sensitive data or exposed to external input, KVM VMs are the conservative choice.
Ceph operational complexity. Ceph is powerful and scales well, but it is not simple to operate. A degraded Ceph cluster can leave VMs inaccessible until the cluster heals. For a homelab with 2–3 nodes, ZFS on NFS is simpler and recoverable without understanding CRUSH maps and PG states. Ceph makes sense when you have 3+ nodes each with multiple dedicated storage disks and someone who understands how to recover it.
GPU passthrough caveats. The GPU is exclusively assigned to one VM. If the VM is off, the GPU is idle and unavailable to the host or other VMs. NVIDIA driver version matching between host (for VFIO) and guest (for computation) sometimes requires careful selection. Consumer NVIDIA GPUs (RTX series) do not support NVIDIA vGPU (which would allow sharing across VMs) without workarounds. If you need multiple VMs with GPU access, you need multiple GPUs or an enterprise card with SR-IOV support.
Migration network bottleneck. Without shared storage (Ceph or NFS), live migration copies the full disk over the migration network. A 100 GB VM disk on a 1GbE link takes over 10 minutes to copy — during which the VM is running on the source but will pause at the end for final synchronization. Plan your migration network for this.
Comments