# MPC deployment on AWS

This guide covers deploying customer MPC nodes (Node 2 and Node 3) to AWS using the **MPC Deployer** tool.

**Prerequisites:** Review the [MPC overview](/products/custody/v1.34/how-to/integrate-kms/mpc/overview) to understand the architecture, shared responsibility model, and node ownership before proceeding.

## Overview

The MPC Deployer automates the deployment of customer MPC nodes to **AWS Nitro Enclaves**, providing hardware-based isolation for key material.

### What gets deployed


```mermaid
flowchart TB
    subgraph aws["AWS Account (Customer)"]
        subgraph vpc["VPC"]
            subgraph pub1["Public Subnet 1"]
                nat1["NAT Gateway 1"]
            end
            subgraph pub2["Public Subnet 2"]
                nat2["NAT Gateway 2"]
            end
            subgraph priv1["Private Subnet 1 (AZ1)"]
                ec2_1["EC2 Nitro Instance<br/>MPC Node 2"]
            end
            subgraph priv2["Private Subnet 2 (AZ2)"]
                ec2_2["EC2 Nitro Instance<br/>MPC Node 3"]
            end
        end
        igw["Internet Gateway"]
        s3["S3 Bucket<br/>Enclave Config"]
        secrets["Secrets Manager<br/>Keys & Config"]
        cw["CloudWatch<br/>Logs"]
    end

    igw --> nat1
    igw --> nat2
    nat1 --> ec2_1
    nat2 --> ec2_2
    ec2_1 --> s3
    ec2_2 --> s3
    ec2_1 --> secrets
    ec2_2 --> secrets
    ec2_1 --> cw
    ec2_2 --> cw

    style aws fill:#fff3e0,stroke:#ef6c00
    style vpc fill:#e3f2fd,stroke:#1565c0
    style ec2_1 fill:#e8f5e9,stroke:#2e7d32
    style ec2_2 fill:#e8f5e9,stroke:#2e7d32
```

**Existing VPC support:** The deployer supports a mode where networking resources (VPC, subnets, NAT gateways, etc.) are not created. Use the `--no-create-vpc` flag if your organization manages networking centrally.

### AWS resources created

| Resource | Count | Purpose | Notes |
|  --- | --- | --- | --- |
| VPC | 1 | Network isolation | Optional - use `--no-create-vpc` to skip |
| Public Subnets | 2 | NAT gateway hosting | Optional - not created with `--no-create-vpc` |
| Private Subnets | 2 | MPC node hosting (one per AZ) | Optional - not created with `--no-create-vpc` |
| Internet Gateway | 1 | Outbound internet access | Optional - not created with `--no-create-vpc` |
| NAT Gateways | 2 | Outbound access for private subnets | Optional - not created with `--no-create-vpc` |
| Route Tables | 4 | Network routing | Optional - not created with `--no-create-vpc` |
| EC2 Nitro Instances | 2 | MPC Node 2 and Node 3 | Required |
| Security Groups | 2 | Network access control | Required |
| S3 Bucket | 1 | Enclave configuration storage | Required |
| Secrets Manager | 1 | Keys and configuration storage | Required |
| CloudWatch Log Groups | 2 | Centralized logging | Required |
| IAM Roles | 2 | EC2 instance permissions | Required |


## Prerequisites

### AWS requirements

**Account & permissions:**

- AWS account with administrative access
- Permissions allowing the deployer tool to create resources in the AWS account


**Credentials (one of):**


```bash
# Option 1: Environment variables
export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
export AWS_DEFAULT_REGION="us-east-1"

# Option 2: AWS credentials file (~/.aws/credentials)
[default]
aws_access_key_id = your-access-key
aws_secret_access_key = your-secret-key
region = us-east-1
```

### Execution requirements

- **Docker**: Docker Desktop or Docker Engine installed and running
- **MPC Deployer Image**: Access to Ripple's Docker registry


**Important:** Contact your Ripple representative to obtain the official MPC Deployer Docker image and registry credentials. Do not use locally-built images in production.

### From Ripple

Before deployment, Ripple will provide:

| Item | Description |
|  --- | --- |
| **MPC Deployer Image** | Official Docker image tag and registry credentials |
| **Tenant Alias** | Your organization identifier |
| **Tenant Instance Code** | Environment identifier (e.g., prod, uat) |
| **Docker Registry Credentials** | Access to `metaco.azurecr.io` (where MPC core component images are stored) |
| **Decryption Server URL** | Enclave decryption service endpoint |
| **OpenTelemetry Endpoint** | Observability service configuration |


## Deployment process

The deployment follows a coordinated process between you and Ripple:


```mermaid
sequenceDiagram
    participant C as Customer
    participant T as MPC Deployer Tool
    participant AWS as AWS Account
    participant R as Ripple

    Note over C,R: Phase 1: Key Generation
    C->>T: Run --keygen mode
    T->>AWS: Store keys in Secrets Manager
    T->>C: Output Node 2 & 3 Peer IDs
    C->>R: Share Peer IDs

    Note over C,R: Phase 2: Ripple Setup
    R->>R: Configure Nodes 0 & 1
    R->>R: Configure Relay Server
    R->>C: Provide Ripple config

    Note over C,R: Phase 3: Deployment
    C->>T: Run deployment mode
    T->>AWS: Provision infrastructure
    T->>AWS: Deploy EC2 Nitro instances
    T->>C: Deployment complete

    Note over C,R: Phase 4: Verification
    C->>R: Confirm connectivity
    R->>C: Run cluster health check
```

## Step 1: Generate node keys

Generate cryptographic keys for your MPC nodes (Node 2 and Node 3):


```bash
docker run --rm -it \
  -e AWS_ACCESS_KEY_ID \
  -e AWS_SECRET_ACCESS_KEY \
  -e AWS_DEFAULT_REGION \
  -v $(pwd)/output:/app/output \
  <RIPPLE_REGISTRY>/mpc-deployer:<VERSION> \
  --keygen --output /app/output
```

The tool will prompt for:

- **Region**: Primary AWS region (e.g., `us-east-1`)
- **Secondary region**: DR region (e.g., `us-west-2`).
- **Tenant alias**: Your organization identifier.
- **Tenant Instance Code**: Environment code


**Output:**


```
🎉 Key material successfully generated and stored in AWS Secrets Manager.
🔑 Node 2 Public Key (Peer ID): 12D3KooWBhMevWJT...
🔑 Node 3 Public Key (Peer ID): 12D3KooWCdEfGhIj...
```

**Share with Ripple:** Send the Node 2 and Node 3 Peer IDs to your Ripple representative. These are public identifiers and are safe to share.

## Step 2: Wait for Ripple configuration

Ripple will configure their infrastructure and provide you with:

| Configuration | Example |
|  --- | --- |
| **Relay Host** | `relay.mpc.ripple.com` |
| **Relay Port** | `6000` |
| **Relay Public Key** | `12D3KooW...` |
| **Node 0 Public Key** | `12D3KooW...` |
| **Node 1 Public Key** | `12D3KooW...` |
| **MPC Docker Image** | `metaco.azurecr.io/custody/mpc-core:1.3.12` |


## Step 3: Deploy MPC nodes

Once you receive configuration from Ripple, deploy the infrastructure:

### Non-interactive deployment (recommended)

For production deployments, use environment variables with the `--non-interactive` flag:


```bash
# Create .env file with configuration
cat > .env << EOF
REGION=us-east-1
SECONDARY_REGION=us-west-2
TENANT_ALIAS=your-tenant
TENANT_INSTANCE_CODE=prod

MPC_DOCKER_IMAGE=metaco.azurecr.io/custody/mpc-core:1.3.12
MPC_DOCKER_REGISTRY_USERNAME=your-username
MPC_DOCKER_REGISTRY_PASSWORD=your-password

MPC_RELAY_HOST=relay.mpc.ripple.com
MPC_RELAY_PORT=6000
MPC_RELAY_PUBLIC_KEY=12D3KooW...
MPC_NODE0_PUBLIC_KEY=12D3KooW...
MPC_NODE1_PUBLIC_KEY=12D3KooW...

OTEL_HTTP_ENDPOINT=https://your-otel-endpoint
OTEL_HTTP_USER=your-username
OTEL_HTTP_PASSWORD=your-password

ENCLAVE_DECRYPTION_SERVER_URL=https://decrypter.metaco.services
EOF

# Run deployment
docker run --rm -it \
  --env-file .env \
  -e AWS_ACCESS_KEY_ID \
  -e AWS_SECRET_ACCESS_KEY \
  -v $(pwd)/output:/app/output \
  -v $(pwd)/.terraform-state:/terraform-state \
  <RIPPLE_REGISTRY>/mpc-deployer:<VERSION> \
  --output /app/output --non-interactive
```

### Interactive deployment (fallback)

If you prefer to enter configuration interactively:


```bash
docker run --rm -it \
  -e AWS_ACCESS_KEY_ID \
  -e AWS_SECRET_ACCESS_KEY \
  -e AWS_DEFAULT_REGION \
  -v $(pwd)/output:/app/output \
  -v $(pwd)/.terraform-state:/terraform-state \
  <RIPPLE_REGISTRY>/mpc-deployer:<VERSION> \
  --output /app/output
```

The tool will prompt for all required configuration. Previously stored values (from key generation) will be pre-populated from AWS Secrets Manager.

### Deployment into existing VPC

If you have an existing VPC, use the `--no-create-vpc` flag:


```bash
docker run --rm -it \
  -e AWS_ACCESS_KEY_ID \
  -e AWS_SECRET_ACCESS_KEY \
  -e AWS_DEFAULT_REGION \
  -v $(pwd)/output:/app/output \
  -v $(pwd)/.terraform-state:/terraform-state \
  <RIPPLE_REGISTRY>/mpc-deployer:<VERSION> \
  --output /app/output --no-create-vpc
```

You will be prompted for:

- **VPC ID**: `vpc-0123456789abcdef0`
- **Private Subnet 1 ID**: `subnet-0123456789abcdef0`
- **Private Subnet 2 ID**: `subnet-0123456789abcdef1`


## Step 4: Verify deployment

After deployment completes, verify the infrastructure:

### Check EC2 instances

Verify that the Nitro Enclave instances are running and have the correct instance type:


```bash
aws ec2 describe-instances \
  --filters "Name=tag:Type,Values=nitro-enclave" \
  --query 'Reservations[].Instances[].{ID:InstanceId,State:State.Name,Type:InstanceType}'
```

**What to check:** Confirm both instances show `State: running` and are using a Nitro-compatible instance type (e.g., `m5.xlarge` or larger).

### Check CloudWatch logs

Verify that log groups exist and contain enclave boot logs:


```bash
aws logs describe-log-groups \
  --log-group-name-prefix "<TENANT_ALIAS>-<INSTANCE_CODE>"
```

**What to check:** Look for log entries indicating the enclave has successfully booted and connected to the relay server.

### Verify Secrets Manager

Confirm that secrets were created for your deployment:


```bash
aws secretsmanager list-secrets \
  --filter Key=name,Values="<TENANT_ALIAS>-<INSTANCE_CODE>"
```

**What to check:** This command lists secret names only and does not reveal key material. Verify that secrets for Node 2 and Node 3 exist.

## Command reference

| Flag | Description | Default |
|  --- | --- | --- |
| `--output` | Output directory for logs and generated files | `./output/` |
| `--keygen` | Generate key material for customer nodes | `false` |
| `--no-create-vpc` | Use existing VPC (prompts for VPC/subnet IDs) | `false` |
| `--non-interactive` | Disable interactive prompts (recommended for production) | `false` |
| `--dry-run` | Simulate deployment without making changes | `false` |


## Troubleshooting

### Common issues

| Issue | Cause | Solution |
|  --- | --- | --- |
| AWS credentials error | Invalid or expired credentials | Refresh credentials, verify IAM permissions |
| VPC quota exceeded | Account VPC limit reached | Request limit increase or use `--no-create-vpc` |
| EC2 instance launch failed | Nitro instance not available in AZ | Try different region or instance type |
| Docker registry auth failed | Invalid registry credentials | Verify credentials with Ripple |
| Secrets Manager access denied | Missing IAM permissions | Verify your Secrets Manager permissions |


### Log files

All operations are logged to the output directory:

| Log File | Content |
|  --- | --- |
| `output.log` | Main application logs |
| `cdktf.log` | Infrastructure provisioning logs |


### Getting help

If you encounter issues:

1. Check log files in the output directory
2. Verify AWS credentials and permissions
3. Contact your Ripple representative with log files


## Next steps

After successful deployment, contact your Ripple representative to:

1. **Verify connectivity** between your nodes and Ripple nodes
2. **Complete cluster configuration** and run health checks
3. **Test key generation** using the DKG process
4. **Set up [MPC backups](/products/custody/v1.34/how-to/integrate-kms/mpc/backups)** for encrypted shard backups with verifiable encryption
5. **Review [Production best practices](/products/custody/v1.34/how-to/integrate-kms/production-best-practices)** for namespace segmentation, HA, and monitoring