Back up and restore VTA state

How to export and import a full VTA backup using pnm backup export and pnm backup import, including encryption details, what is included, and compatibility rules.

By the end of this guide, you have a password-encrypted backup of your VTA’s operator state, and you know how to restore it.

A VTA backup captures the keys, identities, contexts, and access control configuration of a running VTA at a point in time, as a single encrypted .vtabak file. Restoring it replaces all current data in the target VTA. For what the keys inside it are derived from, and why the master seed matters to recovery, see Keys and contexts.

Rebuilding a lost VTA by hand means re-minting every key, re-provisioning every application, and reconstructing the access control list (ACL) from memory, with the original DIDs gone. A backup is what turns that into a restore. Note that a few keyspaces are deliberately excluded, so a restore is not a complete rebuild on its own; see Known gaps.

Use this guide when:

  • You are putting a VTA into production and need a recovery position before you depend on it.
  • You are migrating a VTA to a new host.
  • You want to clone a VTA environment, for example to seed staging from development.
  • You are about to make a change you may need to roll back.
Running VTAkeys, ACL, contexts, WebVH DIDsExportpnm backup exportARGON2ID + AES-256-GCM.vtabak filepassword-encryptedImportpnm backup importREPLACES ALL CURRENT DATA

Exporting a backup

pnm backup export

You are prompted to enter and confirm a password (minimum 15 characters). The backup is saved to a .vtabak file in the current directory:

vta-backup-<did-tail>-<timestamp>.vtabak

<did-tail> is the final segment of the VTA’s DID, not the full DID value.

Including audit logs

Audit logs are excluded from the default export because they can be large. Add --include-audit to include them:

pnm backup export --include-audit

Specifying the output path

pnm backup export --output /path/to/my-backup.vtabak

What is backed up

IncludedNot included
Keys (derived and imported)Sessions
ACL entriesDID templates (known gap: upload separately after restore)
Contexts (BIP-32 key hierarchy)Vault secrets (known gap: re-import after restore)
WebVH DID records and logsIssued holder credentials (known gap: re-issue after restore)
Imported secret material (KEK-wrapped)Cache
Consent records and approversService state (protocol management, drain set)
Agent memory and application statePasskey enrolment state
Holder identity (persona)Bootstrap nonces
Operator security policy
Messaging room groups and invitations
Audit logs (with --include-audit)

Known gaps

DID templates, vault secrets, and issued holder credentials are durable operator or holder data but are currently excluded from the backup. After restoring:

  1. Re-upload any custom DID templates using pnm did-templates create.
  2. Re-store any vault entries your apps depend on using pnm vault upsert.
  3. Re-issue any holder credentials your VTA had previously issued.

Vault secrets are service-consumer secrets stored in the pnm vault store, a separate keyspace that is currently excluded.

Encryption details

Backups are encrypted with Argon2id + AES-256-GCM:

ParameterValue
KDFArgon2id
Memory cost64 MiB (OWASP-recommended profile)
Iterations3
Parallelism4 threads
EncryptionAES-256-GCM
Salt32 bytes, random per export

The KDF parameters are stored in the backup envelope. On import, the VTA validates that the parameters fall within accepted bounds. Extreme values are rejected to prevent memory exhaustion, which matters most for Nitro Enclave deployments.

Inspecting a backup before importing

Use --preview to see what a backup contains without applying any changes:

pnm backup import my-backup.vtabak --preview

Output:

Backup file: my-backup.vtabak
  Source DID:  did:webvh:...
  Created:     2026-06-18 10:00:00 UTC
  Version:     1.2.3
  Audit:       false

  Keys:        12
  ACL entries: 5
  Contexts:    3
  Audit logs:  0

Preview only — no changes applied.

Importing a backup

pnm backup import my-backup.vtabak

The import flow:

  1. Metadata display: shows source DID, creation time, version, and whether audit logs are included.
  2. Password prompt: enter the backup password (not confirmed on import).
  3. Preview: shows counts of keys, ACL entries, contexts, and audit logs to be restored.
  4. Confirmation: you must type yes exactly to proceed.
  5. Apply: all current data is replaced with the backup contents.

Compatibility rules

ConditionResult
Restoring to a fresh (unconfigured) VTAAlways accepted
Restoring to a VTA with the same DIDAccepted
Restoring to a VTA with a different DIDRejected with 400: source DID does not match the running VTA’s DID

The DID mismatch check prevents accidentally restoring the wrong backup to a configured VTA.

To restore to a different VTA (e.g. migration), you must factory-reset or reinstall the target VTA first, then import.

After import

  • The VTA restarts to apply the new key hierarchy.
  • If the VTA DID has changed (cross-VTA migration), you must re-authenticate with credentials from the restored backup.
  • Re-upload any DID templates, re-import any vault secrets, and re-issue any holder credentials (see Known gaps).
  • Inform any integrations of the new VTA DID if it has changed.

Confirm

Test 1: the exported file exists and previews cleanly

Run this against the file pnm backup export wrote, before you rely on it for recovery. A backup you have never read back is not yet a backup.

pnm backup import vta-backup-<did-tail>-<timestamp>.vtabak --preview
Backup file: vta-backup-<did-tail>-<timestamp>.vtabak
  Source DID:  did:webvh:...
  Created:     2026-06-18 10:00:00 UTC
  Version:     1.2.3
  Audit:       false

  Keys:        12
  ACL entries: 5
  Contexts:    3
  Audit logs:  0

Preview only — no changes applied.

Test 2: the counts match the VTA you exported from

Compare the preview counts against the live VTA:

pnm keys list
pnm acl list
pnm contexts list

The Keys, ACL entries, and Contexts totals in the preview match what these commands return. A lower count means the export ran before the most recent changes.

Test 3: the password is the one you recorded

The preview above reads only the envelope. Confirm the password decrypts the payload by running the import against a non-production VTA, or accept that an untested password is a recovery risk: there is no password recovery path for VTA backups.

Troubleshooting

SymptomLikely causeFix
Import rejected with “source DID does not match”The target VTA has a different DID from the backup source.Factory-reset or reinstall the target VTA first, then retry the import. See Compatibility rules.
Password rejected on importWrong password entered, or the backup was exported on a different machine or version.Re-export with the correct password. There is no password recovery path for VTA backups.
Vault secrets missing after restoreVault secrets are excluded from the standard backup format.Re-import vault secrets using pnm vault upsert. See Known gaps.
DID templates missing after restoreDID templates are excluded from the standard backup format.Re-upload DID templates using pnm did-templates create. See Known gaps.
Service cannot authenticate after restoreService credentials were minted after the backup was taken.Re-provision affected services using pnm bootstrap.

Next steps

  Retrieve credentials from the VTA vault at runtime: re-import the vault secrets a restore leaves behind (see Known gaps above).

  Sign application payloads without exposing your keys: provision app credentials, which are also captured in a VTA backup.

  Grant and revoke access: grant, scope, and revoke access roles for DIDs restored from a backup.