Demonstration of No-System-Channel Setup in Hyperledger Fabric v2.3

KC Tam
7 min readMar 9, 2021


Besides the ledger snapshot, Fabric v2.3 also introduced a new feature, bringing up application channels without system channel. The process is documented in details in the readthedoc. In this article I am using the configuration and script provided in Test Network and show what is needed to modify in order to bring up such a no-system-channel setup.


Prior to v2.3, we see two types of channels: system channel and application channel(s). System channel holds the consortium configuration, while all or part of the consortium members are joining various application channels according to the requirements. You may have seen that some configuration updates require the system channel. For example, adding a new organization into the consortium in order to join this organization to a new channel. For details you can see it in my previous article and some behaviour observation in this article.

The flow is like this. First create the genesis block for the system channel and let all orderers boot up with this genesis block. The system channel is now running in all orderers. Then create the genesis block for the application channel through configuration transaction. Finally join peers to the application channel. All orderers by default will also see this application channel.

There are many reasons shown in the readthedoc not to use system channel any more when building a fabric network. Application channel is good enough in daily use. In v2.3, the setup without system channel is introduced and this setup will be the direction in futures. In short, the system channel will no longer be needed.

In v2.3, The flow looks more simpler and straightforward. First create the genesis block for the application channel. Then join selected orderers and peers to the application channel.

In summary here is the difference in the flow.

System channel related steps (yellow) are not needed any more.

In this article we first observe what we have before by inspecting Test Network. The script in Test Network is not yet modified and therefore we can make observations on how the system channel looks like. Later we will make a demonstration of how to create a fabric setup with no system channel.

Observation Test Network with System Channel

Let us first examine a fabric network with the system channel, which is the only way a fabric network is created prior to v2.3.

We use the script to bring up the components (containers).

cd fabric-samples
cd test-network
./ up

We make an observation on the, in which we see a system channel only (system-channel).

docker exec ls /var/hyperledger/production/orderer/chains

Now we create an application channel, mychannel, with the script. After that we inspect the orderer again.

./ createChanneldocker exec ls /var/hyperledger/production/orderer/chains

We know everything works fine in Test Network. Therefore we are done with it here and shut down this setup.

./ down

Demonstration of No-System-Channel Setup

As mentioned above, we are leveraging most configurations in the Test Network. The process of this demonstration is

  1. duplicate the Test Network in another directory
  2. generate crypto material
  3. modify both the docker compose file
  4. bring up components
  5. add a profile for no-system-channel setup in channel configuration
  6. create genesis block for our application channel (mychannel)
  7. join orderer to mychannel
  8. join peers to mychannel
  9. test with SACC chaincode

1. Duplicate the Test Network for the demonstration

We duplicate the directory of Test Network test-network to demo-test-network. All demonstration happens in demo-test-network.

cd fabric-samples
cp -r test-network demo-test-network
cd demo-test-network

2. Generate crypto material using cryptogen

Leverage the directory structure of test-network and generate crypto material with cryptogen. The result is kept in organizations/ordererOrganizations and organizations/peerOrganizations.

Note: the result of using Fabric-CA is to create a similar directory structure. For sake of simplicity cryptogen is used.

// make sure fabric-samples/bin is included in PATH
export PATH=$PATH:${HOME}/fabric-samples/bin
cryptogen generate --config=./organizations/cryptogen/crypto-config-org1.yaml --output="organizations"cryptogen generate --config=./organizations/cryptogen/crypto-config-org2.yaml --output="organizations"cryptogen generate --config=./organizations/cryptogen/crypto-config-orderer.yaml --output="organizations"

3. Modify docker compose file

Similarly we make a copy of the docker/docker-compose-test-net.yaml to another file. We act on this file.

cd dockercp docker-compose-test-net.yaml docker-compose-no-system-channel.yaml

The only part we are modifying is In summary,

  • comment out the use of genesis file and the mapping of genesis file (line 8, 9 and 33)
  • set none bootstrap method (line 22)
  • add configuration for orderer admin (line 23–28)
  • allow orderer joining channel (line 29)
  • map the directory of orderer admin to container (line 36)
  • add mapping of admin port 7080 for accessing (line 40)

4. Bring up components

docker-compose -f docker/docker-compose-no-system-channel.yaml up -d

When orderer container is running, we can Inspect the channel now configured in the orderer. We see no system channel any more.

docker exec ls /var/hyperledger/production/orderer/chains

5. Add a profile for no-system-channel setup in channel configuration

The two existing profiles (TwoOrgsOrdererGenesis and TwoOrgsChannel) defined in configtx/configtx.yaml are for system channel. Here we add a profile SampleAppChannelEtcdRaft.

Profiles:    TwoOrgsOrdererGenesis:


<<: *ChannelDefaults
<<: *OrdererDefaults
- *OrdererOrg
<<: *OrdererCapabilities
<<: *ApplicationDefaults
- *Org1
- *Org2
<<: *ApplicationCapabilities

6. Prepare genesis block for mychannel

Instead of creating genesis block for system channel and configuration transaction, here we generate directly the genesis block for application channel (mychannel) with our new profile.

export FABRIC_CFG_PATH=../configcd configtx/
configtxgen -profile SampleAppChannelEtcdRaft -outputBlock mychannel.block -channelID mychannel

Go back to demo-test-network directory.

cd ..

7. Join orderer to mychannel

Now we are using the new binary osnadmin to handle the channel joining for the orderer.

First we inspect any channel configuration in the orderer.

osnadmin channel list -o localhost:7080 --ca-file ./organizations/ordererOrganizations/ --client-cert ./organizations/ordererOrganizations/\ --client-key ./organizations/ordererOrganizations/\
No system channel and application channels defined yet in the orderer.

Now join the orderer to mychannel.

osnadmin channel join --channel-id mychannel --config-block configtx/mychannel.block -o localhost:7080 --ca-file ./organizations/ordererOrganizations/ --client-cert ./organizations/ordererOrganizations/\ --client-key ./organizations/ordererOrganizations/\

Now we see mychannel in orderer, while there is still no system channel.

The orderer joins mychannel.

We see similar results while inspecting the orderer.

docker exec ls /var/hyperledger/production/orderer/chains

Now the orderer is already in mychannel. Peers can now join mychannel.

8. Join peers to mychannel

Prepare two terminals, with proper environment variables set such that commands are issued to and, respectively.

// for peer of org1
peer channel join -b configtx/mychannel.block
// for peer of org2
peer channel join -b configtx/mychannel.block
Join to mychannel
Join to mychannel

9. Test with SACC chaincode

We again leverage script which makes our life easier, as it completes the chaincode deployment with the lifecycle chaincode.

./ deployCC -ccn mycc -ccp ../chaincode/sacc -ccl go

We invoke the set function in Then check it with the get function in both peers.

In, set function is invoked and the result is queried properly with get function.

Terminal for

In we get the same result.

Terminal for

Now our demonstration completes. we can tear down everything.

docker-compose -f docker/docker-compose-no-system-channel.yaml down -v


In this article I have used Test Network to demonstrate how to build a fabric setup with no system channel. As this will be the direction in the long run, I am expecting the script will be updated in future versions. Nevertheless, hope this article gives you some hints how things are done in this setup.