Guide

Getting Started

Use Nova Platform for the fastest developer path, or follow this page for the self-hosted Nitro path.

Nova Platform — the fastest path

If you want a fully managed deployment experience (build, deploy, attest, verify), use Nova Platform. This guide covers the self-hosted path using capsule-cli directly on your own infrastructure.


Prerequisites

Nitro-Enabled EC2 Instance

An enclave-capable instance type (e.g., m5.xlarge, c5.2xlarge, or larger). See Nitro Host Setup for full preparation.

Docker

Docker Engine installed on the host. Your application must be packaged as a Docker image.

capsule-cli

The Capsule CLI binary for x86_64-linux. Download from GitHub Releases or build from source.


Step 1: Install capsule-cli

Option A: Download release binary

Download and install
# Download the latest release
curl -LO https://github.com/sparsity-xyz/nova-enclave-capsule/releases/latest/download/capsule-cli-x86_64-unknown-linux-musl.tar.gz

# Extract
tar xzf capsule-cli-x86_64-unknown-linux-musl.tar.gz

# Move to PATH
sudo mv capsule-cli /usr/local/bin/

# Verify
capsule-cli --version

Option B: Use the install script

install.sh
# From the repository root
./install.sh

Option C: Build from source

Build with cross-compilation
# Install cross (for musl builds)
cargo install cross

# Build
cd capsule-cli
cross build --release --target x86_64-unknown-linux-musl \
  --features run_enclave,capsule-runtime

# Binary at: target/x86_64-unknown-linux-musl/release/capsule-cli

Step 2: Prepare Your Docker App

Your application must be a working Docker image. Capsule doesn't change how you write your app — it wraps it.

Application requirements

  • Standard Docker image with a working entrypoint
  • Listens on TCP ports for incoming requests
  • Uses HTTP/HTTPS for outbound calls (not raw TCP)
  • Works with the standard proxy environment variables if outbound access is needed

Optional: Use Capsule APIs

  • HTTP requests to 127.0.0.1:18000 for attestation, signing, encryption
  • Use the mock service for local development
  • Switch to real API inside enclave with environment variable detection

Recommended pattern for local / enclave switching

Set IN_ENCLAVE=true in your Dockerfile's ENV. In local dev, omit or set to false. Your app reads this to choose between mock and real Capsule API base URL.

Python example: choose API base URL
import os

IN_ENCLAVE = os.getenv("IN_ENCLAVE", "false").lower() == "true"
CAPSULE_API_MOCK_URL = os.getenv("CAPSULE_API_MOCK_URL", "http://localhost:18000")
CAPSULE_API_BASE_URL = "http://127.0.0.1:18000" if IN_ENCLAVE else CAPSULE_API_MOCK_URL

Step 3: Write capsule.yaml

The manifest tells Capsule how to build and run your enclave application.

Minimal capsule.yaml
version: v1
name: "my-app"
target: "my-app-enclave:latest"

sources:
  app: "my-app:latest"

defaults:
  cpu_count: 2
  memory_mb: 4096

ingress:
  - listen_port: 8080

egress:
  allow:
    - "api.example.com"

api:
  listen_port: 18000
sources.app is the only required image. Capsule Runtime and Shell images are pulled from the public registry by default. See capsule.yaml reference for all options.

Step 4: Build the Capsule Image

Build
# Make sure your app image is available locally
docker build -t my-app:latest .

# Build the capsule image
capsule-cli build -f capsule.yaml
This produces an image tagged as the target value from your manifest (e.g., my-app-enclave:latest). The image contains the Capsule Shell, the EIF, and your manifest.

What happens during build

1. Your app image is amended with Capsule Runtime binary and manifest.
2. nitro-cli build-enclave converts it into an EIF (Enclave Image File).
3. The EIF is packaged into the Capsule Shell base image as the final release artifact.


Step 5: Run the Enclave

Run on a Nitro-enabled host
# Basic run
sudo capsule-cli run my-app-enclave:latest

# With port mapping
sudo capsule-cli run my-app-enclave:latest -p 8080:8080

# With debug console
sudo capsule-cli run my-app-enclave:latest -p 8080:8080 -d

# With resource overrides
sudo capsule-cli run my-app-enclave:latest \
  --cpu-count 4 --memory-mb 8192 \
  -p 8080:8080

# With host-backed mount
sudo capsule-cli run my-app-enclave:latest \
  -p 8080:8080 \
  --mount appdata=/var/lib/my-app/data
Default CPU
2 vCPUs
Default Memory
4096 MiB
API Port
18000
Aux API
18001

Verify It Works

Quick verification
# Check if the app responds
curl http://localhost:8080/health

# If your app calls the Capsule API, verify from inside the enclave:
# The app can reach http://127.0.0.1:18000/v1/eth/address
# and http://127.0.0.1:18000/v1/random

What's Next