A self-contained Fabric-X network for local development and testing.
Canonical source:
fabric-x-samples/devnet —
copy the entire devnet/ folder into your project to customize.
For a (distributed) production deployment, please refer to fabric-x-ansible-collection.
| Component | Count | Description |
|---|---|---|
| Orderer parties | 4 × 4 = 16 | Arma BFT consensus (Router, Batcher, Consenter, Assembler per party) |
| Committer stack | 6 per org | Verifier, Validator, Coordinator, Sidecar, Query Service, PostgreSQL |
| Organizations | Org1 + Org2 | Both orgs are in the genesis block; Org2 committer stack is optional |
| Orderer | Committer | Tools | PostgreSQL |
|---|---|---|---|
| v1.0.0 | v1.0.0 | v1.0.0 | 18.3-alpine3.23 |
make init # generate crypto and genesis block (run once, or after clean)
make start # start orderers + Org1 committer
make init-namespace # create the namespaceTeardown:
make stop # stop (volumes preserved)
make purge # stop and delete all volumesmake init # same init — crypto and genesis block are shared
make start-dev # start the all-in-one test committer
make init-namespace # same target — test-committer exposes the same service aliasesTeardown:
make stop-devfxconfig.yaml is identical for both modes. The test-committer answers on the same Docker
network aliases (orderer-party1-router, committer-query-service, committer-sidecar) as
the full-stack services, so applications need no changes when switching backends.
Delegate network lifecycle to devnet from your own Makefile (this assumes devnet to be a subfolder
of your project, and your application starting with its own compose.yaml):
DOCKER ?= docker
COMPOSE ?= docker compose
.PHONY: init start stop purge
init:
$(MAKE) -C devnet init
start:
$(MAKE) -C devnet start
$(MAKE) -C devnet init-namespace NS=myns POLICY="OR('Org1MSP.member')"
$(COMPOSE) up -d
stop:
$(COMPOSE) down
$(MAKE) -C devnet stop
purge:
$(COMPOSE) down
$(MAKE) -C devnet purgeYour compose.yaml joins the external network created by devnet:
services:
my-app:
# ...
networks:
- fabric-x
networks:
fabric-x:
external: trueAlternatively, pull the devnet services directly into your compose project:
include:
- path: ./devnet/compose.yaml
# - path: ./devnet/compose.org2.yaml # optional
services:
my-app:
# ...
networks:
- fabric-x
depends_on:
- committer-query-serviceRun make -C devnet init once, then docker compose up -d from your project root.
Run one of these after the network is up:
| Target | Policy |
|---|---|
make init-namespace-org1 |
AND('Org1MSP.member') |
make init-namespace-org2 |
AND('Org2MSP.member') |
make init-namespace |
AND('Org1MSP.member','Org2MSP.member') |
All targets are idempotent and work with both start and start-dev.
Override from the command line: make init-namespace-org1 NS=myns POLICY="AND('Org1MSP.member')".
make list-namespaces queries the query service and prints all installed namespaces — useful as a connectivity check in CI.
Org2 is in the genesis block and its crypto material is generated by make init.
make start starts only Org1 by default. To bring up both orgs:
make start-both # start orderers + Org1 and Org2 committersThe standard targets are optimized for Docker and Rancher Desktop. For rootless Podman,
two adjustments are needed because user namespace remapping makes user: "1000:1000" in
compose map to a host subUID rather than your user — causing permission errors on
host-owned files.
One-time setup — start the Podman socket (required by docker-compose):
systemctl --user enable --now podman.socketExport these variables once per shell session (or add to your shell profile):
export DOCKER=podman
export COMPOSE="podman compose"
export COMPOSE_OVERRIDE="-f compose.podman.yaml"
export RUN_AS=RUN_AS= (empty) skips --user on docker run commands; container UID 0 = your host user
in rootless Podman. compose.podman.yaml drops the user: directive from all compose services
for the same reason.
Then all standard targets work unchanged:
make init
make start
make init-namespace
make stop # or make purge| Service | Host port |
|---|---|
| Router (broadcast), parties 1-4 | 7050, 7150, 7250, 7350 |
| Assembler (deliver), parties 1-4 | 7053, 7153, 7253, 7353 |
| Committer Sidecar (Org1) | 4001 |
| Committer Query Service (Org1) | 7001 |
| Committer Sidecar (Org2) | 4002 |
| Committer Query Service (Org2) | 7002 |
| Test committer (dev) | 4001, 7001, 7050, 7053 |
.
├── crypto/ # generated by make init (gitignored)
├── config/ # node config files: party{1-4}-{role}.yaml + committer-*.yaml
├── .gitignore # ignores crypto/ and data/
├── compose.yaml # 4-party Arma BFT orderer, plus 1 committer organization
├── compose.org2.yaml # Org2 committer stack — optional, see below
├── compose.test-committer.yaml # all-in-one dev committer
├── crypto-config.yaml # cryptogen input — all the certificates for the network
├── configtx.yaml # channel topology and genesis block profile
├── shared_config.yaml # Arma BFT party configuration
├── fxconfig.yaml # client connection config — same file for both modes
└── Makefile