# Run CloudSign in AWS Nitro Enclaves

You can run CloudSign inside an AWS Nitro Enclave — an isolated compute environment with no persistent storage, no interactive access, and no direct network connectivity. The enclave isolates the CloudSign node and its key material from the host EC2 instance.

This guide assumes you have already created CloudSign devices and recorded their pairing keys. See [Set up and run CloudSign](/products/wallet/user-interface/devices/set-up-and-run-cloudsign).

New devices only
An existing CloudSign device that has already paired can't be moved into an enclave. To run CloudSign in a Nitro Enclave, create a new device in the console and pair it from inside the enclave.

## How it works

A Nitro deployment has three components:

- **CloudSign enclave image** — The CloudSign node, packaged as an Enclave Image File (EIF) that runs inside the enclave.
- **Networking proxy (`tacos`)** — A systemd service on the host that tunnels the enclave's traffic between a virtual network interface and the enclave's vsock channel, because the enclave has no network interface of its own.
- **Configuration server (`servitor`)** — A small service on the host that serves the node's configuration to the enclave over HTTP on port `3000`. The enclave fetches its configuration once at startup.


In Nitro mode, CloudSign requires a PostgreSQL database — the local storage option isn't available inside an enclave.

The EC2 instance requires no inbound network connectivity — the enclave only makes outbound connections through the host. You can apply firewall rules that block all inbound traffic to the instance.

## Prerequisites

- An EC2 instance with Nitro Enclaves enabled — for example, `m5.xlarge` — running Amazon Linux 2023.
- Docker, and the AWS Nitro Enclaves CLI (`aws-nitro-enclaves-cli` and `aws-nitro-enclaves-cli-devel`). Add your user to the `docker` and `ne` groups.
- The Nitro allocator (`/etc/nitro_enclaves/allocator.yaml`) configured with at least 1 GB of memory and 2 CPU cores. Restart the `nitro-enclaves-allocator` service after you change this file.
- Access credentials for the Palisade container registry (provided by Palisade).
- A PostgreSQL database reachable from the host.
- An AWS KMS key ARN for database encryption (`DB_ENCRYPTION_KEY_REF`).
- A CloudSign pairing key from the console.


Component versions
The CloudSign Nitro image, `tacos`, and `servitor` versions must be compatible with each other. Confirm the current version set with your Palisade representative before deployment, and use it in place of `<version>` below.

## 1. Pull the CloudSign Nitro image

Sign in to the Palisade container registry, then pull the Nitro image:

```shell
aws ecr get-login-password --region eu-west-2 | docker login --username AWS --password-stdin 335650072995.dkr.ecr.eu-west-2.amazonaws.com

docker pull 335650072995.dkr.ecr.eu-west-2.amazonaws.com/external/custody/cloudsign-nitro/app:<version>
```

## 2. Install the networking proxy

Install `socat`, then install and start the `tacos` service. The proxy runs on the host and forwards the enclave's traffic on ports `8080` and `9080`:

```shell
sudo yum install -y socat
sudo systemctl enable tacos.service --now
```

Palisade distributes the `tacos` binary and its systemd unit file as release artifacts — your Palisade representative can point you to the download for your version.

## 3. Build the enclave image file

Build the EIF from the Docker image:

```shell
nitro-cli build-enclave \
  --docker-uri 335650072995.dkr.ecr.eu-west-2.amazonaws.com/external/custody/cloudsign-nitro/app:<version> \
  --output-file ~/cloudsign-<version>.eif
```

## 4. Install and run the configuration server

Install the `servitor` binary (also distributed as a release artifact) to `/usr/local/bin/servitor`, then run it with the node's configuration:

```shell
PAIRING_KEY=<pairing-key> \
DB_ENCRYPTION_KEY_REF=<kms-key-arn> \
DB_DATA_SOURCE='postgres://user:password@host:5432/cloudsign?sslmode=require' \
TSM_DB_DATA_SOURCE='postgres://user:password@host:5432/cloudsign?sslmode=require' \
servitor
```

The server listens on port `3000` and serves the configuration to the enclave. `SIGN_MODE_ACTIVE` (default `true`) and `LOG_LEVEL` are optional.

Protect the configuration
The configuration contains the pairing key and database credentials. If you store it in a file, restrict its permissions (for example, `chmod 600`) and don't commit it to source control.

## 5. Run the enclave

Restart the proxy, then launch the enclave with the resources you allocated:

```shell
sudo systemctl restart tacos.service

nitro-cli run-enclave \
  --eif-path ~/cloudsign-<version>.eif \
  --cpu-count 2 \
  --memory 1024 \
  --enclave-cid 5
```

At startup, the enclave fetches its configuration from the host's configuration server and pairs with the platform. The device in the console moves to **Waiting for approval**, and setup continues as in the [standard flow](/products/wallet/user-interface/devices/set-up-and-run-cloudsign#approve-cloudsign-devices): approve the device, create a quorum, and create wallets.

To see the enclave's console output while debugging, add `--attach-console` to the `run-enclave` command.

## Troubleshooting

| Problem | Cause | Solution |
|  --- | --- | --- |
| `nitro-cli run-enclave` fails with insufficient resources | Allocator not configured or not restarted | Check `/etc/nitro_enclaves/allocator.yaml` reserves at least 1 GB and 2 CPUs; restart `nitro-enclaves-allocator` |
| Enclave starts but the device doesn't pair | Configuration server or proxy not running | Verify `servitor` is running on port 3000 and `tacos.service` is active; then restart the enclave |
| Enclave can't reach the platform | Blocked egress from the host | The enclave's traffic egresses through the host — apply the [network requirements](/products/wallet/user-interface/devices/set-up-and-run-cloudsign#network-requirements) to the host instance |