Terraform files
- HCL 100%
| Claude test | ||
| Claude_test | ||
| .gitignore | ||
| butane.yaml.tftpl | ||
| main.tf | ||
| README.md | ||
| terraform.tfvars.example | ||
| variables.tf | ||
| versions.tf | ||
Fedora CoreOS on Proxmox via Terraform (bpg/proxmox)
Provisions a Fedora CoreOS VM on Proxmox from the official proxmoxve
image, with Ignition rendered from Butane in-process. The image always
resolves to the latest build on your chosen stream, and existing VMs are never
rebuilt when a new build is published.
How it works
data.httpreads the Fedora CoreOSstream.jsonat plan time and pulls the latestproxmoxveqcow2 URL + checksum.proxmox_virtual_environment_download_filedownloads it into Proxmox.decompression_algorithm = "zst"also transparently decompresses the.xz.ct_configtranspilesbutane.yaml.tftplto Ignition; it's stored as a Proxmox snippet (uploaded over SSH).proxmox_virtual_environment_vmboots from the image. Theproxmoxveplatform reads the Ignition from the attached config drive (delivered as cloud-inituser-data).lifecycle.ignore_changes = [disk[0].file_id]guarantees an upstream release can't trigger a rebuild of a running VM.
After first boot, Fedora CoreOS (Zincati) keeps the running OS updated on its own — Terraform's only job is the initial build.
Prerequisites in Proxmox (one-time)
- API token for a dedicated user with VM/datastore privileges.
- SSH access to the node for the token's user (snippet upload needs it).
ssh { agent = true }uses your local ssh-agent. - On the snippet datastore (default
local): enable the Snippets content type (Datacenter → Storage → select storage → Content). - On the image datastore (default
local): ISO image content enabled (on by default).
Usage
cp terraform.tfvars.example terraform.tfvars # then edit
# or: export PROXMOX_VE_API_TOKEN='terraform@pve!provider=...'
terraform init
terraform plan
terraform apply
Notes / troubleshooting
proxmoxvenot found / null during plan: your stream/arch may not carry it yet. Check:curl -s https://builds.coreos.fedoraproject.org/streams/stable.json | jq '.architectures.x86_64.artifacts.proxmoxve'wrong file extensionon download: the.imgfilename already works around this; it affects PVE older than 8.4.- Holding a node at a specific OS version (compliance, etc.) is a Zincati concern, not an image-pinning one — configure the Zincati update strategy in Butane rather than trying to control it from Terraform.
- If
decompression_algorithm = "zst"ever fails on the.xzin your PVE version, the fallback is tounxzthe image locally and upload it withproxmox_virtual_environment_file(content_type = "iso") instead.