Installing Proxmox VE 9 on a Debian 13 cloud image: what breaks, and the fixes
The official “Install Proxmox VE on Debian 13” steps assume a normal install. A cloud image with cloud-init is not one. These are the nine problems we hit building Proxmox VE VPSes, in the order they bite.
Proxmox publishes no cloud image, so on a VPS the supported route is the one in the official wiki: install Proxmox VE on top of Debian 13. That page assumes a normal Debian install. A cloud image is different — cloud-init owns the hostname and network, the bootloader has no install device recorded, and the network is netplan rather than ifupdown. We converted cloud images in place to build our Proxmox VE VPS product, and every item below broke a build before we fixed it.
- The order that works
- 1. pmxcfs: “Unable to resolve node name”
- 2. apt: “You must correct your GRUB install devices”
- 3. Install the kernel first, reboot, then proxmox-ve
- 4. Web UI errors: pve-ssl.pem does not exist
- 5. “storage does not support content type images”
- 6. The bridge config vanishes on reboot
- 7. Validating the network file before you reboot
- 8. netplan, systemd-networkd and resolved fight ifupdown2
- 9. Reboots that look finished but aren’t
The order that works
- Fix
/etc/hostsand stop cloud-init rewriting it (problem 1). - Preseed GRUB’s install device (problem 2).
- Add the Proxmox repository,
apt full-upgrade, installproxmox-default-kernel, reboot into the PVE kernel. - Install
proxmox-ve postfix open-iscsi chrony, regenerate the node certificate, set storage content types (problems 4–5). - Remove the stock Debian kernel and
os-prober. - Write the
vmbr0bridge, validate it, delete the pendinginterfaces.new, switch off netplan/networkd (problems 6–8). - Reboot, then confirm the node is healthy (problem 9).
Do the package work while the cloud-init network is still in place, and change the network last. Every fix below is from that sequence.
1. pmxcfs: “Unable to resolve node name”
The Proxmox cluster filesystem refuses to start if the node’s hostname resolves to a loopback address:
Unable to resolve node name 'pve-node' to a non-loopback IP addressCloud images map the hostname to 127.0.1.1, so you fix /etc/hosts — and on the next boot cloud-init puts it back. If the provider’s cloud-init user-data says manage_etc_hosts: true, that beats anything you set in /etc/cloud/cloud.cfg, so manage_etc_hosts: false there does nothing. What user-data can’t override is a module that isn’t in the list. Remove it, then write the hosts file:
sed -i '/^ - update_etc_hosts$/d' /etc/cloud/cloud.cfg
cat > /etc/hosts <<EOF
127.0.0.1 localhost
203.0.113.10 pve-node.localdomain pve-node pvelocalhost
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
EOF
hostname -i # must print 203.0.113.10, not 127.0.1.1On a VPS behind one-to-one NAT, the node’s own address is the private one on its network interface, not the public IP. Use what ip -4 addr shows.
2. apt: “You must correct your GRUB install devices”
Debian’s cloud images ship grub-pc with no install device recorded. Installing the Proxmox kernel triggers a GRUB reconfiguration, which fails — and takes the whole apt transaction down with it. Preseed the device first. On virtio disks there is no /dev/disk/by-id entry, so the bare device node is what you have:
disk=$(lsblk -ndo PKNAME "$(findmnt -no SOURCE /)") # usually vda
echo "grub-pc grub-pc/install_devices multiselect /dev/$disk" | debconf-set-selections
echo "grub-pc grub-pc/install_devices_failed_upgrade boolean true" | debconf-set-selections3. Install the kernel first, reboot, then proxmox-ve
As the wiki describes, Proxmox VE goes on in two steps: the PVE kernel, a reboot into it, then the rest. With the repository added (the wiki has the keyring and the pve-no-subscription source):
apt update && apt full-upgrade -y
apt install -y proxmox-default-kernel
reboot
# after the reboot — confirm, then install the rest
uname -r # must end in -pve
apt install -y proxmox-ve postfix open-iscsi chrony
# then drop the Debian kernel so GRUB can't boot it
apt remove -y linux-image-amd64 'linux-image-6.12*' os-prober
update-grubRun dpkg --audit after each install. It should print nothing; anything it lists is a half-configured package you’ll trip over later.
4. Web UI errors: pve-ssl.pem does not exist
If pve-cluster wasn’t running while proxmox-ve installed — which is exactly what problem 1 causes — the node certificate is never generated. pvesh get /nodes shows the node as unknown and complains that /etc/pve/nodes/<node>/pve-ssl.pem doesn’t exist. Start the cluster service and regenerate:
systemctl start pve-cluster
pvecm updatecerts -f
systemctl restart pvedaemon pveproxy pvestatd5. “storage does not support content type images”
A Debian-based install had no /etc/pve/storage.cfg on our build, so the local storage used built-in defaults — and the first “Create VM” failed because local wouldn’t hold disk images. If you see that error, set the content types explicitly:
pvesm set local --content images,iso,vztmpl,backup,snippets,rootdir
pvesm status --content images # local should now be listed6. The bridge config vanishes on reboot
This is the one that cost us the most time. Installing proxmox-ve leaves a pending /etc/network/interfaces.new — Proxmox’s own view of the network, with no bridge. A boot-time service, pvenetcommit, moves any pending file over /etc/network/interfaces early in every boot. So “install proxmox-ve, write vmbr0, reboot” brings the node up with no usable network. Because mv keeps the old file’s timestamp, the file you find afterwards looks older than your edit, as if your write never happened.
The fix is one line, after you’ve written your config:
rm -f /etc/network/interfaces.newThe full story, and how to recover a node that already came up without a network, is in Proxmox lost its network after a reboot?
7. Validating the network file before you reboot
A broken interfaces file on a remote server means a reboot you can’t come back from, so check it first. Three traps:
ifqueryis not a validator: it exits 0 for a file with a bogus address and an emptybridge-ports.ifup -sdoes parse properly, but exits non-zero on mere warnings — includingbridge-fd 0, which Proxmox itself writes. The exit code can’t be your gate.- Before
networking.servicehas ever run, ifupdown2’s lock directory doesn’t exist and every command fails with “Another instance of this program is already running.”
What works: write the new file somewhere else, create the lock directory, and look for lines starting with error:.
mkdir -p /run/network
ifup -s -a -i /root/interfaces.candidate 2>&1 | grep '^error:' \
&& echo "do NOT install this file" \
|| install -m 0644 /root/interfaces.candidate /etc/network/interfacesA minimal single-NIC bridge (replace the NIC name, address and gateway with yours):
auto lo
iface lo inet loopback
iface enp1s0 inet manual
auto vmbr0
iface vmbr0 inet static
address 203.0.113.10/24
gateway 203.0.113.1
bridge-ports enp1s0
bridge-stp off
bridge-fd 0
source /etc/network/interfaces.d/*8. netplan, systemd-networkd and resolved fight ifupdown2
Cloud images configure the network with netplan and systemd-networkd. Proxmox uses ifupdown2. Leave both in place and they race at boot. Move netplan’s files aside and hand DNS to a plain resolv.conf:
mkdir -p /etc/netplan.disabled
mv /etc/netplan/*.yaml /etc/netplan.disabled/
systemctl disable --now systemd-networkd.socket systemd-networkd systemd-networkd-wait-online
systemctl disable --now systemd-resolved
rm -f /etc/resolv.conf
printf 'nameserver 1.1.1.1\nnameserver 8.8.8.8\n' > /etc/resolv.conf
systemctl enable networkingWhatever netplan configured goes with it — including any IPv6 address. If your server had IPv6, add an iface vmbr0 inet6 static stanza to the new file before you reboot.
9. Reboots that look finished but aren’t
A Proxmox node takes two to three minutes to shut down when it has VMs, because it stops them first. If you script the reboot and poll port 22, you can reach the old boot moments before it goes down and conclude it came back. Compare the boot ID instead:
before=$(cat /proc/sys/kernel/random/boot_id)
reboot
# ...later, over SSH:
[ "$(cat /proc/sys/kernel/random/boot_id)" != "$before" ] && systemctl is-system-runningThen check what matters: the PVE kernel is running, pve-cluster, pvedaemon, pveproxy and pvestatd are active, vmbr0 has the address and the default route, the web UI on port 8006 answers, local accepts images, /dev/kvm exists, and dpkg --audit is clean. Those are the checks we run before any node is handed over.
/dev/kvm deserves a word: without hardware virtualization exposed to your server, Proxmox installs fine, but its VMs won’t start until you turn off KVM acceleration for them — and then they run in slow software emulation. Check before you start.