You spin up a fresh Ubuntu VM in Proxmox, and now come the ten manual steps: log into the console, set a hostname, configure a static IP, add your SSH key, run updates, maybe create a user. Do that once and it's fine. Do it for the fifth test VM this week and it gets old fast.
Cloud-init is the piece of Proxmox VE that gets rid of most of that busywork. It's not a Proxmox invention — it's an industry-standard tool that ships inside official cloud images from Ubuntu, Debian, Rocky Linux, and others — but Proxmox has built-in support for driving it directly from the web interface, no scripting required. This guide explains what cloud-init actually is, how Proxmox uses it, and walks through the Cloud-Init tab so you know what each field does before you touch it.
What You Will Learn
- What cloud-init is and why it exists outside of Proxmox too
- How Proxmox VE feeds configuration into a VM using cloud-init
- The difference between cloud-init and the QEMU Guest Agent (people mix these up constantly)
- How to find and use the Cloud-Init tab on a VM in the Proxmox web interface
- The commands running underneath the GUI, if you'd rather work from the shell
- Errors you'll hit the first time you try this, and how to fix them
What Is This Feature?
Cloud-init is a small program that runs once, early in a Linux system's boot process, and looks for a data source containing configuration it should apply. That data source can be a metadata service on a cloud provider like AWS or Hetzner — or, in Proxmox's case, a tiny virtual CD-ROM that Proxmox generates and attaches to the VM.
When you create a VM in Proxmox and add a CloudInit Drive, Proxmox writes three files onto that virtual disc: user-data, meta-data, and network-config. These are plain YAML files describing the hostname, the default user account, SSH keys, and network settings. On first boot, cloud-init (already installed inside the guest OS, assuming you used a proper cloud image) reads that disc, applies the settings, and then gets out of the way. It doesn't run again unless you force it to.
The important thing to understand: cloud-init only works if it's already installed inside the operating system you're running. A stock Ubuntu Desktop ISO doesn't have it. The "cloud" or "generic cloud" images published by Ubuntu, Debian, Rocky Linux, and AlmaLinux do — that's specifically what they're built for.
Why Would You Use It?
The honest answer: if you only ever build one or two VMs by hand, you probably don't need this. The Proxmox installer wizard is fine for that. Cloud-init earns its keep once you're recreating similar VMs more than a couple of times — a test environment you tear down weekly, a fleet of identical web servers, or a homelab where you're constantly trying new self-hosted apps and don't want to repeat the same setup checklist every time.
It also removes a category of mistakes. Typing a static IP into a console by hand every time is exactly the kind of task where you eventually fat-finger an octet at 11pm. Baking the network config into cloud-init and letting it apply automatically on boot means it's consistent every single time.
And it plays well with automation tools. If you ever end up driving Proxmox from Terraform or a script, cloud-init is the mechanism those tools use under the hood to configure the VMs they create. Understanding it now means the automation side makes sense later instead of feeling like a black box.
Prerequisites
- A working Proxmox VE 8.x or 9.x host with web UI access — the Cloud-Init tab looks and works the same on both.
- A VM built from an actual cloud image (Ubuntu Server cloud image, Debian generic cloud image, Rocky Linux GenericCloud, etc.), not a VM installed manually from a desktop or server ISO. If you don't have one yet, most Proxmox community scripts and template libraries produce cloud-init-ready VMs already.
- An SSH key pair on the machine you're connecting from. If you don't have one:
ssh-keygen -t ed25519. - About ten minutes.
Step-by-Step Tutorial
Step 1: Check whether the VM already has a Cloud-Init drive
Click on the VM in the left-hand tree, and look for a Cloud-Init entry underneath the Hardware tab in the left sidebar. If you see it, someone (or some script) already attached a cloud-init drive and you can skip to Step 3. If Cloud-Init doesn't appear in the menu at all, the VM doesn't have the drive yet, and the tab stays hidden until it does.
Step 2: Add a Cloud-Init Drive
Go to the VM's Hardware tab, click Add, and choose CloudInit Drive. Pick a storage location — any storage that can hold disk images works, it doesn't need to be the same storage as the VM's main disk. This creates a tiny (around 4 MB) drive, usually mapped to ide2. Once it's added, the Cloud-Init tab appears in the sidebar.
Step 3: Set the default user and SSH key
Open the Cloud-Init tab. Click Edit next to User and set a username. Then click Edit next to SSH public key and paste in the contents of your .pub file — the whole line, starting with ssh-ed25519 or ssh-rsa. Skip the Password field unless you have a specific reason to want password-based login; key-based auth is the safer default and it's what most cloud images expect anyway.
Step 4: Configure networking
Click Edit next to IPv4 under the network section. You'll get a choice between DHCP and Static. DHCP is the easiest starting point — your router hands out an address and you're done. For a static address, enter it in CIDR form, like 192.168.1.50/24, along with the gateway.
Step 5: Set DNS (optional)
By default, the VM inherits DNS settings from the Proxmox host. If you want it to use something different, set DNS domain and DNS servers under the Cloud-Init tab.
Step 6: Regenerate the image and boot
Any time you change a Cloud-Init setting on a VM that hasn't booted yet, Proxmox regenerates the drive automatically the next time you start it. If the VM has already been started once before, click Regenerate Image at the top of the Cloud-Init tab to force it to pick up your new settings, then start the VM.
Step 7: Confirm it actually applied
SSH into the VM using the key you set, then run:
cloud-init status --long
You're looking for status: done. If it says degraded or lists an error, that's your cue to check the logs, covered below in Troubleshooting.
Commands Explained
Everything the GUI does has a shell command behind it, in case you'd rather script this or just understand what's happening:
| Command | What it does |
|---|---|
qm set <vmid> --ide2 local-lvm:cloudinit | Creates and attaches a Cloud-Init drive on the specified storage. |
qm set <vmid> --ciuser myuser | Sets the default username cloud-init creates or configures on first boot. |
qm set <vmid> --sshkeys ~/.ssh/id_ed25519.pub | Injects your public key into the generated cloud-init data so you can log in without a password. |
qm set <vmid> --ipconfig0 ip=dhcp | Sets the first network interface to request an address via DHCP. |
qm set <vmid> --ipconfig0 ip=192.168.1.50/24,gw=192.168.1.1 | Sets a static IP and gateway on the first network interface instead. |
qm cloudinit dump <vmid> user | Prints the exact user-data YAML Proxmox is going to hand the guest, so you can check it before booting. |
cloud-init status --long | Run inside the guest, not on the Proxmox host — shows whether cloud-init finished successfully. |
Common Errors
The Cloud-Init tab is missing entirely
The VM doesn't have a Cloud-Init drive yet. Add one from the Hardware tab as described in Step 2 — the tab only shows up once that drive exists.
You set everything correctly but nothing applies on boot
This is almost always because the disk image isn't actually a cloud image. If you installed the OS from a normal ISO through the regular installer, cloud-init was never on the disk to begin with, and no amount of GUI configuration in Proxmox will make it appear.
"SSH public key" field rejects your paste
Proxmox expects a plain OpenSSH-format public key on a single line. If you're pasting from PuTTY's key format, or you accidentally copied a private key, it'll be rejected. Use the contents of the .pub file as-is.
Static IP doesn't stick after a reboot
Cloud-init only fully applies its configuration once, on a VM's first boot. Rebooting a VM that's already completed its first boot won't reprocess your Cloud-Init settings — you'd need to force a clean run (see Troubleshooting) or it's simply working as intended and something else changed the address.
Troubleshooting
Start inside the guest, not on the Proxmox host. Run cloud-init status --long first — it tells you plainly whether cloud-init thinks it succeeded, failed, or is still running.
If something looks wrong, check the two log files cloud-init writes: /var/log/cloud-init.log for the detailed processing log, and /var/log/cloud-init-output.log for what actually printed to the console during the run. Nine times out of ten, the actual error message is sitting right there.
If you need to test a configuration change on a VM that's already booted once, cloud-init won't rerun on its own. Force it with:
cloud-init clean --logs
reboot
Treat that as a debugging step for a lab VM, not something you run on a production machine without thinking it through — it wipes cloud-init's record of having already run and makes the next boot behave like a brand-new instance.
If networking specifically isn't landing right, check whether the guest OS is using netplan and whether some other config file is conflicting with what cloud-init wrote. On Ubuntu cloud images this is usually under /etc/netplan/.
Best Practices
- Use SSH keys, not the Password field. Password auth over SSH is disabled by default on most cloud images anyway, so setting a cloud-init password often does nothing useful.
- Leave networking on DHCP for anything you plan to template and clone repeatedly, then override the IP per clone. Baking a static IP into a template just means every clone fights over the same address.
- Don't turn on Upgrade packages for VMs where boot speed matters. It runs a full package update on every first boot, which is fine for a one-off VM but adds real time if you're spinning up several at once.
- Check
qm cloudinit dump <vmid> userbefore you boot anything you're not sure about. It costs nothing and catches typos before they become a broken first boot.
Frequently Asked Questions
Is cloud-init the same thing as the QEMU Guest Agent?
No, and this trips people up constantly. The QEMU Guest Agent is a background service that lets Proxmox talk to the running guest — reporting its real IP address, allowing clean shutdowns, and so on. Cloud-init only runs once, at first boot, to apply initial configuration. You'll often want both, but they do completely different jobs.
Does cloud-init work with any Linux distribution I install?
Only if that specific disk image had cloud-init installed on it. The official "cloud" or "generic cloud" images from major distributions ship with it. A distro installed the normal way, through its regular installer, generally won't have it unless you install the cloud-init package yourself afterward.
Can I use cloud-init with LXC containers instead of VMs?
No. Cloud-init in Proxmox applies to virtual machines only. LXC containers use a different, simpler mechanism built into Proxmox itself for setting hostname, network, and SSH keys at creation time.
Do I need internet access for cloud-init to do its job?
Not for the basics — hostname, user creation, SSH keys, and static IP all happen locally, no internet required. You only need connectivity if you've enabled Upgrade packages or written a custom snippet that downloads something.
Will cloud-init overwrite settings I change manually inside the guest later?
No. It only runs on what it considers a genuinely new instance's first boot. Manual changes you make afterward are safe unless you deliberately force cloud-init to run again.
Conclusion
Once you've seen the Cloud-Init tab do its job on a single VM, the appeal is obvious: no console typing, no repeated setup checklist, no risk of fat-fingering a static IP at midnight. It's a small feature on the surface, but it's the foundation everything else — templates, clones, Terraform-driven deployments — is built on top of. Start by trying it on one VM built from a proper cloud image, and the rest of the Proxmox automation story starts making a lot more sense.