> For the complete documentation index, see [llms.txt](https://docs.platform9.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.platform9.com/private-cloud-director/virtualized-clusters/virtual-tpm.md).

# Virtual TPM

This guide outlines the implementation and configuration requirements for Virtual Trusted Platform Module (vTPM) v2.0 support in <code class="expression">space.vars.product\_name</code>.

## What is Virtual Trusted Platform Module (vTPM)

A Trusted Platform Module (TPM) is a specialized hardware chip on your computer's motherboard that is designed to enhance your computer's security by securely storing cryptographic keys that are used for encryption and decryption.

vTPM v2.0 is a software-based representation of a traditional TPM 2.0 chip. It carries out the same hardware-based security functions as a physical Trusted Platform Module, such as attestation, key and random number generation, but without the physical TPM chip being required.

<code class="expression">space.vars.product\_name</code>'s vTPM solution leverages open source Barbican service for encryption management. <code class="expression">space.vars.product\_name</code>'s Virtual TPM service enables TPM support by default on <code class="expression">space.vars.product\_name</code> hypervisor hosts.

## TPM Version and Models Supported

The Virtual TPM configuration is controlled through **metadata that can be applied at the virtual machine image level**.

<code class="expression">space.vars.product\_name</code> currently only supports TPM version 2.0. <code class="expression">space.vars.product\_acronym</code> supports two models for vTPM

* `tpm-tis`: This option emulates a TPM device based on the TPM Interface Specification, which is the standard for TPM version 1.2.
* `tpm-crb`: This option emulates a TPM device based on the TPM 2.0 CRB (Chip Reference Board) specification.

## Image Preparation and Configuration

When you add TPM metadata to an image, any VM created using the image will automatically enable vTPM with the specified configuration. The metadata parameters control:

* The TPM model type (`tpm-tis` or `tpm-crb`)

You can apply these configurations by adding metadata to the image as below:

#### Image-level Properties

Following is the TPM metadata that you need to associate with a virtual machine image in order to enable vTPM for the VMs created with the image.

{% tabs %}
{% tab title="YAML" %}

```yaml
hw_tpm_version = 2.0
hw_tpm_model = tpm-crb
```

{% endtab %}
{% endtabs %}

For example, you might start with a standard Windows image without TPM support and later add TPM 2.0 support by updating the image metadata. Any new VMs created from this image will have TPM 2.0 enabled, while existing VMs remain unchanged.

Similarly, if you create a VM using an image with these tags, do not remove these metadata keys while you have active vTPM VMs as it may lead to unexpected failures.

#### Flavor-level Properties

To enable the support of vTPM live migration, ensure the flavor has the metadata

{% tabs %}
{% tab title="YAML" %}

```yaml
hw:tpm_secret_security = deployment
```

{% endtab %}
{% endtabs %}

Please note that this can only be set on the flavor metadata, not the image metadata.

#### Shared swtpm State Directory

The directory `/var/lib/libvirt/swtpm` must be shared across all compute hosts. Use NFS with the following mount options:

```
vers=3,local_lock=all
```

#### Consistent swtpm UID Across Hosts

Ensure that the swtpm user ID matches across all hosts. Platform9 pins this to UID 64130 starting 2026.4 release. If your UIDs are not consistent across hosts, please fix them so they are consistent. While doing this, you may also have to change the ownership of `/var/lib/swtpm-localca` to the swtpm user again.

## VM Deployment and Verification

1. Create a VM with vTPM support through the <code class="expression">space.vars.product\_name</code> UI
2. Make sure that the VM reaches "Active" state
3. Perform TPM verification:

#### TPM Verification for Windows VMs

{% tabs %}
{% tab title="YAML" %}

```yaml
1. Press Windows key + R
2. Execute tpm.msc
```

{% endtab %}
{% endtabs %}

#### TPM Verification For Linux VMs:

{% tabs %}
{% tab title="YAML" %}

```yaml
ls /dev | grep tpm    # Should show TPM device
```

{% endtab %}
{% endtabs %}

#### General TPM Verification:

{% tabs %}
{% tab title="YAML" %}

```yaml
# List running VMs
virsh list

# Verify TPM configuration
virsh dumpxml <VM_ID>
```

{% endtab %}
{% endtabs %}

Expected TPM configuration in XML:

{% tabs %}
{% tab title="YAML" %}

```yaml
<tpm model='tpm-crb'>
  <backend type='emulator' version='2.0' persistent_state='yes'>
    <encryption secret='<secret>'/>
  </backend>
  <alias name='tpm0'/>
</tpm>
```

{% endtab %}
{% endtabs %}

## Secret Management Verification

Run the following command to make sure that the secrets got created successfully:

{% tabs %}
{% tab title="YAML" %}

```yaml
openstack secret list
```

{% endtab %}
{% endtabs %}

Each VM with TPM should have a corresponding secret entry.

## vTPM State File

VTPM state files are located on directory `/var/lib/libvirt/swtpm` by default on the hypervisor host.

## Live Migration of vTPM-Enabled VMs

### Prerequisites for vTPM Live Migration

Live-migrating a VM with vTPM enabled requires additional setup beyond the standard [live migration prerequisites](/private-cloud-director/virtualized-clusters/virtualmachine/vm-migration.md#live-migration-prerequisites). Because the vTPM emulator (`swtpm`) maintains state files for each VM, those files must be accessible on both the source and destination host during and after the migration.

All four conditions below must be satisfied before attempting live migration of a vTPM-enabled VM:

#### 1. Flavor Must Include the TPM Secret Security Property

The VM's flavor must have the following extra spec set:

```
hw:tpm_secret_security = deployment
```

Without this property, the Compute Service will not attempt to transfer the vTPM secret during migration. The VM may migrate but the vTPM device will fail to start on the destination host.

This property can only be set on the flavor, not the image:

```bash
pcdctl flavor set <FLAVOR_NAME> --property hw:tpm_secret_security=deployment
```

{% hint style="warning" %}
This flavor property must be set before the VM is created. Updating the flavor after a VM has been created does not retroactively enable vTPM migration support for that VM.
{% endhint %}

#### 2. Shared swtpm State Directory (NFS)

The swtpm state directory `/var/lib/libvirt/swtpm` must be mounted from the same NFS share on all compute hosts in the cluster. If the state directory is local to each host, the destination host will not have access to the VM's TPM state after migration.

Mount options must include:

```
vers=3,local_lock=all
```

Verify the mount is consistent across hosts:

```bash
# Run on each host — output should be identical
mount | grep swtpm
```

#### 3. Consistent swtpm UID Across All Hosts

The `swtpm` user must have the same numeric UID on every compute host. <code class="expression">space.vars.product\_name</code> pins this to **UID 64130** starting with the 2026.4 release. If hosts were added at different times or from different base images, UIDs may differ, causing permission errors when the destination host tries to access the shared state directory.

Check the swtpm UID on each host:

```bash
id swtpm
```

If the UID is not 64130, update it:

```bash
sudo usermod -u 64130 swtpm
sudo chown -R swtpm /var/lib/swtpm-localca
sudo chown -R swtpm /var/lib/libvirt/swtpm
```

Restart `libvirtd` on the host after changing the UID:

```bash
sudo systemctl restart libvirtd
```

#### 4. VM HA Shared Storage Requirements (If VM HA Is Enabled)

If your cluster has [Virtual Machine High Availability (VM HA)](/private-cloud-director/virtualized-clusters/virtualized-cluster/virtual-machine-high-availability-vm-ha.md) enabled and the cluster contains vTPM VMs:

* The VM's ephemeral storage directory (the virtual machine storage path from the Cluster Blueprint) must be on shared storage mounted on all hypervisor hosts.
* The vTPM state directory (`/var/lib/libvirt/swtpm`) must also be on shared storage.
* Both directories must be owned by the `pf9` user and `pf9group` group.

### Diagnose vTPM Live Migration Failures

#### Symptom: Migration Fails with "swtpm" or "TPM" in the Error

If a live migration fails and the Compute Service log or `virsh` output references `swtpm`, `tpm`, or a permissions error, work through the following checks.

**Check 1: Verify swtpm UID consistency**

```bash
# On source host
id swtpm

# On destination host
id swtpm
```

If the UIDs differ, fix them using the steps in the "Consistent swtpm UID" section above.

**Check 2: Verify the shared NFS mount is healthy**

```bash
# On both source and destination hosts
ls -la /var/lib/libvirt/swtpm/
```

If the directory is empty on the destination host while the source has state files, the NFS mount is not working correctly. Check NFS mount status:

```bash
mount | grep swtpm
df -h /var/lib/libvirt/swtpm
```

Re-mount the NFS share if it has become stale:

```bash
sudo umount /var/lib/libvirt/swtpm
sudo mount /var/lib/libvirt/swtpm
```

**Check 3: Verify the flavor property**

Check that the VM's flavor includes `hw:tpm_secret_security = deployment`:

```bash
pcdctl flavor show <FLAVOR_NAME>
```

Look for `hw:tpm_secret_security` in the `properties` section. If it is absent, the flavor needs to be updated and a new VM created with the updated flavor — the property cannot be applied retroactively.

**Check 4: Inspect the libvirt and swtpm logs**

On the destination host, check for errors from `swtpm` after a failed migration attempt:

```bash
sudo journalctl -u swtpm@<VM_UUID> --since "10 minutes ago"
```

Also check the libvirt migration log on the source host:

```bash
sudo grep -i "swtpm\|tpm\|migration" /var/log/libvirt/libvirtd.log | tail -50
```

#### Symptom: VM Migrates Successfully but vTPM Is Unavailable After Migration

If the VM reaches **ACTIVE** on the destination host but the guest OS reports that the TPM device is missing or inaccessible:

1. Verify that the swtpm state file for the VM exists on the shared NFS path:

   ```bash
   ls /var/lib/libvirt/swtpm/<VM_UUID>/
   ```
2. Verify that the `swtpm` user on the destination host owns the state file:

   ```bash
   stat /var/lib/libvirt/swtpm/<VM_UUID>/
   ```

   The owner should be `swtpm` (UID 64130). If not, fix ownership:

   ```bash
   sudo chown -R swtpm:swtpm /var/lib/libvirt/swtpm/<VM_UUID>/
   ```
3. Perform a hard reboot of the VM to allow the guest to re-detect the TPM device:

   ```bash
   pcdctl server reboot --hard <VM_UUID>
   ```

#### Symptom: Maintenance Mode Does Not Migrate vTPM VMs

Maintenance Mode does not support live migration of vTPM-enabled VMs in releases prior to 2026.4. If you are running an earlier release and need to move a vTPM VM off a host for maintenance:

1. Shut down the VM (note: this causes downtime).
2. Perform a cold migration to the desired host.
3. Restart the VM on the destination host.

See [Virtual Machine Migration](/private-cloud-director/virtualized-clusters/virtualmachine/vm-migration.md) for cold migration instructions.

## Related Pages

* [Virtual Machine Migration](/private-cloud-director/virtualized-clusters/virtualmachine/vm-migration.md)
* [Virtual Machine High Availability (VM HA)](/private-cloud-director/virtualized-clusters/virtualized-cluster/virtual-machine-high-availability-vm-ha.md)
* [Maintenance Mode](/private-cloud-director/virtualized-clusters/add-hosts-virtualized-cluster/maintenance-mode.md)
* [VM Flavors](/private-cloud-director/virtualized-clusters/virtualmachine/vm-flavors.md)


---

# 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:

```
GET https://docs.platform9.com/private-cloud-director/virtualized-clusters/virtual-tpm.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
