When my vCenter and ESXi licenses expired, I needed free alternatives. Hereโ€™s what I found and how to set it up.


vCenter / ESXi Alternatives

Replaces both ESXi + vCenter in a single install.

VMware Feature Proxmox Equivalent
ESXi Proxmox VE (KVM+QEMU)
vCenter Built-in web UI
vMotion Live migration
VMFS LVM / LVM-thin / ZFS
Distributed Switch Linux bridges

Best for: Homelabs, small clusters


2. XCP-ng + Xen Orchestra

VMware XCP-ng Stack
ESXi XCP-ng
vCenter Xen Orchestra

Best for: VMware-like architecture


3. KVM + libvirt (Minimal)

VMware KVM Stack
ESXi KVM (kernel)
vCenter libvirt/virt-manager

Best for: DIY, automation-heavy


Quick Decision

Use Case Choice
Homelab Proxmox
VMware-like XCP-ng
Minimal KVM

Proxmox Installation

1. Download ISO

From proxmox.com


2. Create Bootable USB (Mac)

sudo dd if=proxmox-ve.iso of=/dev/diskX bs=4M status=progress

Or use Balena Etcher.


3. BIOS Settings

  • Disable Secure Boot
  • Enable VT-x / VT-d
  • Boot mode = UEFI

4. Install Proxmox

Boot from USB โ†’ follow installer:

Option Recommendation
Disk Internal SSD
Filesystem ZFS (gives snapshots)
IP Static (important for cluster)

5. First Login

https://<IP>:8006
user: root
password: (your่ฎพ็ฝฎ็š„ๅฏ†็ )

Configure Updates

Remove Enterprise Repo

sed -i 's/^deb/#deb/g' /etc/apt/sources.list.d/pve-enterprise.list
echo "deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription" > /etc/apt/sources.list.d/pve-no-subscription.list
apt update && apt full-upgrade -y

Remove Subscription Popup

sed -i "s/data.status !== 'Active'/false/g" /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js
systemctl restart pveproxy

Make Popup Fix Persistent

Create apt hook:

echo 'DPkg::Post-Invoke {
  "sed -i \"s/data.status !== '\"'\"Active'\"'\"'/false/g\" /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js || true";
  "systemctl restart pveproxy || true";
};' > /etc/apt/apt.conf.d/99proxmox-popup-fix

Option A: iSCSI + LVM

On QNAP / SAN

  1. Storage & Snapshots โ†’ iSCSI
  2. Create Target (e.g., proxmox-target)
  3. Create Block-based LUN (NOT file-based)
  4. Attach LUN to target
  5. Note the Target IQN

On Proxmox

  1. Datacenter โ†’ Storage โ†’ Add โ†’ iSCSI
    • ID: qnap-iscsi
    • Portal: <QNAP-IP>
    • Target: select discovered IQN
  2. Add โ†’ LVM
    • ID: qnap-lvm
    • Base storage: qnap-iscsi
    • Volume: (your LUN)
    • Content: Disk image
  3. (Recommended) Add โ†’ LVM-Thin for snapshots

Option B: NFS

On NAS (QNAP/Synology/TrueNAS)

  1. Create NFS share
  2. Allow access from Proxmox IP
  3. Mount options: rw,no_root_squash,subdir_check=

On Proxmox

  1. Datacenter โ†’ Storage โ†’ Add โ†’ NFS
    • ID: qnap-nfs
    • IP: <NAS-IP>
    • Export: <nfs-share-path>
    • Content: Disk image, ISO image

Quick Comparison

Storage When to Use
iSCSI + LVM SAN-style, block access
NFS Simpler, file-based
ZFS (local) Single node, snapshots
Ceph Multi-node HCI

Cluster Setup (Optional)

1. Prepare Nodes

Set hostname:

hostnamectl set-hostname pve1

Update /etc/hosts on ALL nodes:

192.168.1.10 pve1
192.168.1.11 pve2
192.168.1.12 pve3

Enable passwordless SSH:

ssh-copy-id root@pve2

2. Create Cluster

On pve1:

pvecm create homelab-cluster

On other nodes:

pvecm add 192.168.1.10

Verify:

pvecm nodes

3. Enable HA

  1. Datacenter โ†’ HA โ†’ Groups โ†’ Create
  2. Add nodes
  3. Select VM โ†’ More โ†’ Manage HA

Note: 2-Node Cluster

Set expected votes to avoid quorum issues:

pvecm expected 1

Common Mistakes

  • Using file-based LUN instead of block-based
  • Running iSCSI over WiFi
  • Mixing VM traffic + storage on same NIC
  • Not adding LVM layer (iSCSI alone wonโ€™t store VMs)

Next Steps

  • Add cloud-init templates for VM provisioning
  • Set up backups with Proxmox Backup Server
  • Add Ceph for hyperconverged storage (3+ nodes)


Ansible Automation

Inventory

[proxmox_nodes]
pve1 ansible_host=192.168.1.10
pve2 ansible_host=192.168.1.11
pve3 ansible_host=192.168.1.12

[proxmox_nodes:vars]
ansible_user=root
proxmox_ntp_server: "pool.ntp.org"

Playbook: Configure No-Subscription Updates

- name: Configure Proxmox no-subscription repo
  hosts: proxmox_nodes
  become: true

  vars:
    proxmox_ntp_server: "pool.ntp.org"

  tasks:
    - name: Disable enterprise repo
      shell: |
        sed -i 's/^deb/#deb/g' /etc/apt/sources.list.d/pve-enterprise.list

    - name: Add no-subscription repo
      ansible.builtin.copy:
        content: |
          deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription
        dest: /etc/apt/sources.list.d/pve-no-subscription.list

    - name: Remove subscription popup
      ansible.builtin.replace:
        path: /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js
        regexp: "data.status !== 'Active'"
        replace: "false"

    - name: Restart web service
      ansible.builtin.service:
        name: pveproxy
        state: restarted

    - name: Create apt hook for popup fix
      ansible.builtin.copy:
        content: |
          DPkg::Post-Invoke {
            "sed -i \"s/data.status !== 'Active'/false/g\" /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js || true";
            "systemctl restart pveproxy || true";
          };
        dest: /etc/apt/apt.conf.d/99proxmox-popup-fix

    - name: Install chrony
      ansible.builtin.apt:
        name: chrony
        state: present

    - name: Configure NTP server
      ansible.builtin.lineinfile:
        path: /etc/chrony/chrony.conf
        regexp: "^server"
        line: "server  iburst"
        state: present

    - name: Enable and start chrony
      ansible.builtin.service:
        name: chrony
        enabled: yes
        state: started

    - name: Run apt update
      ansible.builtin.apt:
        update_cache: yes
        cache_valid_time: 3600

    - name: Upgrade packages
      ansible.builtin.apt:
        upgrade: full

Run

ansible-playbook -i inventory.ini proxmox-setup.yml