# ova2vzdump *[English](#english) · [Deutsch](#deutsch)* Convert OVA appliances (VirtualBox / VMware export) into **Proxmox vzdump** `.vma.zst` backup files that can be restored with `qmrestore`. The tricky part is `vma`, the proprietary container format Proxmox uses for QEMU backups. The `vma` binary only ships with Proxmox, so this tool runs inside a Docker image that installs `pve-qemu-kvm` from the Proxmox no-subscription apt repo. That way you can convert appliances on any machine with Docker — no PVE host required. ## Pipeline 1. Extract OVA tar → OVF descriptor + VMDK disk(s) 2. Parse OVF XML → CPU, memory, disks, NICs 3. `qemu-img convert` each VMDK → raw 4. Synthesize a `qemu-server.conf` 5. `vma create` packs raws + conf → `.vma` 6. `zstd` compresses → `vzdump-qemu--.vma.zst` ## Usage ### Build the image ```bash docker compose build ``` ### Web UI ```bash docker compose up # browse http://localhost:8880 ``` Uploads land in `./data/uploads`, results in `./data/output`. ### Getting a test OVA ova2vzdump ships a built-in test OVA generator — both the CLI and the web UI have a dedicated entry point. Two modes: - **stub** (default, ~1 KB): valid OVA with an empty VMDK. Fast, exercises the full `extract → parse → qemu-img → vma → zstd` pipeline. Not bootable. - **bootable** (~80 MB): packages a pre-cached **Alpine Linux** raw image (downloaded during `docker build`, sha512-verified). After `qmrestore` on Proxmox the VM actually boots to an Alpine login prompt — this is what you want for a real end-to-end test. Existing test OVAs are reused by default; pass `--force` to rebuild. #### CLI ```bash # stub: docker compose run --rm ova2vzdump create-test-ova \ /data/uploads/test.ova --name demo # bootable Alpine: docker compose run --rm ova2vzdump create-test-ova \ /data/uploads/alpine.ova --name alpine --bootable # rebuild: docker compose run --rm ova2vzdump create-test-ova \ /data/uploads/test.ova --force ``` #### Web UI Click the **Create test OVA** tab, pick a name, tick **Bootable** if you want real Alpine, hit Create. The list at the bottom shows what's already in the upload directory and offers direct download. The generated OVA also appears as an available input on the **Convert** tab. If you'd rather grab a real-world appliance from elsewhere: - **TurnKey Linux Core** (~250 MB): [turnkeylinux.org/core](https://www.turnkeylinux.org/core) → VM build. - **DIY**: export any small VM from VirtualBox via `File → Export Appliance…` → `.ova`. ### CLI ```bash docker run --rm \ -v "$PWD/data/uploads:/in" \ -v "$PWD/data/output:/out" \ ova2vzdump:latest convert /in/appliance.ova /out \ --vmid 123 --storage local-lvm ``` Output filename looks like `vzdump-qemu-123-2026_04_21-12_30_00.vma.zst`. ### Restore on Proxmox Copy the `.vma.zst` onto a PVE node into a backup-capable storage (for example `/var/lib/vz/dump/`), then: ```bash qmrestore vzdump-qemu-123-2026_04_21-12_30_00.vma.zst 123 --storage local-lvm ``` ## Options | Flag | Meaning | Default | | ---- | ------- | ------- | | `--vmid` | **Placeholder** VMID — overridden at restore time | `100` | | `--storage` | **Placeholder** storage name in qemu-server.conf — overridden by `qmrestore --storage` | `local-lvm` | | `--keep-workdir` | Keep intermediate raw disks + vma for debugging | off | > `qmrestore [--storage ]` always decides the > real VMID and storage. The values baked into the archive are only > placeholders; you can leave the defaults for most use cases and only > tweak them if you want a meaningful filename like > `vzdump-qemu--*.vma.zst`. ## Config mapping | OVF | qemu-server.conf | | --- | ---------------- | | `VirtualHardwareSection` CPU quantity | `cores` | | `VirtualHardwareSection` memory | `memory` (MiB) | | OS description heuristic (`linux`/`windows`/…) | `ostype` (`l26` / `win10` / `other`) | | Disks w/ SCSI controller | `scsiN` + `scsihw: virtio-scsi-pci` | | Disks w/ SATA controller | `sataN` | | Disks w/ IDE controller | `ideN` | | Ethernet subtype | `netN: =auto,bridge=vmbr0` | Heuristics are conservative; review the generated config after restore before booting production workloads. ## Limitations - OVF 1.x / 2.x only (DMTF envelope namespace). - `manifest`, `cert`, and signed OVAs are not verified. - Firmware (BIOS vs. UEFI) is not read from OVF — defaults to SeaBIOS. Edit the config after restore if your appliance needs OVMF. - MAC addresses are not preserved (Proxmox assigns new ones on import). ## Local development (without Docker) You need `qemu-img`, `vma`, and `zstd` on your PATH — i.e. you must be on a Proxmox host. Then: ```bash pip install -e . ova2vzdump convert appliance.ova ./out ``` --- # ova2vzdump (Deutsch) Konvertiert OVA-Appliances (Export aus VirtualBox / VMware) in **Proxmox vzdump** `.vma.zst`-Backup-Dateien, die sich mit `qmrestore` direkt zurückspielen lassen. Der knifflige Teil ist `vma` — das proprietäre Container-Format, in dem Proxmox seine QEMU-Backups speichert. Die `vma`-Binary gibt es nur mit Proxmox, deshalb läuft dieses Tool in einem Docker-Image, das `pve-qemu-kvm` aus dem Proxmox-No-Subscription-Apt-Repo installiert. Dadurch kannst du Appliances auf jeder Maschine mit Docker konvertieren — ganz ohne PVE-Host. ## Pipeline 1. OVA-Tar entpacken → OVF-Descriptor + VMDK-Disk(s) 2. OVF-XML parsen → CPU, RAM, Disks, NICs 3. Jede VMDK mit `qemu-img convert` nach raw konvertieren 4. Eine `qemu-server.conf` generieren 5. `vma create` packt raws + config → `.vma` 6. `zstd` komprimiert → `vzdump-qemu--.vma.zst` ## Benutzung ### Image bauen ```bash docker compose build ``` ### Web-UI ```bash docker compose up # dann http://localhost:8880 öffnen ``` Uploads landen in `./data/uploads`, Ergebnisse in `./data/output`. ### Test-OVA bekommen ova2vzdump bringt einen eingebauten Test-OVA-Generator mit — sowohl die CLI als auch die Web-UI haben einen eigenen Einstiegspunkt. Zwei Modi: - **stub** (Default, ~1 KB): valide OVA mit leerer VMDK. Schnell, testet die komplette Pipeline `extract → parse → qemu-img → vma → zstd`. Nicht bootbar. - **bootable** (~80 MB): verpackt ein vorgecachtes **Alpine-Linux**-Raw- Image (wird beim `docker build` heruntergeladen, sha512-verifiziert). Nach `qmrestore` auf Proxmox bootet die VM tatsächlich in einen Alpine-Login — das ist der echte End-to-End-Test. Vorhandene Test-OVAs werden standardmäßig wiederverwendet; `--force` baut neu. #### CLI ```bash # Stub: docker compose run --rm ova2vzdump create-test-ova \ /data/uploads/test.ova --name demo # Bootbares Alpine: docker compose run --rm ova2vzdump create-test-ova \ /data/uploads/alpine.ova --name alpine --bootable # Neu bauen: docker compose run --rm ova2vzdump create-test-ova \ /data/uploads/test.ova --force ``` #### Web-UI Auf den Tab **Create test OVA** klicken, Name wählen, Häkchen bei **Bootable** setzen wenn du echtes Alpine willst, auf Create klicken. Die Liste unten zeigt, was im Upload-Verzeichnis liegt, mit direkten Download-Buttons. Die erzeugte OVA erscheint auch im **Convert**-Tab als auswählbare Eingabe. Lieber eine echte Appliance von woanders? - **TurnKey Linux Core** (~250 MB): [turnkeylinux.org/core](https://www.turnkeylinux.org/core) → VM-Build. - **DIY**: irgendeine kleine VM aus VirtualBox exportieren via `Datei → Appliance exportieren…` → `.ova`. ### CLI (Konvertierung) ```bash docker run --rm \ -v "$PWD/data/uploads:/in" \ -v "$PWD/data/output:/out" \ ova2vzdump:latest convert /in/appliance.ova /out \ --vmid 123 --storage local-lvm ``` Der Ausgabedateiname sieht etwa so aus: `vzdump-qemu-123-2026_04_21-12_30_00.vma.zst`. ### Restore auf Proxmox Die `.vma.zst` auf einen PVE-Node in ein backup-fähiges Storage kopieren (z.B. `/var/lib/vz/dump/`), dann: ```bash qmrestore vzdump-qemu-123-2026_04_21-12_30_00.vma.zst 123 --storage local-lvm ``` ## Optionen | Flag | Bedeutung | Default | | ---- | --------- | ------- | | `--vmid` | **Platzhalter**-VMID — wird beim Restore überschrieben | `100` | | `--storage` | **Platzhalter**-Storage-Name in `qemu-server.conf` — wird durch `qmrestore --storage` überschrieben | `local-lvm` | | `--keep-workdir` | Zwischenergebnisse (raw-Disks, vma) behalten, zum Debuggen | aus | > `qmrestore [--storage ]` entscheidet immer die > echte VMID und das Storage. Die Werte im Archiv sind nur Platzhalter — > Defaults reichen meist. Du passt sie höchstens an, wenn du einen > sprechenden Dateinamen haben willst, z.B. > `vzdump-qemu--*.vma.zst`. ## Config-Mapping | OVF | qemu-server.conf | | --- | ---------------- | | `VirtualHardwareSection` CPU-Anzahl | `cores` | | `VirtualHardwareSection` RAM | `memory` (MiB) | | OS-Description-Heuristik (`linux`/`windows`/…) | `ostype` (`l26` / `win10` / `other`) | | Disks am SCSI-Controller | `scsiN` + `scsihw: virtio-scsi-pci` | | Disks am SATA-Controller | `sataN` | | Disks am IDE-Controller | `ideN` | | Ethernet-Subtyp | `netN: =auto,bridge=vmbr0` | Die Heuristiken sind konservativ; bitte die generierte Config nach dem Restore einmal prüfen, bevor du produktive Workloads startest. ## Limitierungen - Nur OVF 1.x / 2.x (DMTF-Envelope-Namespace). - `manifest`, `cert` und signierte OVAs werden nicht verifiziert. - Firmware (BIOS vs. UEFI) wird nicht aus der OVF gelesen — Default ist SeaBIOS. Config nach dem Restore manuell anpassen, falls deine Appliance OVMF braucht. - MAC-Adressen werden nicht übernommen (Proxmox vergibt beim Import neue). ## Lokale Entwicklung (ohne Docker) Du brauchst `qemu-img`, `vma` und `zstd` im PATH — also de facto einen Proxmox-Host. Dann: ```bash pip install -e . ova2vzdump convert appliance.ova ./out ```