⚡ Frank Villaro-Dixon's website

Launching CoreOS images on Proxmox, the easy way

How to launch CoreOS VMs on proxmox and configure them with Ignition files

useful

TL;DR: Use the ibmcloud image, and it will work :)

The problem

Although Red Hat Enterprise Linux CoreOS or Fedora CoreOS don’t officially support Proxmox yet, it’s possible to launch CoreOS on Proxmox and use it with Ignition, with some small workarounds.

CoreOS uses Ignition files to setup and configure itself. Ignition is a bit like cloud-init. It uses configuration files that must be known by the machine.

There are various ways to provide these files. Some cloud providers like Exoscale, Azure, etc., provide the metadata through a metadata HTTP service.

Other platforms, like OpenStack (which also uses a metadata service), and in our case Proxmox, provide a virtual drive to the VM.

This drive (a virtual CD, labeled cidata), contains files with the metadata provided to the VM:

myself@proxmox-vm:~$ ls /dev/disk/by-label/ -lah
total 0
---8<----snip----8<---
lrwxrwxrwx. 1 root root   9 Mar 20 09:40 cidata -> ../../sr0
---8<----snip----8<---

Ignition provides a proxmoxve provider, but it is not activated in the provided CoreOS images.

Indeed, contrary to cloud-init, which kind of tries every possible source and then merges back the results together, CoreOS specifies to ignition which provider it should use with the use of a kernel argument:

ignition.platform=xxx

Thus, if the image uses platform=qemu, then it won’t try the proxmoxve source. Which is kind of a shame.

Crappy solution

There are some alternative solutions, for example providing kvm with extra args containing the path to the configuration, like so:

resource "proxmox_virtual_environment_vm" "fcos" {
    
    kvm_arguments = "-fw_cfg name=opt/com.coreos/config,file=/path/to/config.ign"
}

or even:

resource "proxmox_virtual_environment_vm" "fcos" {
    
    kvm_arguments = "-fw_cfg name=opt/com.coreos/config,string=${replace(ign_string, ",", ",,")}'"
}

In my opinion, this is not very clean, because we start messing with the hypervisor and bypass its runtime and file storage API.

Manual solution

One manual solution is to, when booting up the VM, change the command line of grub, but of course this is horrible and not automated:

proxmox grub

Automated solution

So the “best” way would be to be able to generate the correct image with the correct provider, but it is a bit of a pain and takes a while to generate.

However, looking at the source code of Ignition I found out that the ibmcloud provider is basically the same as the proxmoxve one. Thus, a really simple solution is to use this image instead.

Terraform steps

The following steps use the bpg/proxmox=0.73.1 provider.

Importing the image

Sadly, Proxmox’s backend cannot import qcow2 images compressed with xz.

To solve this, the image must either be transferred manually, or downloaded and uncompressed on the machine running terraform:

wget https://builds.coreos.fedoraproject.org/prod/streams/stable/builds/41.20250302.3.2/x86_64/fedora-coreos-41.20250302.3.2-ibmcloud.x86_64.qcow2.xz

unxz fedora-coreos-41.20250302.3.2-ibmcloud.x86_64.qcow2.xz

mv fedora-coreos-41.20250302.3.2-ibmcloud.x86_64.qcow2 fedora-coreos-41.20250302.3.2-ibmcloud.x86_64.img

It can then be uploaded with the simple terraform ressource:

resource "proxmox_virtual_environment_file" "fcos" {
  content_type = "iso"
  datastore_id = "local"
  node_name    = var.node_name

  source_file {
    path = "fedora-coreos-41.20250302.3.2-ibmcloud.x86_64.img"
  }
  overwrite = false
}

Spawning the VM

Now, we just have to spawn up the VM:

resource "proxmox_virtual_environment_vm" "fcos" {
  name      = "fcos"
  node_name = var.node_name

  cpu {
    cores = 4
  }

  memory {
    dedicated = 4096
    floating = 16000
  }

  disk {
    datastore_id = "local-lvm"
    file_format = "qcow2"
    file_id      = proxmox_virtual_environment_file.fcos.id
    interface    = "virtio0"
    iothread     = true
    discard      = "on"
    size         = 100
  }

  initialization {
    user_data_file_id = proxmox_virtual_environment_file.ignition.id
  }
}

resource "proxmox_virtual_environment_file" "ignition" {
  content_type = "snippets"
  datastore_id = "local"
  node_name    = var.node_name

  source_file {
    path = "my-ignition.ign"
  }
  overwrite = true
}

Enjoy!