Skip to main content
RunBook Academy

Proxmox VEXXI · Migration to ProxmoxCloud to Proxmox

Cloud-to-Proxmox: importing AWS, Azure, and GCP images

Advanced⏱ ~22 minqemu-imgaws CLI optionalaz CLI optionalgcloud optional

What you'll learn

  • Pull public cloud images into Proxmox without rebuilding
  • Convert cloud disk formats AMI, VHD, raw to Proxmox storage
  • Decouple cloud-specific provisioning cloud-init, user-data
  • Identify workloads that are NOT worth migrating off-cloud

Prerequisites

Verified against Proxmox VE 9.2.4 · Proxmox Backup Server 4.2.5 · Ceph Squid / Tentacle · Debian 13 (Trixie) · Linux kernel 7.0 (PVE 9.2 default) · 2026-08-07

Not yet marked complete on this device.

The cloud repatriation wave

After a decade of “go cloud first”, many organisations are moving workloads back on-prem. Common drivers:

  • Predictable costs — capex vs runaway variable bills
  • Latency — colocated systems can’t beat on-prem LAN
  • Data gravity — large datasets are expensive to move and egress fees add up
  • Compliance — some regulations require data to stay in specific jurisdictions
  • Vendor lock-in avoidance — AWS-specific services are hard to leave

This lesson covers how to actually bring cloud images into Proxmox. The tooling differs per provider but the workflow is the same: export, convert, import, decouple cloud-init.

Step 0: Decide if migration is worth it

Not every workload should come back on-prem. Use this rough decision matrix:

Workload typeMigrate?Notes
Stateless web/API tierYesEasy, saves a lot
Database on dedicated EC2/EBSMaybeCompare RDS cost vs your storage costs
Managed database (RDS, Cloud SQL)Probably notRefactor to self-hosted DBMS is risky
Serverless (Lambda, Cloud Functions)NoArchitecture mismatch
Big-data (EMR, BigQuery, Dataproc)NoWrong toolset
GPU compute (P4, A100)MaybeIf your on-prem GPU is competitive
Internal dev/test VMsYesBig cost saver
Legacy monolith VMYesMost common driver

From AWS

EC2 instances run on EBS volumes (which are essentially snapshots over S3) or instance-store (ephemeral). For migration, you want EBS-backed instances.

Step 1: Find the AMI

# Get the AMI ID from a running instance
aws ec2 describe-instances --instance-ids i-0abc123 --query 'Reservations[].Instances[].ImageId'

# Or list your own AMIs
aws ec2 describe-images --owners self --query 'Images[].[ImageId,Name,CreationDate]'

Step 2: Export the AMI to S3

# Create an S3 bucket and an IAM role for VM Import/Export first
# (See AWS docs for the exact policy)

# Export the AMI as VMDK, VHD, or RAW
aws ec2 export-image \
  --image-id ami-0abc123 \
  --disk-image-format VMDK \
  --s3-export-location S3Bucket=my-export-bucket,S3Prefix=exports/

# Wait for the export task to complete
aws ec2 describe-export-image-tasks --query 'ExportImageTasks[].Status'

Step 3: Download

aws s3 cp s3://my-export-bucket/exports/ami-0abc123.vmdk ./

Step 4: Convert

qemu-img convert -f vmdk -O qcow2 ami-0abc123.vmdk vm-200-disk-0.qcow2

From Azure

Azure VMs use VHD (sometimes VHDX for Gen 2) on managed disks. The export path is straightforward but slow.

Step 1: Deallocate the VM (required for export)

# Stop the VM (do NOT deallocate first if you want the disk state preserved)
# Then snapshot the OS disk:
az snapshot create \
  --resource-group myResourceGroup \
  --name mySnapshot \
  --source /subscriptions/<sub>/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/myVM_OsDisk_1_<GUID>

# Get the SAS URL to download the VHD
az snapshot grant-access --name mySnapshot --duration-in-seconds 3600

Step 2: Download

Read-only / Safe
# Use the SAS URL returned above
wget "<SAS_URL>" -O osdisk.vhd

Step 3: Convert

# Azure VHD has 512-byte footer alignment; qemu-img handles it natively
qemu-img convert -f vpc -O qcow2 osdisk.vhd vm-201-disk-0.qcow2

From GCP

GCP supports exporting a custom image to Cloud Storage as a raw disk file. There’s no direct VM export — you create an image from the boot disk first.

Step 1: Create an image from the instance’s boot disk

# Stop the instance first (saves state)
gcloud compute instances stop my-vm --zone us-central1-a

# Create an image
gcloud compute images create my-vm-image \
  --source-disk my-vm \
  --source-disk-zone us-central1-a \
  --family debian-12

Step 2: Export the image

# Create a Cloud Storage bucket first
gsutil mb gs://my-vm-export/

# Export (writes a .tar.gz containing a disk.raw file)
gcloud compute images export \
  --destination-uri gs://my-vm-export/my-vm.tar.gz \
  --image my-vm-image \
  --format raw

Step 3: Download and extract

gsutil cp gs://my-vm-export/my-vm.tar.gz ./
tar -xzf my-vm.tar.gz disk.raw

Step 4: Convert

qemu-img convert -f raw -O qcow2 disk.raw vm-202-disk-0.qcow2

Step 5: Decouple cloud-init

Cloud VMs ship with cloud-init pre-configured. On Proxmox, cloud-init is fine but the datasource must match. If you keep the cloud-init metadata pointing at the cloud provider’s metadata service (169.254.169.254), the guest will hang or misbehave.

On the Proxmox side

Proxmox has built-in cloud-init support that writes an nocloud datasource to a CD-ROM.

qm set 200 --ide2 local-lvm:cloudinit
qm set 200 --ciuser admin
qm set 200 --cipassword 'change-me-now'
qm set 200 --ipconfig0 ip=10.0.0.50/24,gw=10.0.0.1
qm set 200 --sshkeys ~/.ssh/id_rsa.pub

On the guest side

On first boot in Proxmox, cloud-init will read the nocloud CD. The guest’s existing cloud-init config will see a new datasource. To prevent the guest from re-reaching out to AWS/GCP/Azure metadata:

Read-only / Safe
# Inside the guest, disable the cloud-specific datasource
# Debian/Ubuntu
echo "datasource_list: [NoCloud]" > /etc/cloud/cloud.cfg.d/99-pve.cfg

# RHEL/CentOS
echo "datasource_list: [NoCloud]" > /etc/cloud/cloud.cfg.d/99-pve.cfg

# Clean up cloud-init state so it re-runs on first Proxmox boot
cloud-init clean -l

Step 6: License and activation

Cloud VMs typically have:

  • Windows — KMS-style activation tied to the cloud provider; needs re-activation with your on-prem KMS
  • RHEL — Cloud Access subscription tied to your Red Hat account; bring your entitlement to on-prem
  • Ubuntu Pro — token-based; re-attach with pro attach
  • SQL Server — may downgrade to evaluation mode; activate with your licence

Plan for these. They are the most common cause of “the migration worked but the VM won’t start its database”.

Step 7: Validate

  • Boots cleanly
  • Network connectivity (with the Proxmox-set IP, not the cloud one)
  • Cloud-init reapplied the right config
  • Licence is valid
  • Application services start
  • Backup runs successfully
  • No more calls to 169.254.169.254 (check with tcpdump or strace)

Network reconfiguration

Cloud VMs typically have a single NIC with DHCP from the cloud’s metadata service. In Proxmox:

  • Set the IP statically (via cloud-init) or via DHCP (Proxmox doesn’t run a DHCP server by default — set one up or use static IPs)
  • Update /etc/hosts and any service-specific config that references the old cloud name/IP
  • Update DNS records (split-horizon DNS is a common gotcha; the old cloud IP might still be in DNS)

Bandwidth and timing

A typical “export a VM from cloud” timeline:

StepTime
AWS export-image task5-60 minutes
S3 download (100 GB) over 1 Gbps15 minutes
qemu-img convert5-15 minutes
Total30-90 minutes per VM

Egress costs from AWS/Azure/GCP can be significant — check the bill before mass-migrating. Often it’s cheaper to keep the source VM running for an extra week and use a separate, faster transfer path (e.g., AWS Snowball, Azure Data Box) for bulk moves.

Key takeaways

  • Cloud VMs can be exported, but it takes time and incurs egress fees
  • AWS → VMDK, Azure → VHD/VHDX, GCP → raw.tar.gz
  • All convert with qemu-img
  • Decouple cloud-init from the cloud metadata service before first boot
  • Watch for licence re-activation and DNS record updates
  • Not every workload is worth bringing back; do the cost math first

Knowledge check

Knowledge check · 4 questions

  1. Q1. Which qemu-img input format is used for an AWS export-image task in VMDK format?

  2. Q2. Which cloud-init datasource should you configure on a Proxmox-imported cloud VM?

  3. Q3. Which command extracts an AWS EC2 image to a local file as VMDK?

  4. Q4. Reconstruct the answer from the lesson context.

Passing score: 75%. Answers are checked in this browser.