Skip to content

Latest commit

 

History

History

README.md

Fabric-X devnet

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.

What's included

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

Version compatibility

Orderer Committer Tools PostgreSQL
v1.0.0 v1.0.0 v1.0.0 18.3-alpine3.23

Quick start

Full stack (production-like)

make init                # generate crypto and genesis block (run once, or after clean)
make start               # start orderers + Org1 committer
make init-namespace      # create the namespace

Teardown:

make stop                # stop (volumes preserved)
make purge               # stop and delete all volumes

Dev mode (single container, includes built-in orderer)

make 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 aliases

Teardown:

make stop-dev

fxconfig.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.

Using this network in your project

Makefile (recommended)

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 purge

Your compose.yaml joins the external network created by devnet:

services:
  my-app:
    # ...
    networks:
      - fabric-x

networks:
  fabric-x:
    external: true

Docker Compose include (requires Compose v2.20+)

Alternatively, 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-service

Run make -C devnet init once, then docker compose up -d from your project root.

Namespace init targets

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.

Running Org2's committer stack

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 committers

Rootless Podman

The 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.socket

Export 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

Port reference

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

Directory layout

.
├── 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