Deploy VTA appliance

Deploy a VTA appliance using Affinidi Portal to get started.

By the end of this guide, you will have a VTA deployed through Affinidi Portal, with PNM connected to it. Affinidi hosts and operates the VTA in one of two modes, compared in Which mode to choose:

  • Shared: runs on a shared network. Evaluation and development purposes only. Offered on every plan, and the only mode on the free Essential and Community plans.
  • Isolated: runs in an AWS Nitro Enclave, a Trusted Execution Environment (TEE). Hardware-rooted attestation, keys and data. Offered on the Standard and Enterprise plans.

Already have a running VTA? Skip to Create your first context. To run the VTA yourself, see Self-hosted (open source).

Prerequisites

Step 1. Install the PNM CLI

The Personal Network Manager (PNM) CLI is how you connect to and manage your VTA. Both modes use the same version:

cargo install pnm-cli@0.45.0 --locked --registry crates-io

Run pnm help to confirm it installed. Then follow the steps for your mode below, starting at Step 2.

Deploy in Shared mode

You create your own Administrator DID with PNM, give it to Affinidi Portal when you create the VTA, then connect PNM to the VTA with it.

Install PNM CLIYOUR MACHINECreate Admin DIDCreate VTA ConfigurationPNM & AFFINIDI PORTALConnect PNMConfirm AccessCONNECT via PNM CLI

Step 2. Create your Administrator DID

Pick a short local name for this VTA, its VTA slug, such as my-vta, and run:

pnm setup --name my-vta

Copy the Admin DID from the output, which starts:

Pending VTA 'my-vta' created.
  Admin DID: did:key:z6MkjLfAT61ZbMfUTytxjp6KnDh7hy9jE5YkQJNuouJEC4cU

The output then suggests setting admin_did in a setup.toml file. That hint is for self-hosted VTAs: here, you enter the Admin DID in Affinidi Portal in the next step.

PNM keeps the DID’s private key in your OS keyring, so run Step 4 on this same machine.

Step 3. Create the VTA in Shared mode

Open the create form

In Affinidi Portal , go to Verifiable Trust Agent and click Create configuration.

Set the configuration fields

Set these fields, and leave the others at their defaults:

Create Configuration form for a VTA in Affinidi Portal, with Appliance type set to Shared and the Administrator DID field below it

Create a Shared VTA configuration in Affinidi Portal

FieldWhat to enter
Appliance typeShared. On the free plans, it is already selected.
Administrator DIDThe did:key you created with pnm setup.
Mediator DID - optionalOne of this project’s mediators, or + Enter custom mediator DID. To deploy one, see Deploy an Affinidi-hosted mediator.

Create the VTA

Click Create, wait for the status to show Complete, then copy the VTA DID from the configuration page.

Step 4. Connect PNM to the VTA

pnm setup continue my-vta --vta-did <vta-did>

PNM confirms that the VTA accepts your Administrator DID, then replaces it with a fresh long-lived key. The output includes:

Ready: try `pnm health`.

Deploy in Isolated mode

You create a one-time bootstrap claim DID with PNM and give it to Affinidi Portal when you create the VTA. PNM then bootstraps against the VTA: it checks the enclave’s attestation against the measurement you pin, and only if they match does it create your Administrator DID on your machine and hand the VTA’s first administrator role over to it.

Install PNM CLIYOUR MACHINECreate Claim DIDCreate VTA ConfigurationPNM & AFFINIDI PORTALBootstrap PNMConfirm AccessPIN THE ENCLAVE & CONNECT via PNM CLI

Step 2. Create the VTA in Isolated mode

Create a bootstrap claim DID

pnm bootstrap claim-did create

Copy the did:key it prints: you enter it in Affinidi Portal, and pass it to PNM in Step 3. PNM keeps its private key in your OS keyring, so run Step 3 on this same machine.

Open the create form

In Affinidi Portal , go to Verifiable Trust Agent and click Create configuration.

Set the configuration fields

Set these fields, and leave the others at their defaults:

Create Configuration form for a VTA in Affinidi Portal, with Appliance type set to Isolated and the Bootstrap claim DID field below it

Create VTA configuration in Affinidi Portal

FieldWhat to enter
Appliance typeIsolated, the default on the Standard and Enterprise plans.
Bootstrap claim DIDThe did:key you created with pnm bootstrap claim-did create.
Mediator DID - optionalOne of this project’s mediators, or + Enter custom mediator DID. To deploy one, see Deploy an Affinidi-hosted mediator.
Appliance sizeEnhanced, or Advanced on the Enterprise plan. See which sizes your plan includes.

Create the VTA

Click Create, wait for the status to show Complete, then note the VTA DID on the configuration page.

VTA configuration page while deployment is in progress, with Deployment state In Progress and the VTA DID still pending

Wait for the deployment to complete.

Copy the bootstrap command

Copy it from the Verify the enclave before you bootstrap alert on the configuration page. If you dismissed the alert, click Show bootstrap instructions.

VTA configuration page after deployment, showing the VTA DID, PCR0 and PCR8 measurements, and the Verify the enclave before you bootstrap alert with its bootstrap command

Copy the bootstrap command from the alert below the configuration details.

Step 3. Bootstrap PNM against the VTA

Paste the command you copied, and add --claim-did with the claim DID from Step 2 unless the command already includes it. Add --slug my-vta to give the VTA a short name in PNM, its VTA slug. Run it on the machine where you created the claim DID:

pnm bootstrap connect --vta-did did:webvh:QmVE1TQeCtg3aavpTqasqencJpagRr8JKdGRyoZ5Qx6kRp:your-appliance.vta.affinidi.io --expect-pcr0 8f1d3c5a7b9e...c9a1f3b5 --expect-pcr8 4b2e9d6f0a1c...a7c1e0d2 --claim-did did:key:z6Mk... --slug my-vta

Check that the output shows (pinned ✓) next to PCR0, followed by Bootstrap complete.. That confirms the enclave runs the build you pinned. The VTA first enrols your claim DID as a temporary administrator. PNM then creates your Administrator DID on this machine, hands the administrator role over to it, and deletes the claim key: the Admin DID line under Bootstrap complete. shows the new DID. For what the pins check, see PCR0 pinning.

Confirm

Whichever mode you deployed, check the connection:

pnm --vta my-vta health

Replace my-vta with your VTA slug. Every check should show ✓. Client DID is the long-lived did:key PNM now authenticates with, not the DID from Step 2. This sample is from a VTA with a mediator:

  VTA: my-vta
  DID: did:webvh:QmVE1TQeCtg3aavpTqasqencJpagRr8JKdGRyoZ5Qx6kRp:your-appliance.vta.affinidi.io

── VTA ───────────────────────────────────────────
  DID           did:webvh:QmVE1TQeCtg3aavpTqasqencJpagRr8JKdGRyoZ5Qx6kRp:your-appliance.vta.affinidi.io
                ✓ resolves (webvh)
  Mode          DIDComm + REST
  URL           https://your-appliance.vta.affinidi.io (from DID)
  Service       ✓ ok

── Authentication ────────────────────────────────
  Client DID    did:key:z6Mk...
  Token         ✓ valid (expires in 899s)

── Mediator ──────────────────────────────────────
  DID           did:webvh:QmSW59XWpXN4xNX5ZJvkYmaJBpBH7d1WN1fR6ZZG8xtjGE:your-appliance.mediator.affinidi.io
                ✓ resolves (webvh)
                ✓ pong (14ms)

── VTA DIDComm ───────────────────────────────────
  Trust-ping    ✓ pong (25ms)

The output above is abridged. Between Authentication and Mediator, pnm health also prints a Deployment section with these rows:

  • Sealed: whether the VTA is sealed.
  • Storage: whether the VTA’s storage is encrypted at rest.
  • TSP: whether TSP is enabled.
  • TEE: the TEE type and whether it is detected, on a VTA that runs in a TEE.
  • Version: the VTA version, shown to administrators only.
  • Restored: whether the VTA’s state was restored from a backup, shown to administrators only.

If any check shows ✗, see Troubleshooting below.

PNM treats the first VTA you register on a machine as its default, and --vta picks a specific VTA for a single command. To make this VTA the default for every later command, run pnm vta use my-vta. pnm vta list shows every VTA registered on this machine.

Troubleshooting

SymptomLikely causeFix
pnm setup continue fails with no pending VTA named '<name>'The name differs from the one you gave pnm setup --name in Step 2, or the command is running on a different machine.Run pnm vta list to see the VTAs on this machine, then run the command on the machine where you ran Step 2, with the same name.
pnm setup continue prints <vta-did> does not accept <admin-did> yetThe Administrator DID you entered when you created the VTA is not the one PNM printed in Step 2, or --vta-did names a different VTA.Compare your --vta-did value with the VTA DID on the configuration page. If either DID was wrong, delete the configuration in Affinidi Portal and start again from Step 2 with a new name: the Administrator DID is fixed after creation, and PNM has already saved this VTA.
pnm setup continue prints Could not reach <vta-did> to check whether it accepts <admin-did>The VTA has not finished deploying, or its DID cannot be resolved from this machine yet.Wait until the configuration shows Complete, then run pnm --vta <name> health. PNM completes the connection on its first successful call.
Could not resolve bootstrap endpoint for VTA DID ...The VTA’s DID log has not published yet, or this machine cannot reach it. Bootstrap always resolves locally, so a reachable resolver sidecar does not satisfy it: PNM_RESOLVER_URL and [resolver_url] are deliberately ignored for this call.Retry once the DID log is published and reachable from this machine. Otherwise, run the copied command with --vta-url <vta-url> in place of --vta-did <vta-did>, keeping the PCR values, --claim-did, and --slug. The URL form still pins the enclave through PCR0, but not which VTA answers.
pnm bootstrap connect fails with PCR0 mismatch: enclave reported …, operator expected …The pinned PCR0 does not match the enclave’s live attestation, so the running software is not the build you expected.Treat this VTA as untrusted. Its one-time bootstrap is already used, so delete the configuration in Affinidi Portal, remove the claim key with pnm bootstrap claim-did discard --claim-did <claim-did>, deploy a new one with a new claim DID, and confirm the PCR0 on its configuration page before you bootstrap it.
pnm bootstrap connect fails with no bootstrap claim key stored for '<vta-slug>' in this machine's OS keyringThe command has no --claim-did, so PNM looked for a claim key stored under the slug.Add --claim-did <claim-did>, the did:key you entered in Affinidi Portal, and run the command again.
pnm bootstrap connect fails with no bootstrap claim key for <claim-did> in this machine's OS keyringThe command is running on a different machine from the one where you created the claim DID, --claim-did names a different DID, or bootstrap already succeeded and PNM deleted the claim key.Run the command on the machine where you created the claim DID, with the did:key you entered in Affinidi Portal. If bootstrap already succeeded, run pnm --vta <vta-slug> health to confirm the connection instead.
pnm bootstrap connect fails with bootstrap request failed (410 Gone): {"error":"gone: TEE first-boot carve-out has already been used"}The VTA’s one-time first-boot claim was already used, for example by an earlier run that failed its PCR0 check.Treat this VTA as untrusted. Delete the configuration in Affinidi Portal, remove the claim key with pnm bootstrap claim-did discard --claim-did <claim-did>, and start again from Step 2 with a new claim DID.
pnm bootstrap connect fails with the VTA enrolled the claim DID, but handing its entry over to the long-term DID <did> did not completeThe run stopped after the VTA accepted your claim, before PNM finished handing the administrator role to your new Administrator DID.Run the same pnm bootstrap connect command again on the same machine within 24 hours of the first run. PNM resumes the hand-over.
pnm bootstrap connect prints The VTA refused this claim before enrolling anything. and fails with 403 ForbiddenThe Bootstrap claim DID the VTA was created with is not the DID in --claim-did, or --vta-did names a different VTA.Compare --claim-did with the Bootstrap claim DID you entered in Affinidi Portal, and --vta-did with the VTA DID on the configuration page. If both match and the VTA still refuses, treat it as untrusted: delete the configuration and start again from Step 2 with a new claim DID.
pnm bootstrap connect fails with bootstrap request version 1 is not acceptedThe installed PNM is older than the version this guide pins, and speaks an earlier first-boot claim format. The one-time bootstrap is not spent.Install the pinned version from Step 1, then run the command again.
Create configuration is disabled with Configuration limit reached for this project. Delete a configuration or contact support.The project already has a VTA configuration. Each project holds one.Use the existing configuration, or delete it and create a new one.
pnm health shows ✗ trust-ping failed or ✗ trust-ping timed out on Trust-pingVTA DIDComm layer has stalledRestart the VTA with pnm vta restart, then wait for the confirmation VTA is back. Re-run pnm health to confirm Trust-ping shows ✓ pong.

Next steps

  Create your first context and signing key

  VTA overview

  Glossary: the terms used across these pages and in pnm output.