Proxmox Auto Install Notes

Installation on WSL

sudo -i # to become root
echo "deb [arch=amd64] http://download.proxmox.com/debian/pve bookworm pve-no-subscription" > /etc/apt/sources.list.d/pve-install-repo.list
wget https://enterprise.proxmox.com/debian/proxmox-release-bookworm.gpg -O /etc/apt/trusted.gpg.d/proxmox-release-bookworm.gpg
apt update
apt install -y xorriso proxmox-auto-install-assistant

Answer File

Its a toml file and we use Tomlyn to load and save Models in C# to toml files.

format is like this:

[SECTION]
KEY = "VALUE"
KEY = [
    "VALUE1",
    "VALUE2"
]

it has these sections:

  • global

  • network

  • network.interface-name-pinning

  • network.interface-name-pinning.mapping

  • disk-setup

  • post-installation-webhook

  • first-boot

you can validate with

proxmox-auto-install-assistant validate-answer answer.toml

global

keyboard: de de-ch dk en-gb en-us es fi fr fr-be fr-ca fr-ch hu is it jp lt mk nl no pl pt pt-br se si tr

country: 2 letter code

fqdn option 1: HOSTNAME.DOMAIN

fqdn option 2: fqdn.source = "from-dhcp", fqdn.domain = "FALLBACKDOMAIN" → DHCP Server MUST supply a hostname

mailto: root user email

timezone: standard unix timezone, eg Europe/Zurich, or UTC

root-password: plain text (dont want), NOT use with hashed version

root-password-hashed: pre hashed with mkpasswd (via WSL on windows)

root-ssh-keys: optional ssh keys for root user

reboot-on-error: false (will halt on installation fail)

reboot-mode: reboot, (power-off doesnt make much sense)

network

either sets static from dhcp or all other options must be supplied

dhcp

source = "from-dhcp"

manual

source = "from-answer"

cidr = "x.x.x.x/N"

dns = "DNS IP ADDRESS"

gateway = "ROUTER IP ADDRESS"

filter: required for from-answer, not supported for from-dhcp. Uses dotted-key format with uppercase UDEV property names.

[network]
source = "from-answer"
cidr = "10.10.10.10/24"
dns = "10.10.10.1"
gateway = "10.10.10.1"
filter.ID_NET_NAME = "*"

Or to match by MAC-based name:

filter.ID_NET_NAME_MAC = "*AABBCCDDEEFF"
Note
MAC filter always has a * prefix because the interface name always has a prefix like "enx".

On Odroid devices, the first MAC is extracted from the serial number (which is a concatenation of all MACs, capped to 32 hex chars).

network.interface-name-pinning

enabled: true/false → controls if mapping section is used

network.interface-name-pinning.mapping

"MAC ADDRESS" = "INTERFACE NAME"

disk-setup

filesystem: ext4, xfs, zfs, btrfs → we want btrfs because snapshots make backups easy and small

disk-list: list of all disk devnames (eg sda, nvme0n) that should be added, ONLY that or filter

filter-match: "any" or "all" - required when using filter. "any" = match if any criterion matches, "all" = all must match.

filter.ID_SERIAL = "X" → can we get within winpe and write out

filter: uses dotted-key format with uppercase UDEV property names. Supports: ID_SERIAL, ID_MODEL, ID_VENDOR. Wildcards (*) supported.

[disk-setup]
filesystem = "btrfs"
filter-match = "any"
filter.ID_SERIAL = "SAMSUNG*"

zfs…​ options

lvm…​ options

btrfs…​ options ?

all support the optional options:

  • raid: raid0, raid1, raid10

  • hdsize: set max size in GB to be used of disk

  • compress: on, off, zlib, lzo, zstd (especially for btrfs)

post-installation-webhook

sends a post request with the system information to a url

url: post endpoint

cert-fingerprint: optional sha256 of the tls/ssl cert to verify endpoint

first-boot

optional, specify executable to run first time after boot, NETSetup ;)

source = "from-url" OR "from-iso"

ordering = "before-network" or "fully-up" → when to run the executable → then we can already auto create vms :D

url: where to download from, PUBLIC URL DIRECT DOWNLOAD (only for from-url)

cert-fingerprint: optional sha256 of the tls/ssl cert to verify endpoint (only for from-url)

from-iso details

The auto-installer reads the executable from /cdrom/proxmox-first-boot (max 1 MiB). It must be baked into the ISO at build time with prepare-iso --on-first-boot <script>. The installer copies it to /var/lib/proxmox-first-boot/proxmox-first-boot on the target, enables a systemd service (proxmox-first-boot-{ordering}.service), and runs it once on first boot.

Source: pve-installer/proxmox-auto-installer/src/bin/proxmox-auto-installer.rs line 49, pve-installer/Proxmox/Install.pm function setup_proxmox_first_boot_service.

NETSetup first-boot bootstrap (DONE)

A generic bootstrap script (netsetup-first-boot.sh) is baked into every prepared ISO. It runs once on first boot (via PVE’s proxmox-first-boot-fully-up.service) and:

  1. Downloads the NETSetup linux-x64 ELF binary from Dropbox

  2. Copies machine-specific config from the SYSTEM partition (if USB still present)

  3. Creates a systemd service + timer for periodic NETSetup runs (on boot + every 6h)

  4. Runs NETSetup install immediately

The script is generic — machine identity comes from the running system (serial number, MAC, hostname from answer.toml).

Source: src/NETSetup/Resources/netsetup-first-boot.sh

C# side: WithFirstBootFromIso() in ProxmoxAutoInstallBuilder generates the [first-boot] section in answer.toml. Called automatically by ToProxmoxAutoInstall() for all Proxmox configs.

Assistant Usage / ISO Creation

We want 1 iso to rule them all. We achieve this by modifying a regular iso only to look for the partition SYSTEM and in there for the answer file. The file must lie directly on partition root with name "answer.toml".

# 1. download current ISO from https://www.proxmox.com/en/downloads/proxmox-virtual-environment/iso
wget -O ISOPATH https://enterprise.proxmox.com/iso/proxmox-ve_9.1-1.iso

# 2. patch ISO: answer-file from SYSTEM partition + first-boot script baked in
proxmox-auto-install-assistant prepare-iso ISOPATH \
    --fetch-from partition --partition-label SYSTEM \
    --on-first-boot netsetup-first-boot.sh

Now you have the current iso to put into Dropbox Images, so we can later download using NETSetup.

Be sure to update the README.txt so its clear when and what are latest version.