Skip to content

Run the reference stack

The reference deployment is orchestrated by one program: unidpp-stack in the unidpp-pilot-data repository (source at ops/, invoked from the pilot directory as ./ops/target/release/unidpp-stack). It builds each service if needed, starts them dependency-ordered, waits for each to be healthy, and verifies the right service is on the right port before declaring success.

  • A checkout of the UniDPP family, with the service repositories side by side, with unidpp-pilot-data among them: unidpp-registry, unidpp-trust, unidpp-log, unidpp-issuer, unidpp-projector, unidpp-gateway, unidpp-archive, unidpp-console, unidpp-cli, unidpp-config.
  • Rust toolchain (cargo) for the initial build.
  • curl, jq for the queries this page shows.

Ports used: 8389-8397 (the console, the eight stack services — registry, trust, log, issuer, projector, gateway, archive, and the hub on 8397), and 8399 (the JP peer registry). All loopback by design; public exposure is a per-deployment decision made through a tunnel, not a bind change.

Terminal window
$ cd unidpp-pilot-data
$ ./ops/target/release/unidpp-stack up
==> starting registry on http://127.0.0.1:8390
==> starting trust on http://127.0.0.1:8391
==> starting log on http://127.0.0.1:8392
==> starting issuer on http://127.0.0.1:8393
==> starting projector on http://127.0.0.1:8394
==> starting gateway on http://127.0.0.1:8395
==> starting archive on http://127.0.0.1:8396
==> starting hub on http://127.0.0.1:8397
==> starting console on http://127.0.0.1:8389
==> starting jp-registry on http://127.0.0.1:8399
==> stack up: 8390 registry · 8391 trust · 8392 log · 8393 issuer
8394 projector · 8395 gateway · 8396 archive
8397 hub (stateless relay) · 8389 console · 8399 JP peer
==> next: unidpp-stack seed-jp (idempotent)

What up actually does:

  1. Build if needed. Each service binary is built (cargo build --release) only when missing; UNIDPP_FORCE_BUILD=1 rebuilds unconditionally.
  2. Adopt or refuse. A service already healthy on its port and answering the right identity is adopted (==> registry already healthy on http://127.0.0.1:8390 (reusing)). A foreign listener on a needed port is a hard error naming the holder.
  3. Wire the environment. Every service starts with its UNIDPP_* environment (binds, state files, upstreams), which are the same variables the operator manifest renders.
  4. Wait for health, then verify identity via the discovery document’s service field (all family services answer ok on /healthz; the identity check is what tells them apart on a shared box).
  5. Journals replay. Nothing is wiped; state comes back from the JSONL journals on start.
  6. Tunnels (optional): if tunnel.token, jp-tunnel.token, or console-tunnel.token are present, a cloudflared named tunnel is adopted or started per surface. No token, no tunnel, and the stack stays loopback.
Terminal window
$ ./ops/target/release/unidpp-stack seed
== [1] discovery seed (C3/C4/C5 + C1 units)
already present (10 units — journal replay)
== [2] item seed (10 pilot items)
present urn:unidpp:profile:extraction
...
== [5] demo passport (live issuer)
already issued urn:unidpp:passport:pilot-e8-j000842 (issuer journal replay)
== [6] Tier-A pack + CLI verify (anchor from the issuer /keyring)
verified: PASS (exit 0) — the three readings named, coverage complete
== [7] notarized Tier-C snapshot (anchored in the transparency log)
== [8] projector two-lens views (at 2028-06-01T00:00:00Z)
== [9] gateway renders (UNTP triad + EN 18222)
== [10] as-of applicability for momiji:e8
at 2027-06-01: ['urn:unidpp:profile:jp-road-traffic']
at 2028-06-01: ['urn:unidpp:profile:eu-machinery-battery', 'urn:unidpp:profile:jp-road-traffic']
== seed complete — the stack stays up (unidpp-stack status, unidpp-stack down)

The seed is idempotent: item and profile registrations tolerate 409, the demo passport is issued once, events are appended only up to the expected sequence. Re-running against a seeded stack is safe and produces the demo artifacts under demo/ (the passport view, the Tier-A pack, the CLI verification report, the notarized snapshot, both lens views, both gateway renders, the as-of proofs).

The JP peer node is seeded separately (it has its own journal and register):

Terminal window
$ ./ops/target/release/unidpp-stack seed-jp
[skip] jp-road-traffic profile already present
[skip] jp-road-traffic binding already present
JP node seeded: 1 profile + 1 applicability binding (its own journal, its own register)
Terminal window
$ ./ops/target/release/unidpp-stack status
registry (unidpp-registry) http://127.0.0.1:8390 healthy
trust (unidpp-trust) http://127.0.0.1:8391 healthy
log (unidpp-log) http://127.0.0.1:8392 healthy
issuer (unidpp-issuer) http://127.0.0.1:8393 healthy
projector (unidpp-projector) http://127.0.0.1:8394 healthy
gateway (unidpp-gateway) http://127.0.0.1:8395 healthy
archive (unidpp-archive) http://127.0.0.1:8396 healthy
hub (unidpp-hub) http://127.0.0.1:8397 healthy
console (unidpp-console) http://127.0.0.1:8389 healthy
jp-registry (unidpp-registry) http://127.0.0.1:8399 healthy
registry journal: 1550 records -> 1531 items, 8 discovery services
applicability (momiji:e8 @2028-06-01): urn:unidpp:profile:eu-machinery-battery, urn:unidpp:profile:jp-road-traffic
log tree head: size 5 · root d23b199b96ed73ea…
demo artifacts: 13 files under demo/

status exits non-zero if any service is down or a port is held by a foreign listener, and it is safe to use as a monitoring probe.

Terminal window
$ ./ops/target/release/unidpp-stack down
==> console stopped (pid 1234)
==> archive stopped (pid 1235)
...
==> journals preserved (registry-journal.jsonl, run/*-journal.jsonl)

Stop never deletes state. The journals replay on the next start (unidpp-stack up).

Path What
registry-journal.jsonl the registry’s append-only journal (the seed of record)
jp-registry-journal.jsonl the JP peer’s journal
run/*-journal.jsonl trust, log, issuer, archive journals
run/archive-snapshots/ one AIP file per notarized snapshot
run/*.pid, run/*.log process handles and per-service logs
passports/ the projector’s passport document store
demo/ artifacts produced by unidpp-stack seed

The backup and restore page builds on exactly this file set.

The reference stack runs with no admin tokens and seeded-dev keyrings. Every mutation endpoint is open, and every signing key derives from documented development seeds. That is the correct posture for a demonstration pilot and the wrong posture for anything else; a real deployment sets admin tokens and production seeds in its operator manifest and environment. The whitelabel and sovereign tenants demonstrate the difference.