Primer

How Hyperledger Identus fits together

Identus is a set of components for building self-sovereign identity systems: agents that hold keys and speak DIDComm, a node that anchors DID operations, and SDKs for edge wallets. This page summarises the moving parts; the official documentation is the authoritative reference.

identus.io/documentation

The stack

Cloud Agent

A Scala service exposing a REST API for DID management, DIDComm connections, credential issuance and proof presentation. Backed by Postgres and a PRISM node.

source →
PRISM node

Anchors DID operations to a ledger (or an in-memory ledger for development) and answers DID resolution requests for did:prism.

source →
Mediator

Stores and forwards DIDComm messages for mobile or intermittently connected wallets that cannot hold an inbound endpoint.

source →
SDKs

Edge-agent SDKs for TypeScript, Kotlin Multiplatform and Swift let wallets hold keys, store credentials and speak DIDComm directly.

source →

The credential lifecycle

1 · Create DIDs

The issuer publishes a did:prism with an assertion key; the holder creates one for authentication.

2 · Connect

The issuer creates an out-of-band invitation. The holder accepts it and both sides exchange peer DIDs over DIDComm.

3 · Offer

The issuer sends a credential offer referencing a schema and the claims it will attest.

4 · Accept & issue

The holder accepts the offer; the agent signs a W3C JWT verifiable credential and delivers it to the wallet.

5 · Present & verify

A verifier requests a presentation. The holder responds and the verifier checks signature, issuer DID and revocation status.

Cloud Agent endpoints used by this app

POST
/did-registrar/didsCreate a new managed DID
POST
/connectionsCreate a DIDComm out-of-band invitation
POST
/issue-credentials/credential-offersOffer a verifiable credential
POST
/present-proof/presentationsRequest a presentation from a holder
GET
/_system/healthAgent health and version

Where to run an Identus Cloud Agent

The Cloud Agent ships as container images and needs a Postgres instance with several databases on a private network. That shapes which hosts can run the full stack versus which are only suitable for code snippets.

Use postgres:13-alpine with Cloud Agent 1.40. On Postgres 16 or newer the agent's V27 migration fails with syntax error at or near “format” and the agent never starts — both the Fly deploy and the Compose Lab template pin 13 for that reason.

Capability
Fly Machines
Docker local
Sprites.dev
Container image execution
Yes — runs identus/identus-cloud-agent and identus/prism-node images
Yes — the same pinned images, run locally by Compose
No — sprites.dev runs a single Linux box, not container images
Multi-service composition
Yes — separate Machines for Postgres, PRISM node and Cloud Agent
Yes — Compose orchestrates all services
No — one command at a time, no Compose-like service grouping
Managed Postgres + private network
Yes — Fly Postgres with internal 6PN IPs and 4 databases
Yes — local Postgres on the Docker network
No — no managed Postgres or private service networking
Long-running agent service
Yes — Machines stay up and expose HTTPS endpoints
Yes — but localhost only; external DIDComm peers need a tunnel
No — exec commands are short-lived; no persistent service model
SDK snippet sandbox
Not designed for ad-hoc code
Possible but manual
Yes — per-user Node box with the Identus TypeScript SDK
Recommendation: use Fly Machines for Cloud Agents. A real Identus Cloud Agent needs Postgres, a PRISM node and the agent service running together with a public HTTPS endpoint. Fly Machines supports this multi-service composition, private networking and health checks out of the box.
Sprites.dev is only the SDK sandbox. It cannot host the Cloud Agent because it has no container image execution, no multi-service composition and no managed Postgres. The companion app uses it instead as a per-user scratch box: each account gets a private sprite with Node and the Identus TypeScript SDK installed, and snippets run there with the active agent's base URL and admin key injected as environment variables. The same box also powers the Compose Lab, which authors, interpolates and lints the docker-local stack — ports, credentials, image tags and databases — and then hands you the bundle plus the commands to run it on your own machine. Sprites never executes the containers.
Delegation quickstart. The SDK snippets tab opens with copy-paste TypeScript for the flow most people need first: issue an AgentDelegationCredential for an AI agent, then verify it — right agent, in scope, within the spend cap, not expired — before honouring the action. Signing uses WebCrypto ES256, so the snippets run unchanged in the browser, in Node and in the sandbox, and the claim names match what the x402 gate actually checks.

Run Identus with Docker

Docker Compose gives you the highest-fidelity local stack: the same images the hosted deployment uses, on your own machine, with logs and a debugger within reach.

1 · Prerequisites

Docker Desktop or Docker Engine with the Compose v2 plugin — Compose is a docker compose subcommand now, not the old docker-compose binary. The Cloud Agent and PRISM node are JVM services, so give Docker at least 4 GB of memory and 2 CPUs.

docker compose version   # expect v2.x
docker info | grep -i "total memory"

2 · Get a stack

Either take the upstream stack from the Cloud Agent repository, or generate a validated bundle from the Compose Lab in the console's Sandbox — it writes docker-compose.yml, .env and postgres/init.sql with pinned image tags.

git clone https://github.com/hyperledger-identus/cloud-agent
cd cloud-agent/infrastructure/local
./run.sh            # agent on http://localhost:8085/cloud-agent

3 · Lifecycle commands

docker compose config               # print the interpolated stack, catch .env typos
docker compose up -d --wait         # start and block until services are healthy
docker compose ps                   # state + published ports
docker compose logs -f cloud-agent  # follow one service
docker compose restart cloud-agent  # bounce a single service
docker compose pull && docker compose up -d   # upgrade to newer image tags
docker compose down                 # stop, keep the Postgres volume
docker compose down -v              # stop and DELETE all wallet + DID data

--wait is the important one: it returns only once every service with a healthcheck reports healthy, so scripts never race a half-booted agent.

4 · How the stack fits together

  your app / console
          |  REST  :8085/cloud-agent          DIDComm  :8090
          v
   +--------------+  gRPC :50053   +------------+
   | cloud-agent  |--------------->| prism-node |
   +--------------+                +------------+
          |  pollux, connect, agent      |  node
          v                              v
              +--------------------------+
              |  postgres :5432 (pgdata) |
              +--------------------------+

Four databases are created by postgres/init.sql pollux (credentials), connect (DIDComm connections), agent (wallets and secrets) and node (PRISM node). Keeping them separate stops the modules' migrations from colliding.

5 · Environment and ports

.env var
Default
Purpose
AGENT_PORT
8085
Host port for the Cloud Agent REST API (/cloud-agent).
DIDCOMM_PORT
8090
Host port for the agent's DIDComm endpoint.
PRISM_NODE_PORT
50053
Host port for the PRISM node's gRPC API.
POSTGRES_PORT
5432
Host port for Postgres — change it if you already run one.
POSTGRES_USER
postgres
Owner of the pollux, connect, agent and node databases.
POSTGRES_PASSWORD
postgres
Database password; change it for anything shared.
ADMIN_TOKEN
local-admin-token
Admin API key. This is what the console stores.
DEFAULT_WALLET_AUTH_API_KEY
local-admin-token
API key for the default wallet; keep it equal to ADMIN_TOKEN.

Only the left side of a port mapping is yours to change. If 5432 is already taken by a local Postgres, set POSTGRES_PORT=5433 — the container keeps listening on 5432 inside the network, so no other service needs editing.

6 · Startup order and health

The agent cannot migrate its schema until Postgres accepts connections, so Postgres declares a pg_isready healthcheck and the other services depend on it with condition: service_healthy. Plain depends_on only waits for the container to start, which is not the same as ready. The agent has its own healthcheck against /_system/health with a generous start_period for JVM boot.

7 · Connect the console

On the Agents page pick Docker local, set the base URL to http://localhost:8085/cloud-agent and paste your ADMIN_TOKEN as the admin API key, then run the health probe. Verify from the shell first:

curl -fsS http://localhost:8085/cloud-agent/_system/health
curl -fsS -H "apikey: $ADMIN_TOKEN" \
  http://localhost:8085/cloud-agent/did-registrar/dids

8 · Troubleshooting

Error: bind: address already in use

Cause: Another process (often a local Postgres, or a previous stack) already holds that host port.

Fix: Change the host side in .env — e.g. POSTGRES_PORT=5433 — then docker compose up -d --wait. Find the culprit with lsof -i :5432.

cloud-agent restarts in a loop

Cause: Its schema migration failed, usually because a database is missing or credentials changed.

Fix: Read docker compose logs cloud-agent for the Flyway/JDBC error, confirm all four databases exist with docker compose exec postgres psql -U postgres -l, then reset with docker compose down -v.

Databases missing even though init.sql is present

Cause: Scripts in /docker-entrypoint-initdb.d only run when the data directory is empty, and the pgdata volume already existed.

Fix: docker compose down -v to drop the volume, then bring the stack back up so the init script runs.

no matching manifest for linux/arm64

Cause: The pinned image has no arm64 build (common on Apple Silicon).

Fix: Add platform: linux/amd64 to that service and expect emulation to be slower, or pick a tag that publishes multi-arch images.

pull access denied / unauthorized

Cause: The tag points at a private or non-existent registry path.

Fix: Use the public Docker Hub images identus/identus-cloud-agent and identus/prism-node with an explicit version tag — never :latest.

Agent healthy but the console cannot reach it

Cause: The base URL is missing the /cloud-agent prefix, or the apikey header is not being sent.

Fix: Use http://localhost:8085/cloud-agent and set the admin key to your ADMIN_TOKEN value, then re-run the health probe.

9 · Data and cleanup

All state lives in the named volume pgdata. Published DIDs and issued credentials do not survive a down -v, so back it up before resetting.

docker compose exec postgres pg_dumpall -U postgres > identus-backup.sql
docker volume ls | grep pgdata
docker compose down -v && docker compose up -d --wait   # clean slate

Other ways to run

Fly.io, from the console

The Agents page provisions a Fly app with three machines — Postgres, a PRISM node and the Cloud Agent — using your Fly organisation token, then stores the generated API key so the console can talk to it over HTTPS.

Simulated

No infrastructure. The app performs the same workflow deterministically so you can learn the protocol shape before deploying anything.