> For the complete documentation index, see [llms.txt](https://docs.ionos.com/cloud/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ionos.com/cloud/compute-services/compute-engine/confidential-computing-vm/api-how-tos/prepare-confidential-vm-image.md).

# Prepare a Confidential VM Image

Build a Confidential VM image with LUKS encryption, LAUNCH\_ARTIFACTS partition, firmware, and attestation support for IONOS CLOUD.

A Confidential VM image is a standard `QCOW2` file with a dedicated `LAUNCH_ARTIFACTS` partition that the <code class="expression">space.vars.ionos\_cloud</code> platform reads at VM start to configure the hardware-enforced startup. `LAUNCH_ARTIFACTS` is an <code class="expression">space.vars.ionos\_cloud</code>-specific mechanism that lets you bundle all required binaries, including firmware, kernel, `initrd`, and configuration, into a single image, rather than managing them as separate files.

{% hint style="warning" %}
**Important:** You cannot use the standard <code class="expression">space.vars.ionos\_cloud</code> images for a Confidential VM. You must build your own image with the required `LAUNCH_ARTIFACTS` partition. This is a consequence of the [<mark style="color:blue;">zero-trust principle</mark>](/cloud/compute-services/compute-engine/confidential-computing-vm/overview/security-and-trust-model.md).
{% endhint %}

{% hint style="info" %}
**Prerequisites:**

* A supported Linux distribution (Debian 13+ or Ubuntu 24.04 LTS+)
* SNPGuard toolchain or a custom image pipeline
* FTP access to your <code class="expression">space.vars.ionos\_cloud</code> account
* GitHub CLI `gh` installed and authenticated for firmware verification
* Access to your target Linux distribution's official release repositories and checksums
  {% endhint %}

## How to prepare a Confidential VM image

{% stepper %}
{% step %}

### Understand image requirements

Your `QCOW2` image needs the following:

1. **An encrypted root filesystem:** Encrypt the root filesystem with [<mark style="color:blue;">Linux Unified Key Setup (LUKS)</mark>](https://docs.ionos.com/cloud/support/general-information/glossary-of-terms#linux-unified-key-setup-luks). Consistent with zero trust, you hold the disk key, not <code class="expression">space.vars.ionos\_cloud</code>, so you must apply the disk encryption. Without it, the confidentiality guarantee does not cover your data on disk.
2. **`LAUNCH_ARTIFACTS` partition:** Create a separate partition that the platform reads at startup.

{% hint style="warning" %}
**Important:**

* **Disk encryption and attestation:** Confidential VMs protect data in memory and during execution, but not data on disk. To secure your virtual drive, encrypt it using a method such as `LUKS2`.
* **As a best practice, use attestation:** Your [<mark style="color:blue;">attestation service</mark>](https://docs.ionos.com/cloud/support/general-information/glossary-of-terms#attestation-service) can release the volume encryption key after verifying the VM's measurements. This is an example pattern, not a requirement.
* **IONOS CLOUD boundaries:** We do not require a specific encryption method, cannot troubleshoot your encryption setup, and have no knowledge of your attestation implementation. You must choose and manage your own disk encryption and key release mechanisms.
  {% endhint %}
  {% endstep %}

{% step %}

### Create LAUNCH\_ARTIFACTS partition

#### 1. Create a GUID Partition Table (GPT)

Create a separate [<mark style="color:blue;">GUID Partition Table (GPT)</mark>](https://docs.ionos.com/cloud/support/general-information/glossary-of-terms#guid-partition-table-gpt) primary partition, format it as `ext4`, and label it `LAUNCH_ARTIFACTS` (exact, case-sensitive). The partition mounts at `/artifacts/` inside the image, and you cannot write to this drive from within the guest. It must contain all files the <code class="expression">space.vars.ionos\_cloud</code> platform needs to configure your VM at startup.

{% hint style="warning" %}
**Important:**

* Ensure the names match the list of **Files** mentioned in the following table. All files must be placed in the `/artifacts/` directory of the `LAUNCH_ARTIFACTS` partition with the exact filenames. A file named `initrd` instead of `initrd.img`, or `firmware.fd` instead of `firmware-code.fd`, will cause upload rejection by the upload handler. Throughout the documentation, `initrd` refers to the component conceptually; the required filename in the partition is always `initrd.img`.
* The **mandatory** files must be sourced from your target Linux distribution.
* Kernel parameters can be extracted from the `GRUB` configuration file or read from the running kernel command line.
* The **optional** files support the attestation flow and VM ownership verification and are required during attestation. They are not mandatory if attestation is not used. Their structure and content are defined in the [<mark style="color:blue;">AMD SEV Secure Nested Paging Firmware ABI Specification</mark>](https://docs.amd.com/v/u/en-US/56860_PUB_1.58_SEV_SNP).
* The platform reads these artifacts at startup to configure `QEMU` exactly to your specifications. The AMD hardware includes the `firmware-code.fd`, `kernel`, `initrd`, and `kernel-params.txt` in the cryptographic launch measurement. While the platform excludes `launch-config.json` from the measurement itself, this file instructs the host how to configure the VM; any configuration mismatch causes the AMD hardware to reject the startup sequence immediately.
  {% endhint %}

**All files listed below go into the `/artifacts/` folder:**

| **Files**            | **Type**                                                                                                                             | **Mandatory/Optional** | **Purpose**                                                                                                                                                                                                                                                                                                                                     | **Location**                                              |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
| `launch-config.json` | Config (JSON)                                                                                                                        | **Mandatory**          | Guest [<mark style="color:blue;">launch configuration</mark>](#2-configure-launch-configjson). VM startup configuration read by the <code class="expression">space.vars.ionos\_cloud</code> platform. **The file size cannot exceed 1 KB**.                                                                                                     | —                                                         |
| `firmware-code.fd`   | Guest [<mark style="color:blue;">firmware (UEFI/OVMF) binary</mark>](#3-verify-the-ovmf-firmware) compiled with `SNP_KERNEL_HASHES`. | **Mandatory**          | UEFI firmware that initialises the VM before the kernel loads. You can download them from <code class="expression">space.vars.ionos\_cloud</code> builds. **The file size cannot exceed 50 MB**.                                                                                                                                                | —                                                         |
| `vmlinuz`            | Compressed Linux kernel binary                                                                                                       | **Mandatory**          | The kernel launched by the firmware. **The file size cannot exceed 50 MB**.                                                                                                                                                                                                                                                                     | `/boot` directory                                         |
| `initrd.img`         | Initial ramdisk archive                                                                                                              | **Mandatory**          | Boots before the OS. If you are using attestation, embed the attestation client inside the initrd. Without attestation, the initrd is still required but does not need an attestation agent. **The file size cannot exceed 150 MB**.                                                                                                            | `/boot` directory                                         |
| `kernel-params.txt`  | Plain text, single line                                                                                                              | **Mandatory**          | Kernel command-line parameters passed to the kernel at startup. **The file size cannot exceed 4 KB**.                                                                                                                                                                                                                                           | `/boot/grub/grub.cfg` or `/proc/cmdline` (running kernel) |
| `id-block.bin`       | Binary                                                                                                                               | **Optional**           | [<mark style="color:blue;">ID Block</mark>](https://docs.ionos.com/cloud/support/general-information/glossary-of-terms#id-block) that binds the VM identity to a [<mark style="color:blue;">measurement</mark>](https://docs.ionos.com/cloud/support/general-information/glossary-of-terms#measurement). **The file must be exactly 96 bytes**. | —                                                         |
| `id-auth.bin`        | Binary                                                                                                                               | **Optional**           | Authentication information for the ID Block. **The file must be exactly 4096 bytes**.                                                                                                                                                                                                                                                           | —                                                         |

#### 2. Configure `launch-config.json`

The `launch-config.json` file tells the <code class="expression">space.vars.ionos\_cloud</code> platform how to configure `QEMU` on starting the VM. If the configuration at startup does not match what was measured, the AMD Secure Processor rejects the start.

```json
{
  "guest-policy": "0x30000",
  "vcpu-count": 4,
  "vcpu-model": "<cpuFamily-from-enabledFeatures-API>"
}
```

{% hint style="warning" %}
**Important:** Both `cpuFamily` and `cores` are derived from the `launch-config.json` file; do not set either when creating the VM.
{% endhint %}

| **Field**          | **Type** | **Required** | **Value**                                 | **Description**                                                                                                                                                                                                                                                  |
| ------------------ | -------- | ------------ | ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`guest-policy`** | String   | Yes          | `"0x30000"`                               | Fixed by <code class="expression">space.vars.ionos\_cloud</code>. Cannot be changed. Translates to: `DEBUG` disabled (<code class="expression">space.vars.ionos\_cloud</code> cannot inspect VM memory), live migration disabled, SMT (hyper-threading) allowed. |
| **`vcpu-count`**   | Integer  | Yes          | Positive even integer                     | The number of vCPUs the VM is created with. **This value must be an even number.** The platform derives the VM's core count from this field, so you do not specify cores separately in the API request.                                                          |
| **`vcpu-model`**   | String   | Yes          | CPU family name. Example: `"EPYC-Turin"`. | Must match a Confidential VM-capable CPU family at your target location. The `cpuFamily` value `AMD_TURIN` maps directly to the `vcpu-model` argument `"EPYC-Turin"`.                                                                                            |

To find valid values, call `GET /locations/{locationId}` and look for CPU family objects that have `AMD_SEV_SNP` in their `enabledFeatures` array to find which `cpuFamily` values are valid at your target location. The `maxCores` is the upper bound for `vcpu-count`.

Each `cpuFamily` value corresponds to a `vcpu-model` argument; these are different strings:

| **`cpuFamily` (API value)** | **`vcpu-model` (image value)** |
| --------------------------- | ------------------------------ |
| `AMD_TURIN`                 | `EPYC-Turin`                   |
| `AMD_EPYC`                  | `EPYC-Milan`                   |

```bash
GET /cloudapi/v6/locations/{locationId}
# inspect cpuArchitecture[].enabledFeatures for "SEV-SNP"
```

#### 3. Verify the OVMF firmware

<code class="expression">space.vars.ionos\_cloud</code> provides a verified [<mark style="color:blue;">OVMF</mark>](https://docs.ionos.com/cloud/support/general-information/glossary-of-terms#ovmf) firmware binary, published as `AMDSEV-OVMF.fd`:

1. Download it from the [<mark style="color:blue;">ionos-cloud/edk2 releases page</mark>](https://github.com/ionos-cloud/edk2/releases) and verify it using the following command:

```bash
curl -L -o AMDSEV-OVMF.fd https://github.com/ionos-cloud/edk2/releases/latest/download/AMDSEV-OVMF.fd
```

2. Verify the [<mark style="color:blue;">SLSA provenance</mark>](https://docs.ionos.com/cloud/support/general-information/glossary-of-terms#supply-chain-levels-for-software-artifacts-slsa-provenance):

{% hint style="warning" %}
**Important:** You must authenticate with GitHub before running the following command.
{% endhint %}

```bash
gh attestation verify AMDSEV-OVMF.fd --repo ionos-cloud/edk2
```

3. Rename the OVMF firmware binary to `firmware-code.fd` and place it in the `LAUNCH_ARTIFACTS` partition.

{% hint style="warning" %}
**Important:** Do not modify the firmware binary after you verify it. If the `gh attestation verify` command fails, download the binary again from the official release.
{% endhint %}

#### 4. Embed `kernel` and `initrd`

Before embedding `vmlinuz` and `initrd.img` into the `LAUNCH_ARTIFACTS` partition, verify their checksums against your Linux distribution's official published checksums. This confirms the binaries have not been modified between download and use and were built from trusted sources.

Download the checksum file directly from your distribution's official release page, not from a mirror or third-party source.

```bash
# Example for Ubuntu; replace with your distribution's checksum file
sha256sum -c SHA256SUMS --ignore-missing
```

{% endstep %}

{% step %}

### Build the image

Choose one of the following approaches to build your image:

* [<mark style="color:blue;">**SNPGuard**</mark>](https://github.com/ionos-cloud/snp-guard)**:** The <code class="expression">space.vars.ionos\_cloud</code> open-source reference toolchain. It automates `LUKS` encryption, attestation client injection, and artifact embedding. Recommended for users working with Debian 13+ or Ubuntu 24.04 LTS+. Refer to the SNPGuard repository for detailed build instructions and examples.
* **Custom toolchain:** Bring your own image pipeline. Use this approach if you prefer to manage each step manually or work with a distribution not listed below. Your image must conform to the [<mark style="color:blue;">artifact requirements</mark>](#2-configure-launch-configjson), specifically the partition structure, file naming, and `launch-config.json` format. Ensure all files are placed correctly in `/artifacts/` and verify your image against the [<mark style="color:blue;">verification checklist</mark>](#verify-your-image) before upload.

{% hint style="info" %}
**Note:** SNPGuard officially supports Debian 13+ and Ubuntu 24.04 LTS+. If your target distribution is not listed, use the custom toolchain approach, provided it is SEV-SNP-compatible.
{% endhint %}
{% endstep %}

{% step %}

### Verify your image

Use the following checklist to verify your image before uploading it to the <code class="expression">space.vars.ionos\_cloud</code> `/confidential-images/` FTP folder. The upload handler performs these same checks and rejects images that fail any of them.

{% hint style="info" %}
**Note:** Use the following checklist as a final review step. Confirm every item before uploading, as the image becomes immutable after upload.
{% endhint %}

<details>

<summary><strong>Partition and files</strong></summary>

* A partition labeled `LAUNCH_ARTIFACTS` exists in the [<mark style="color:blue;">QCOW2</mark>](https://docs.ionos.com/cloud/support/general-information/glossary-of-terms#qemu-copy-on-write-qcow) image.
* The partition is formatted as `ext4`.
* The partition label is exactly `LAUNCH_ARTIFACTS`, case-sensitive, with no spaces or extra characters.
* The `/artifacts/` directory exists inside the partition.
* `firmware-code.fd` is present in `/artifacts/` and non-empty.
* `vmlinuz` is present in `/artifacts/` and non-empty.
* `initrd.img` is present in `/artifacts/` and non-empty.
* `kernel-params.txt` is present in `/artifacts/`, non-empty, and contains a single line.
* `launch-config.json` is present in `/artifacts/` and non-empty.

</details>

<details>

<summary><strong>Verify launch-config.json</strong></summary>

* `launch-config.json` is valid JSON (no syntax errors).
* `guest-policy` field is present and set to `"0x30000"`.
* `vcpu-count` field is present and set to a positive integer.
* `vcpu-model` field is present and matches the `cpuFamily` name of a Confidential VM-capable CPU family at your target location.

</details>

<details>

<summary><strong>Firmware and binaries</strong></summary>

* `firmware-code.fd` was compiled with the `SNP_KERNEL_HASHES` flag.
* `firmware-code.fd` passes SHA-256 checksum verification against the published `SHA256SUMS`.
* `firmware-code.fd` passes `gh attestation verify` against `ionos-cloud/edk2`.
* `vmlinuz` and `initrd.img` checksums verified against your distribution's official published checksums.
* *(If using attestation)* The measurement was registered with your attestation service **after** the final `initrd.img` was embedded.
* Cloud-init v1 (no-cloud) is not used.

</details>
{% endstep %}

{% step %}

### Upload using FTP

Upload your `QCOW2` image to your <code class="expression">space.vars.ionos\_cloud</code> FTP storage within the `/confidential-images/` folder. Do not save it in the standard `/images/` folder.

The upload handler checks structure, not content: it confirms required files are present, filenames match exactly, `launch-config.json` is valid JSON with the correct `guest-policy` value, and the partition label is correct. It does not verify the content of your firmware, kernel, or `initrd`. Verifying those against trusted sources is your responsibility before upload.

{% hint style="info" %}
**Note:**

* **FTP credentials:** Your FTP credentials are the same as your standard <code class="expression">space.vars.ionos\_cloud</code> FTP credentials.
* **Image immutability:** Once uploaded, the image cannot be modified. Any change to firmware, kernel, initrd, or `launch-config.json` requires building and uploading a new image.
  {% endhint %}

```bash
ftp ftp-<location>.ionos.com # Remember to replace the location placeholder with your specific location code. Example: ftp-fra-2.ionos.com.
cd /confidential-images/
put your-image.qcow2
```

{% endstep %}
{% endstepper %}

{% hint style="success" %}
**Result:** Your Confidential VM image is now uploaded and ready to use for provisioning Confidential VM instances.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.ionos.com/cloud/compute-services/compute-engine/confidential-computing-vm/api-how-tos/prepare-confidential-vm-image.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
