AWS ECS Deployment Process
For AI agents: visit https://vault.docs.blockdaemon.com/llms.txt for an index of all pages formatted in Markdown and endpoints in OpenAPI.
The AWS deployment of the self-installed Institutional Vault uses separate AWS KMS policies and Secrets Manager instances for each Policy Node quorum member. Policy Nodes run inside AWS Nitro enclaves during execution so sensitive in-memory data stays isolated. No single party should have access to multiple master key shards.
Roles and Responsibilities
Assign team members before you begin. Multi-account installs split Policy Node KMS keys across accounts.
| Roles | Responsibilities |
|---|---|
| Infrastructure admin | Manages wallet infrastructure in the wallet AWS account |
| Policy Node admin | Manages one Policy Node partition and its KMS key (one admin per Policy Node account in the recommended layout) |
In the recommended three-account layout:
| Actor | Roles | Responsibilities |
|---|---|---|
| Actor A | Infrastructure and Policy Node 0 admin | Wallet infrastructure and Policy Node 0 KMS key |
| Actor B | Policy Node 1 admin | Policy Node 1 KMS key |
| Actor C | Policy Node 2 admin | Policy Node 2 KMS key |
Summary of Steps Per Role
| Roles | Steps performed |
|---|---|
| Infrastructure admin | 1–11, 13–17 |
| Policy Node admins | 1–7, 9 (baseline only in their account), 10 (their Policy Node long-lived stack), 12 (their partition secrets) |
Prerequisites
- AWS experience and comfort with shell scripts and
make. - A local install host with Docker, make, AWS CLI, and cosign (recommended for image verification).
- Separate AWS credentials per account. Do not use the AWS root user. Follow AWS root user best practices.
- An OIDC identity provider for the wallet and Approver App (Auth0, Okta, Azure Entra ID, or equivalent). See Configuring Okta for Okta-specific steps.
- A DNS hosted zone for the wallet (for example
wallet.<companydomain.com>). The installer creates records in this zone. OIDC redirect URIs must match the deployed hostnames. - AWS account IDs authorized to pull from the Blockdaemon delivery ECR (Blockdaemon configures this from your intake form).
- Emergency Recovery Secret (ERS) public key. See Step 2.
- Blockdaemon delivery artifacts: wallet release tag, deployer version, Policy Node / enclave tag (
MPA_IMAGE_TAG), and API credentials. Blockdaemon sends these through a secure channel if they were not collected on your intake form. - Blockdaemon API key with Native API, Blocks, Events, Transactions, Fee Estimation, Balances for Wallet and UTXOs, and Historical Token Price. Confirm event streaming is enabled for your organization.
- Optional integrations:
- Chainalysis ( https://www.chainalysis.com/) if you use transaction risk screening.
Recommended Wallet Architecture
Review the architecture before you deploy.
Makefile Variables
Set these as environment variables (recommended) or edit defaults at the top of the Makefile Blockdaemon delivers in your installer bundle.
| Variable | Purpose | Example |
|---|---|---|
DEPLOYER_VERSION |
Wallet deployer container tag | v3.4.0 |
MPA_IMAGE_TAG |
Policy Node / Nitro EIF S3 prefix (enclave/<tag>/) |
v8.26.5 |
CUSTOMER_SHARED_SEGMENT |
Wallet release tag for the shared S3 bundle | v3.4.0 |
NAMESPACE |
Deployment namespace (resource naming) | acme-custody |
ENV_PREFIX |
Environment name and DNS prefix | testnet |
AWS_REGION |
Target AWS Region | us-east-1 |
BACKEND_API_PATH |
Wallet API base URL (frontend and bootstrap) | https://api.testnet.wallet.example.com |
Run make help from the bundle directory for the full list.
Example exports:
Shell
export DEPLOYER_VERSION=<deployer-version>
export MPA_IMAGE_TAG=<policy-node-enclave-tag>
export CUSTOMER_SHARED_SEGMENT=<wallet-release-tag>
export NAMESPACE=<namespace>
export ENV_PREFIX=<environment-name>
export AWS_REGION=<aws-region>
export BACKEND_API_PATH=https://api.<environment-name>.wallet.<company-domain>
Step 1: Create Local Installation Environment
All infrastructure and Policy Node admins configure a local host with:
Configure AWS credentials for the account you will deploy into. For AWS SSO profiles, set AWS_PROFILE and use LOCAL_AWS_PROFILE_MODE=true if your team documents that convention.
Step 2: Generate Emergency Recovery Secret
Generate the ERS key pair before install. Follow Create ERS Key for key generation, ceremony guidance, and how to supply ers_public_key in customer-secrets.yml during Step 12.
📘
Note
Skip this step if you already completed your ERS key ceremony.
Step 3: Receive Blockdaemon Delivery Artifacts
Blockdaemon grants ECR and S3 access and sends:
- Target wallet release tag (
CUSTOMER_SHARED_SEGMENT) - Deployer version (
DEPLOYER_VERSION) - Policy Node / enclave tag (
MPA_IMAGE_TAG) when it differs from the wallet tag - API credentials and any delivery-specific notes
📘
Note
Skip this step if you already have current delivery values from a prior engagement.
Step 4: Authenticate to the Institutional Vault Registry and Validate Images
All admins authenticate to the Blockdaemon ECR registry:
Shell
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin \
638663786504.dkr.ecr.us-east-1.amazonaws.com
Optionally verify the deployer image with cosign (set DEPLOYER_VERSION from Step 3):
Shell
export DEPLOYER_VERSION=<deployer-version>
BLOCKDAEMON_SIGNING_AUTHORITY="-----BEGIN PUBLIC KEY-----\
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEfJLNcMpG3m8EOswCU7cqzWBsHSfY\
+rt4HRvbPWAqadeYxIhhBWXjWDiRk4SAa2XXhZVi7IEO7TMaJcuFyHvoBQ==\
-----END PUBLIC KEY-----" \
cosign verify --key env://BLOCKDAEMON_SIGNING_AUTHORITY \
638663786504.dkr.ecr.us-east-1.amazonaws.com/blockdaemon/wallet-deployer/aws:${DEPLOYER_VERSION}
Step 5: Download the Installer Bundle
All admins download the shared installer bundle from S3 into a dedicated working directory. The bundle includes the Makefile, customer-config.yml template, tenant-setup.json, helper scripts, and cold-wallet templates.
The bundle path is s3://638663786504-prod-mpa-deployment-customer-artifacts/customer/shared/<wallet-release-tag>/.
Copy the Makefile from S3, then sync the rest of the bundle with make:
Shell
export CUSTOMER_SHARED_SEGMENT=<wallet-release-tag>
aws s3 cp s3://638663786504-prod-mpa-deployment-customer-artifacts/customer/shared/${CUSTOMER_SHARED_SEGMENT}/Makefile .
make pull-customer-assets
📘
Note
By default,
pull-customer-assetsdoes not overwrite a localMakefile. To refresh the Makefile from S3, runPULL_SYNC_MAKEFILE=1 make pull-customer-assetsafter backing up local edits.
Step 6: Configure Makefile Variables
All admins set the variables in Makefile Variables for the environment they deploy. ENV_PREFIX is the environment name (Blockdaemon recommends testnet and mainnet) and DNS prefix. NAMESPACE must match the value you will use in customer-config.yml.
Step 7: Generate Deployment Configuration
All admins complete local configuration before infrastructure deploy.
- Pull the deployer image:
Shell
make pull-deployer
- Edit
customer-config.ymlwith your namespace, AWS accounts, hosted zones, admin users, optional Canton settings, and resource tags. See customer-config.yml Reference. - Generate deployment assets:
Shell
make generate-customer-assets
tenant-setup.json
Edit tenant-setup.json in the installer bundle before bootstrap ( Step 16). This file is the request body for POST /api/tenants/default/setup. It seeds initial Vault users, the owner group, master keys, and registered chains. It does not define transaction restrictions or admin policies.
| Field | Purpose |
|---|---|
Users |
Initial Vault users (ID is email, Name is display name) |
Group |
Owner group name (for example owner) |
MasterKeysAndAccounts |
Hot master keys and account names |
Assets.CAIP2s |
CAIP-2 chain identifiers to register at bootstrap |
Configure policies after bootstrap in the Vault UI or through supported policy APIs.
📘
Note
After the first install, you may edit
bd-wallet.ymldirectly for some changes. Regenerate fromcustomer-config.ymlwhen you change namespace, accounts, or hosted zones.
Step 8: Optional Cold Wallet Bundle
Infrastructure admin only, when cold wallet is in scope:
Shell
make generate-cold-wallet-bundle
This produces cold-wallet.tar.gz for air-gapped Policy Node operations. Skip when you deploy hot quorum only.
Step 9: Deploy Stage 1 (Baseline and Long-Lived Infrastructure)
Confirm ENV_PREFIX and NAMESPACE match bd-wallet.yml, then deploy long-lived infrastructure.
Infrastructure admin (wallet account)
Either run the stage wrapper:
Shell
make deploy-stage-1
Or run the same steps individually:
Shell
make deploy-baseline
make deploy-service-images
make generate-conf-files
make fetch-enclave-artifacts
make deploy-wallet-long-lived
make deploy-all-policy-nodes-long-lived
deploy-stage-1 creates baseline CDK resources, populates customer ECR with service images, generates component config files, downloads Nitro enclave.eif / pcr.json for MPA_IMAGE_TAG, and deploys wallet and Policy Node long-lived stacks in the wallet account.
📘
Note
Do not delete long-lived stack resources unless you are decommissioning the environment.
Policy Node admins (separate accounts)
In each Policy Node account:
Shell
make deploy-baseline
make fetch-enclave-artifacts
make deploy-policy-node0-long-lived # or node1 / node2 for that admin
Policy Node admins do not run deploy-service-images or deploy-wallet-long-lived.
Step 10: Deploy Policy Node KMS Keys (Multi-Account)
When Policy Node KMS keys live in accounts other than the wallet account, each Policy Node admin deploys only their partition (if not already done in Step 9):
Shell
make deploy-policy-node0-long-lived
make deploy-policy-node1-long-lived
make deploy-policy-node2-long-lived
Run only the target matching the account you control.
Step 11: Verify Deployer Image
If any admin skipped Step 7.1, pull the deployer before secrets or Stage 2:
Shell
make pull-deployer
Step 12: Generate and Populate Secrets
The Encryptor Master Password encrypts each Policy Node database that holds a master key share. One password exists per Policy Node partition. The install tooling encrypts and stores values in AWS Secrets Manager.
- Infrastructure admin generates the secrets template:
Shell
make generate-secret-file
- Infrastructure admin edits
customer-secrets.ymlwith:
ubiquity_org_usernameandubiquity_auth_token(Blockdaemon Workspace and API key)- OIDC values under the
auth0block (AUDIENCE,ISSUER,CLIENT_ID_SPA,CLIENT_ID_NATIVE) for Auth0-shaped configs; use the keys your IdP mapping expects ers_public_key(see Create ERS Key)broker-root-caandbroker-root-ca-key(NATS mTLS root; use YAML|literal blocks with PEM newlines)- Optional:
chainalysis-user,chainalysis-token,canton-client-id,canton-client-secret, custom chain RPC URLs
Do not commit customer-secrets.yml.
- Infrastructure admin:
Shell
make populate-secrets-wallet
- Policy Node 0 admin:
Shell
make populate-secrets-policy-node0
- Policy Node 1 admin:
Shell
make populate-secrets-policy-node1
- Policy Node 2 admin:
Shell
make populate-secrets-policy-node2
🚧
Warning
Re-running
populate-secrets-walleton a live environment overwrites most wallet-partition secrets in AWS Secrets Manager. It does not replace Policy Node Encryptor Master Passwords (those belong to the policy-node populate targets). Avoid blind re-runs:db-infoandwebhook-tokenvalues are regenerated and can break a running wallet. Re-run populate only when you intend to rotate the secrets you changed incustomer-secrets.yml.
Step 13: Deploy Stage 2 (Wallet Runtime and Policy Nodes)
After secrets are populated, infrastructure admin deploys runtime services on ECS and Nitro hosts.
Either:
Shell
make deploy-stage-2
Or individually:
Shell
make generate-fe-env
make deploy-wallet
make deploy-nitro-nodes
make start-wallet
**generate-fe-env**requiresBACKEND_API_PATH. It buildsenv-config.jsand packagesfrontend.zip.**deploy-wallet**deploys ECS task definitions with wallet count 0 (services defined, wallet not started).**deploy-nitro-nodes** deploys Nitro EC2 instances for all three Policy Nodes.**start-wallet** setsWalletServiceCount=1and starts the wallet service.
🚧
Warning
After go-live, do not change the public API URL without a planned migration. Event streaming and integrations depend on a stable endpoint.
If CDK fails pulling the AWS SAM CLI image from public.ecr.aws, run make ecr-public-login on the host and retry.
Step 14: Apply Configuration Changes After Install
When you change bd-wallet.yml (or regenerate it) on an already running wallet:
Shell
make generate-conf-files
make deploy-wallet
Add make deploy-nitro-nodes when Policy Node configuration changed. Add make generate-fe-env when BACKEND_API_PATH changed.
Use make start-wallet only if the wallet service is still at desired count 0. Do not use start-wallet as a substitute for deploy-wallet when applying config.
For secret value changes, edit customer-secrets.yml and run the appropriate populate-secrets-* target for the partition you changed, then redeploy affected services.
Step 15: Optional RDS Snapshot Before Upgrades
Before major upgrades:
Shell
export RDS_DB_INSTANCE_IDENTIFIER=<your-cluster-id>
make backup-rds-snapshot
See AWS Wallet Upgrade.
Step 16: Populate Initial Tenant State
After the wallet is healthy, infrastructure admin seeds users, groups, master keys, and registered chains from tenant-setup.json (see Step 7).
The wallet creates a bootstrap Admin API key automatically on first start ( Step 13) and stores it in AWS Secrets Manager. Retrieve it before bootstrap (replace NAMESPACE and ENV_PREFIX with your Makefile values, or substitute your namespace and environment name):
Shell
export WALLET_API_KEY=$(aws secretsmanager get-secret-value \
--region "${AWS_REGION}" \
--secret-id "bd-wallet.${NAMESPACE}.${ENV_PREFIX}.bootstrap-key" \
--query SecretString --output text)
export BACKEND_API_PATH=https://api.<environment-name>.wallet.<company-domain>
make bootstrap-policies-and-users
This calls POST /api/tenants/default/setup as the bootstrap@blockdaemon-wallet.com system user. It is one-shot: a second successful run returns an "already populated" response. Configure transaction restrictions and admin policies afterward in the Vault UI or through supported policy APIs.
📘
Note
Override the JSON path with
TENANT_SETUP_JSON=/path/to/file.jsonwhen needed.
Step 17: Backup the Wallet Master Private Key
After first login and Approver App pairing, approve master key backup in the Approver App. Store backup material separately from the live system.
See Back Up Master Key.
Updated about 1 month ago.