Cloud-agnostic Install Guide
Institutional Vault Installation Guide
This guide describes how to install and configure the Institutional Vault in a cloud-agnostic way. It covers the installation flow, components and how they connect, broker configuration, secrets management, and the configuration options for the wallet service and policy nodes.
Prerequisites
- A Kubernetes cluster (any supported distribution).
- Container images for: wallet service, policy-node (×3), NATS; optionally cold-wallet and Postgres if not using an existing database.
- Storage: PersistentVolumes (or equivalent) for Postgres and, if used, cold-wallet nodes.
- Secrets: An external secrets manager is required for production.
- Confidential Computing is required for Policy Nodes in production to protect MPC key share material while in-use.
Deployment Components
- Namespace and RBAC – Create the target namespace and any service accounts/roles used by the components.
- Secrets and ConfigMaps – Create Kubernetes Secrets (or provision secrets via your chosen secret store) and ConfigMaps. Do not store secrets in ConfigMaps.
- Database (PostgreSQL) – Deploy PostgreSQL 14 or 15 and run init scripts to create databases:
wallet,orchestrator,approval,mpa0,mpa1,mpa2. Ensure TLS is configured for production. - Message broker (NATS) – Deploy the broker and configure accounts/users for: policy-node0, policy-node1, policy-node2, facade. The wallet service connects as
facade; each policy node has its own user (e.g.node0,node1,node2). - Policy nodes – Deploy the three policy nodes. They require broker and database connectivity.
- Wallet service – Deploy the wallet after the broker and (if using the same cluster) policy nodes and database are ready. The wallet connects to the broker as
facadeand to the MPA routes (route0, route1, route2) via the broker. WalletConnect runs in-process and does not require a separate NATS connection. - Cold wallet – Optional. Requires Redis and persistent storage for two cold-wallet nodes and a proxy.
- Ingress / Gateway – Expose the wallet API via your chosen gateway or ingress.
Component Wiring
High-level architecture:
Data Layer
Wallet Namespace
Clients
HTTPS 443
HTTPS 443
HTTPS 443
HTTP 80
TCP 8080
TCP 5432
NATS TCP 4222
NATS TCP 4222
NATS TCP 4222
NATS TCP 4222
NATS TCP 4222
TCP 5432
TCP 5432
TCP 5432
Wallet UI
Client
Wallet API
Client
Approver
Reverse Proxy
Wallet Frontend
Wallet Service
EVM Tracker
NATS Message Broker
Policy Node 0
Policy Node 1
Policy Node 2
wallet,
approval,
orchestrator
mpa0
mpa1
mpa2
- Wallet service – API and business logic, including integrated WalletConnect support. Talks to the broker as
facade, to Postgres (wallet, approval, orchestrator DBs), and to policy nodes only indirectly via the broker (route0, route1, route2). Ports: 8080 (API/health), 9876 (approval), 8085 (webhook), 9090 (metrics). - Policy nodes – Three MPC participants. They connect to the broker and the database only. They do not call the wallet; the wallet sends intents over the broker and receives responses over the broker. When
HealthCheckPortis set, exposeGET /live(liveness; HTTP 200 while the process is running) andGET /ready(readiness; HTTP 200 only after NATS connect and subscribe, 503 before then). OptionalGET /metricson the same port. - NATS – Message broker. Client port (e.g. 4222), monitoring (e.g. 8222), optional WebSocket (e.g. 8443). Users: node0, node1, node2, facade.
- PostgreSQL – Version 14 or 15 recommended. The wallet uses multiple DBs (wallet, approval, orchestrator); policy nodes use a DB per tenant (e.g.
local) or shared DB with schema separation. - Cold wallet – Optional; uses Redis and persistent volumes; integrates with the wallet for cold-storage flows.
- Gateway – Optional; routes external traffic (e.g. Gateway API HTTPRoute or Ingress) to the wallet.
Secrets Management
Wallet and policy-node services load local config files at startup; any secret values referenced in those files must be interpolated by fetching them from external secret managers at runtime (not stored in plaintext in config files or ConfigMaps). Both wallet and policy nodes support direct SDK-based secret retrieval (for example via AWS Secrets Manager or Azure Key Vault client integrations) so secrets are resolved from the manager instead of being hardcoded in deployment manifests.
Secret interpolation syntax
The config templates in this stack use Go-template style interpolation ({{ ... }}).
| Interpolation type | Syntax | Behavior |
|---|---|---|
| Environment variable (for development only) | {{ envVAR_NAME }} (example: {{ envBD_API_KEY }}) |
Reads VAR_NAME from process environment; errors if missing. |
| AWS Secrets Manager lookup | {{ awsSecretsecret-name }} or {{ awsSecretsecret-name#FIELD }} |
Reads secret by name; when #FIELD is provided, treats the secret value as JSON and returns that key. |
| Azure Key Vault lookup | {{ azureSecretsecret-name }} or {{ azureSecretsecret-name#FIELD }} |
Same pattern as AWS; optional #FIELD extracts a JSON field. |
| Attested enclave secret lookup (MPA policy-node) | {{ enclaveSecretsecret-name }} |
Retrieves the secret and decrypts through enclave/attestation flow before injecting into config. |
In this repository:
- The policy-node config expansion supports
env,awsSecret,azureSecret, andenclaveSecret. - The wallet service config expansion supports
env,azureSecretandawsSecret.
Security tiers (reference)
- Tier 0 (dev/example) – Kubernetes Secrets with local config interpolation (including env var expansion); values provided by overlay or manual creation. Not safe against cluster-admin access.
- Tier 1 (production) – Applications must fetch secrets directly from an external secret manager (for example AWS Secrets Manager, Azure Key Vault, or Vault) at runtime using provider SDKs or approved secret-client libraries. Do not rely on mounted Kubernetes Secrets for sensitive material, because cluster-admin users can observe Kubernetes Secrets once they are materialized in the cluster.
- Tier 2 (high assurance) – Secret release gated by attestation. Policy nodes may run in TEEs and pull secrets after attestation.
Secret categories and usage
| Service | Secret Name | Purpose |
|---|---|---|
wallet |
WALLET_DB_PASSWORD |
Wallet database password for main wallet DB connection ( optional when use_iam: true with AWS IAM DB authentication). |
wallet |
APPROVAL_DB_PASSWORD |
Approval service database password ( optional when use_iam: true with AWS IAM DB authentication). |
wallet |
ORCHESTRATOR_DB_PASSWORD |
Orchestrator/MPA database password used by wallet adapter ( optional when use_iam: true with AWS IAM DB authentication). |
wallet |
FACADE_BROKER_PASSWORD |
NATS password for wallet facade user. |
wallet |
BD_API_KEY |
API key used by Blockdaemon service integrations (auth_token/utxos/ubiquity/staking APIs). |
wallet |
WEBHOOK_TOKEN |
Webhook shared secret/token for callback verification. |
wallet |
BOOTSTRAP_KEY |
Bootstrap key material used for local/bootstrap API auth flow. |
wallet |
CHAINALYSIS_TOKEN |
Chainalysis credential ( optional, only if compliance integration is enabled). |
wallet |
BOSS_API_KEY |
Staking service token ( optional, only if staking integration is enabled). |
wallet |
WEBHOOK_SECRET |
Alternate webhook secret key name ( optional, only in deployments using this key instead of WEBHOOK_TOKEN). |
wallet |
CANTON_DEVNET_CLIENT_SECRET |
Canton OIDC client secret ( optional, only if Canton integration is enabled). |
policy-node |
DB_PASSWORD |
Policy-node Postgres password for default and tenant DB DSNs. |
policy-node |
BROKER_PASSWORD |
NATS password for per-node broker users (node0/node1/node2). |
policy-node |
ENCRYPTOR_MASTER_PASSWORD |
Master password used to derive encryption keys for sensitive policy-node data. |
policy-node |
BROKER_INTERMEDIATE_CA |
CA bundle used to validate broker certificate ( optional, required when broker TLS validation is enabled). |
Wallet Service Configuration
The wallet is configured via a single YAML file (e.g. mounted from a ConfigMap). Sensitive values must come from Secrets, not from this file.
The following YAML is an annotated example showing the available configuration keys and typical option values.
wallet.yaml
# CORS allow-origin. Typical: "*" for dev, or exact frontend origin in production.
access_control_allow_origin: "http://localhost:3000"
# Bootstrap key source.
# Supported `type` values in wallet config:
# - local (read key from file path)
# - secretsmanager (AWS Secrets Manager)
# - keyvault (Azure Key Vault)
bootstrap_key:
type: "local"
key: "/secrets/api-key"
# Compliance provider credentials. Keep secret values in external secret manager.
compliance:
chainalysis:
password: "{{ env `CHAINALYSIS_TOKEN` }}"
# Provider username/account identifier.
username: new_user_02
# Cold wallet signer set.
# Options: comma-separated signer indexes, e.g. "0,1", "0,2", "1,2".
cold_wallet:
signer_set: "0,1"
# Wallet DB DSN.
# Options:
# - sslmode=disable (local dev)
# - sslmode=require (production)
database:
url: postgresql://postgres:{{ env `WALLET_DB_PASSWORD` }}@host.docker.internal:5432/wallet?sslmode=disable
# Environment label / tenant namespace.
# Typical: local, dev, staging, production, or per-tenant subdomain.
environment: "local"
# Feature flags.
# Toggle true/false based on your deployment capabilities.
features:
block_explorer: true
cold_storage: true
dev_tools: true
stake_eth: true
txn_risk_assessment: true
# Gateway and webhook behavior.
gateway:
# Webhook listener port.
webhook_port: 8085
# Shared secret/token for webhook verification.
webhook_secret: "{{ env `WEBHOOK_SECRET`}}"
# Public host URL used in callback generation.
webhook_url: "http://localhost"
# Internal buffering/cache knobs.
buffer_flush_interval: 1s
cache_flush_interval: 10m
cache_expiry: 12h
# Logging verbosity.
# Typical: 0 (quiet) to higher values (more verbose), based on runtime implementation.
log_level: 1
# Deployment mode label.
# Typical values: on-prem or cloud-managed flavors depending on environment.
mode: "on-prem"
# MPA/orchestrator integration.
mpa_adapter_config:
# Blockdaemon auth token.
auth_token: "{{ env `BD_API_KEY` }}"
# Approval DB DSN.
approval_db_url: "postgresql://postgres:{{ env `APPROVAL_DB_PASSWORD` }}@host.docker.internal:5432/approval?sslmode=disable"
approval_service:
# Mobile approval bundle/application id.
bundle_id: "com.blockdaemon.Advanced-MPC-Approver"
# Minimum supported approver app version.
min_version: "v1.0.8"
# Public host and port for approval callbacks.
host_url: "http://localhost"
port: "9876"
# Optional: SMTP relay for email notifications when an operation requires approver action.
# Omit smtp_relay entirely to disable email notifications.
# smtp_relay:
# host: smtp.internal.example.com
# port: 587
# from_email: wallet@example.com
# username: "{{ env `SMTP_USERNAME` }}"
# password: "{{ env `SMTP_PASSWORD` }}"
# tls_skip_verify: false # Set true only for self-signed certs in non-production environments.
# Supported asset families.
asset_families:
- EVM
- solana
- bitcoin
- TVM
- substrate
# Supported blockchain definitions.
# Repeat block entries per chain/network you enable.
blockchains:
- protocol_name: "base"
network_name: "sepolia"
family_name: "EVM"
native_symbol: "BASE-ETH"
decimals: 18
mainnet_coin_type: 8453
test_network: true
native_driver_url: "https://svc.blockdaemon.com/base/testnet/native/http-rpc"
# Optional: credential for this chain's native_driver_url only. When omitted, the global
# auth_token above is used. Plain string = Bearer auth; or HTTP Basic, for example:
# native_driver_auth_token: "{{ env `BASE_SEPOLIA_NATIVE_DRIVER_KEY` }}"
# native_driver_auth_token: "Authorization: Basic dXNlcjpwYXNz"
family_properties:
evm_properties:
chain_id: 84532
# Orchestrator DB DSN.
db_url: "postgresql://postgres:{{ env `ORCHESTRATOR_DB_PASSWORD` }}@host.docker.internal:5432/orchestrator?sslmode=disable"
# NATS connection for wallet facade user.
nats:
broker_url: "nats://host.docker.internal:4222"
username: "facade"
password: "{{ env `FACADE_BROKER_PASSWORD` }}"
# Optional TLS CA bundle for NATS server validation.
ca_bundle_file: ""
# Optional client cert/key for mTLS to broker.
client_certificate_file: ""
client_certificate_key_file: ""
# Route IDs must match policy-node [Identity] NodeId (for example route0, route1, route2).
nodes:
- route_id: "route0"
- route_id: "route1"
- route_id: "route2"
# True for testnets/sandboxes, false for production mainnet-only behavior.
should_use_test_networks: true
staking:
service_name: "BlockdaemonStaking"
protocol_name: "ethereum"
native_asset_symbol: "ETH"
auth_token: "{{ env `BOSS_API_KEY` }}"
client_id: "3bcf0d33-cb49"
is_test_network: true
url: "https://svc.blockdaemon.com"
# Global MPA timeout.
timeout: "5m"
utxos:
url: "https://svc.blockdaemon.com"
auth_token: "{{ env `BD_API_KEY` }}"
# OIDC configuration.
oidc_static_config:
issuer: "https://auth.example-wallet.local/oauth2/default"
audience: "api://wallet-example"
# SPA/web frontend OIDC client id.
client_id: "wallet-spa-client-id-example"
# Native/mobile Approver app OIDC client id.
# Must match policy-node TOML OIDCConfig.ClientID for approver JWT validation.
client_id_native: "wallet-approver-native-client-id-example"
# Wallet HTTP port.
port: 80
# Optional region label.
region: ""
# Use IAM DB authentication instead of static DB passwords (AWS deployments).
# When true, wallet DB connections use IAM auth token flow (for example RDS IAM auth).
use_iam: false
# Telemetry.
telemetry:
enable_prom: true
enable_otlp: true
service_name: "wallet"
# OTLP collector endpoint.
otel_endpoint: "localhost:4318"
# Sample ratio: 0..1
otel_sample_ratio: 1
# Ubiquity API integration.
ubiquity:
url: "https://svc.blockdaemon.com"
api_key: "{{ env `BD_API_KEY` }}"
# WalletConnect integration (runs in-process in the wallet service).
walletconnect:
project_id: "927b518384169c157828af8b77181ad3"
# Staking API settings.
staking_api:
api_key: "{{ env `BD_API_KEY` }}"
base_url: "https://svc.blockdaemon.com/boss"
# Staking reporting API settings.
staking_report_api:
api_key: "{{ env `BD_API_KEY` }}"
base_url: "https://svc.blockdaemon.com/boss/reporting/staking/v1"
cache_expiration: "10m"
# Mailer sender identity.
mailer:
from_email: "wallet-noreply@localhost"
# Service version label.
version: "2.0"
# Optional Canton integration.
# Uncomment and set values when Canton support is enabled.
#canton_config:
# # OAuth2 client-credentials token endpoint for Canton participant and validator APIs.
# token_url: "https://<oidc_issuer>/realms/canton-devnet/protocol/openid-connect/token"
# # OAuth2 client ID for the client-credentials grant (machine-to-machine identity). The token subject
# # for this client must hold IdentityProviderAdmin or ParticipantAdmin on the participant node to create external parties.
# client_id: "A54918EC-DD51-4B5A-BED5-C0653C3C48FA"
# # Secret for the OAuth client above. Use secret interpolation, not plaintext.
# client_secret: "{{ env `CANTON_DEVNET_CLIENT_SECRET` }}"
# # OAuth audience required by the Canton IdP. Must match the token aud claim.
# audience: "<audience>"
# # Canton network label (e.g. devnet, testnet, mainnet). Must match the registered chain.
# network: "devnet"
# # gRPC Ledger API endpoint (used by the wallet Canton driver and MPA).
# ledger_api_url: "https://<canton_grpc_endpoint>:443"
# # HTTP JSON Ledger API base URL (not gRPC). Required for the embedded Canton Contract Management UI.
# json_ledger_api_url: "https://<canton_json_ledger_endpoint>/api/json-api"
# # HTTP Validator API base URL (scan proxy, wallet registration).
# validator_api_url: "https://<canton_wallet_endpoint>/api/validator"
# # When true, the wallet re-runs address generation for existing Canton accounts after startup. Dev and recovery convenience after a ledger reset; does not reset sync cursors.
# regenerate_addresses: true
# # Optional. Required for outgoing Canton DA Utility Token transfers.
# # Host root only (no path). Vault discovers instruments at {base}/api/utilities/v0/contract/instrument-configuration/all.
# token_registry_urls:
# - "https://<token_registry_host>"
Policy Node Configuration
Each policy node is configured by a single TOML file (e.g. policy-node.conf). The three nodes differ only by identity and broker username; the rest of the structure is the same. Sensitive values (database password, broker password, encryptor master password) must come from secrets (env or secret-manager interpolation).
Confidential Computing and Attestation
For production deployments, secret protection should include Confidential Computing and remote attestation for policy-node workloads. This ensures secret confidentiality while the workload is running (in-use), not only at rest or in transit. For the security architecture (Nitro/Azure TEE isolation, KMS attestation, and MPC share protection), see MPC and TEE Security Architecture.
- Run policy-node workloads in a confidential execution environment (TEE-backed runtime).
- Require remote attestation before releasing sensitive material such as
ENCRYPTOR_MASTER_PASSWORD, broker credentials, database passwords. - Keep secrets in an external secrets manager and release them to workloads only after attestation policy checks pass.
- Use short-lived credentials where possible and rotate static secrets in the service secret table regularly.
Example policy node TOML
Below is an example for policy node 0 (route0). For node 1 and 2, change NodeId, PlayerIndex, and Broker.Username to route1/route2, 1/2, and node1/node2. Passwords and encryptor material must come from your secret store (env vars or secret-manager interpolation); do not commit real passwords.
policy-node.conf
# OIDC config list. You can define one or more OIDC providers.
[[OIDCConfig]]
# OIDC issuer URL.
Issuer = "https://auth.example-wallet.local/oauth2/default"
# OIDC client id expected in JWT audience/client claims.
ClientID = "wallet-approver-native-client-id-example"
# Optional: allow tokens without email_verified=true.
AllowUnverifiedEmail = false
# Optional: static public keys. If omitted, keys are fetched from the IdP JWKS endpoint.
[[OIDCConfig.PublicKeys]]
# Key ID from JWT header.
KID = "kid-1"
# Base64-encoded DER public key bytes (non-secret public key material).
Key = "MIIBojANBgkqhkiG9w0BAQEFAA...u6AfzAgMBAAE="
# Identity: NodeId must match wallet mpa.nodes[].route_id and broker routing (route0, route1, route2).
[Identity]
NodeId = "route0"
# MPC player index for this node.
PlayerIndex = 0
# Global encryptor password for multi-tenant mode (required unless set per-tenant).
[Secrets]
EncryptorMasterPassword = "{{ env `ENCRYPTOR_MASTER_PASSWORD` }}"
# Global/default database used when tenant-specific database override is not set.
[Database]
# Database driver name.
DriverName = "pgx"
# DSN/connection string.
DataSourceName = "host=postgres sslmode=require user=postgres password={{ env `DB_PASSWORD` }} dbname=local"
# Broker settings.
[Broker]
# Broker endpoint URL.
URL = "nats://nats:4222"
# Username/password auth (optional depending on broker mode).
Username = "node0"
Password = "{{ env `BROKER_PASSWORD` }}"
# Optional token auth (NATS).
Token = ""
# Optional (NATS): allow untrusted TLS certificates (development only).
AllowUntrustedCertificate = false
# Optional broker public key pinning (base64-encoded key bytes).
PublicKey = ""
# Optional client mTLS cert/key file paths.
ClientCertificateFile = ""
ClientCertificateKeyFile = ""
# Optional CA bundle path for broker TLS verification.
CABundleFile = ""
# Service settings.
[Service]
# If > 0, HTTP on this port: GET /live (liveness), GET /ready (readiness after NATS subscribe), GET /metrics (optional). GET /health is deprecated (same as /live).
HealthCheckPort = 8080
# CloudWatch logging toggle.
CloudwatchLogging = false
# Tenant-specific overrides. You can define multiple tenant blocks.
[Tenant.default]
# Optional tenant ERS RSA public key (base64-encoded DER/SPKI).
ERSPublicKey = "MIIBojANBgkqhkiG9w0BAQEFAA...u6AfzAgMBAAE="
# Optional tenant-specific override for EncryptorMasterPassword.
EncryptorMasterPassword = "{{ env `ENCRYPTOR_MASTER_PASSWORD` }}"
# Optional tenant-specific DB override (same keys as [Database]).
[Tenant.default.Database]
DriverName = "pgx"
DataSourceName = "host=postgres sslmode=require user=postgres password={{ env `DB_PASSWORD` }} dbname=local"
Broker Configuration
The message broker (NATS) can be secured with password authentication and/or TLS.
Password authentication
- The broker is configured with one user per client: e.g.
node0,node1,node2for policy nodes,facadefor the wallet. - Each component’s config supplies the same username and the password (from a secret). No certificates are required for this mode.
- In NATS server config,
accounts.default.users[].passwordshould be a bcrypt hash (not raw plaintext). Keep raw passwords only in client-side secret values.
Recommended setup sequence (config-focused):
- Generate one raw password per NATS user (
node0,node1,node2,facade). - Configure each client service with its username and raw password.
- Configure NATS
accounts.default.users[].passwordwith bcrypt hashes of those same passwords. - Generate broker server TLS cert/key and CA chain.
- If using mTLS, generate per-service client cert/key material.
- Mount cert/key/CA files into pods and point service config fields to file paths (
ClientCertificateFile,ClientCertificateKeyFile,CABundleFile).
Certificates
- Server TLS: Broker can expose a TLS listener (e.g.
nats://with TLS or a separate port). In that case, clients need to trust the broker’s certificate (or the CA that signed it). - Client certificates (mTLS): Policy nodes and wallet can present a client certificate to the broker. In the policy-node config this is done via:
ClientCertificateFile– path to the client certificate (PEM).ClientCertificateKeyFile– path to the client private key (PEM).
- CA bundle: To verify the broker’s server certificate, set:
CABundleFile– path to a PEM file containing the CA (or CA chain) that signed the broker’s certificate.
In Kubernetes, TLS material is typically mounted from Secrets (e.g. kubernetes.io/tls or opaque Secrets) into the pod; config then references file paths under the mount (e.g. /certs/tls.crt, /certs/tls.key, /certs/ca.crt). On VMs, use equivalent paths to where you deploy certs and keys.
nats-server.conf
{
// NATS client port used by wallet and policy nodes.
"port": 4222,
// Monitoring/health endpoint (e.g. GET /healthz).
"http_port": 8222,
// Optional websocket listener for broker websocket clients.
"websocket": {
// Websocket port.
"port": 8443,
// Set true for plaintext websocket in local/dev.
// Set false in production and configure websocket TLS.
"no_tls": true
},
// TLS for NATS client listener (production recommended).
// Enable this block and provide broker certificate material in production.
"tls": {
// Broker/server certificate PEM.
"cert_file": "/etc/nats/server-cert.pem",
// Broker/server private key PEM.
"key_file": "/etc/nats/server-key.pem",
// CA bundle PEM used to validate client certificates and trust chain.
"ca_file": "/etc/nats/intermediate-ca.pem",
// Require and verify client certificates.
"verify": true
},
// Debug tracing. Keep false in production unless troubleshooting.
"debug": false,
"trace": false,
// User accounts and credentials.
"accounts": {
"default": {
"users": [\
// Use bcrypt password hashes in NATS server config.\
{ "user": "node0", "password": "{{ env `NODE0_BROKER_PASSWORD_HASH` }}" },\
{ "user": "node1", "password": "{{ env `NODE1_BROKER_PASSWORD_HASH` }}" },\
{ "user": "node2", "password": "{{ env `NODE2_BROKER_PASSWORD_HASH` }}" },\
{ "user": "facade", "password": "{{ env `FACADE_BROKER_PASSWORD_HASH` }}" }\
]
},
// Internal NATS system account.
"SYS": {}
},
// Authorization options.
// Option A (default): static username/password in accounts.default.users (shown above).
// Option B (advanced): auth_callout for externalized auth/token validation.
"authorization": {
"auth_callout": {
// Public key / issuer material used by auth callout verifier.
// Must match the public key derived from the auth-callout signer seed.
"issuer": "{{ env `BROKER_PUBLIC_KEY` }}",
// Users that are allowed to use auth callout in the target account.
// Must use NATS usernames (not service IDs).
"auth_users": ["node0", "node1", "node2", "facade"],
// Account where auth_callout should apply.
"account": "default"
}
},
"system_account": "SYS"
}
Verification
- Broker: HTTP health on the monitoring port (e.g. 8222) at
/healthz. - Wallet: HTTP 200 on
/health(e.g. port 8080). - Policy nodes (when
HealthCheckPortis set): HTTP 200 on/live; HTTP 200 on/readyonly after NATS connect and subscribe (503 before then)./healthis deprecated (same behavior as/live). - Postgres:
pg_isready(or equivalent) for the postgres user; engine 14 or 15.
Summary
- Install in order: namespace/RBAC → secrets/config → database → broker → policy nodes → wallet → cold wallet (optional) → ingress/gateway.
- Policy nodes require broker + database connectivity (+ inter-node MPC).
- Use an external secrets manager in production (for example AWS Secrets Manager, Azure Key Vault, or Vault); never put secrets in ConfigMaps or in repo.
- Broker: password auth and/or TLS/mTLS; policy nodes support CA bundle and optional public key pinning.
- Wallet config: one YAML; MPA section wires route0/route1/route2 via broker only.
- Policy node config: one TOML per node; identity (
NodeId= walletroute_id,PlayerIndex), broker URL/user/password, DB (PostgreSQL 14 or 15), tenant ERS public key (plaintext in config), and encryptor password from secrets; probe/liveand/readyonHealthCheckPort.