This document will describe about the detail of each configuration:
-
Modify
app/explorerconfig.json
to update PostgreSQL database settings."postgreSQL": { "host": "127.0.0.1", "port": "5432", "database": "fabricexplorer", "username": "hppoc", "passwd": "password" }
-
Another alternative to configure database settings is to use environment variables, example of settings:
export DATABASE_HOST=127.0.0.1 export DATABASE_PORT=5432 export DATABASE_DATABASE=fabricexplorer export DATABASE_USERNAME=hppoc export DATABASE_PASSWD=pass12345
-
Modify
app/explorerconfig.json
to update Authorization (JWT) settings."jwt": { "secret" : "a secret phrase!!", "expiresIn": "2 days" }
secret
: secret string to sign the payload.expiresIn
: expressed in seconds or a string describing a time span zeit/ms. Eg:60
,"2 days"
,"10h"
,"7d"
. A numeric value is interpreted as a seconds count. If you use a string be sure you provide the time units (days, hours, etc), otherwise milliseconds unit is used by default ("120"
is equal to"120ms"
).
-
Modify the connection profile (e.g.
app/platform/fabric/connection-profile/test-network.json
) to configure authorization of login user."client": { "adminCredential": { "id": "exploreradmin", "password": "exploreradminpw" }, "enableAuthentication": true,
adminCredential.id
is the the admin user to login Explorer. Currently Explorer only supports single user mode (can't add more users. We're working on it)adminCredential.password
is the password for the admin user to login Explorer.enableAuthentication
is a flag to enable authentication using a login page, setting to false will skip authentication.- Even if disable user authentication, you still need to get
adminCredential.id
specified, because it's used to get access to the wallet.
- Even if disable user authentication, you still need to get
- If you want to disable login authentication, set
false
toenableAuthentication
in the connection profile"client": { "enableAuthentication": false }
-
Only admin and users who has admin roles can register a new user.
-
admin user can register a user who has
admin
oruser
rolesuser
roles doesn't include a privilege to manipulate user
-
If multiple profiles are configured, user information of each profile is completely isolated.
- e.g. Admin of org1-network can't manipulate user of org2-network.
-
There are 2 ways to register a new user to Explorer. You can do that via GUI or Web API.
-
Web API First you need to login using admin credential to get a JSON Web token.
$ curl -s --location --request POST 'localhost:8080/auth/login' \ --header 'Content-Type: application/json' --data-raw '{ "user": "exploreradmin", "password": "exploreradminpw", "network": "test-network" }' | jq . { "success": true, "message": "You have successfully logged in!", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiZXhwbG9yZXJhZG1pbiIsIm5ldHdvcmsiOiJmaXJzdC1uZXR3b3JrIiwiaWF0IjoxNTk3MTMyMTY0LCJleHAiOjE1OTcxMzkzNjR9.5Z9nyQi93fsKNV9Y7RgAXaXKds70fivZOVAEefHzlx4", "user": { "message": "logged in", "name": "exploreradmin" } }
Then post a request for registering a new user with the retrieved token and mandatorily required parameters.
$ curl -s --location --request POST 'localhost:8080/api/register' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer eyJheyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiZXhwbG9yZXJhZG1pbiIsIm5ldHdvcmsiOiJmaXJzdC1uZXR3b3JrIiwiaWF0IjoxNTk3MTMyMTY0LCJleHAiOjE1OTcxMzkzNjR9.5Z9nyQi93fsKNV9Y7RgAXaXKds70fivZOVAEefHzlx4' \ --data-raw '{ "user": "newuser", "password": "newuser", "roles": "user" }' | jq . { "status": 200 }
-
Anyone can request this Web API after sing in Explorer dashboard.
-
You can list registered user via Web API (GUI for this operation has not been supported yet).
$ curl -s --location --request GET 'localhost:8080/api/userlist' \ --header 'conten: application/json' \ --header 'Authorization: Bearer eyJheyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiZXhwbG9yZXJhZG1pbiIsIm5ldHdvcmsiOiJmaXJzdC1uZXR3b3JrIiwiaWF0IjoxNTk3MTMyMTY0LCJleHAiOjE1OTcxMzkzNjR9.5Z9nyQi93fsKNV9Y7RgAXaXKds70fivZOVAEefHzlx4' \ | jq . { "status": 200, "message": [ { "username": "exploreradmin", "email": null, "networkName": "test-network", "firstName": null, "lastName": null, "roles": "admin" }, { "username": "newuser", "email": null, "networkName": "test-network", "firstName": null, "lastName": null, "roles": "user" } ] }
- Root admin user can't be unregistered
- It's not allowed to unregister user who's sending this request itself
- You can unregister user via Web API (GUI for this operation has not been supported yet).
$ curl -s --location --request POST 'localhost:8080/api/unregister' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer eyJheyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiZXhwbG9yZXJhZG1pbiIsIm5ldHdvcmsiOiJmaXJzdC1uZXR3b3JrIiwiaWF0IjoxNTk3MTMyMTY0LCJleHAiOjE1OTcxMzkzNjR9.5Z9nyQi93fsKNV9Y7RgAXaXKds70fivZOVAEefHzlx4' \
--data-raw '{
"user": "newuser"
}' | jq .
{
"status": 200,
"message": "Unregistered successfully!"
}
-
If your fabric network enables TLS, then set
true
toclient.tlsEnable
in the connection profile (e.g.app/platform/fabric/connection-profile/test-network.json
). And you also need to specify peer URL withgrpcs://
. If your fabrice network disables TLS, usegrpc://
instead."client": { "tlsEnable": true,
"peers": { "peer0.org1.example.com": { "url": "grpcs://localhost:7051",
-
Modify
app/platform/fabric/config.json
to define your fabric network connection profile:{ "network-configs": { "test-network": { "name": "Test Network", "profile": "./connection-profile/test-network.json" } }, "license": "Apache-2.0" }
test-network
is the name of your connection profile, and can be changed to any name.name
is a name you want to give to your fabric network, you can change only value of the key "name".profile
is the location of your connection profile, you can change only value of the key "profile"- Change
fabric-path
to your fabric network disk path in thetest-network.json
file - Provide the full disk path to the adminPrivateKey config option, it ussually ends with "_sk"
e.g.or Provide the pem string instead."adminPrivateKey": { "path": "/opt/dev/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/users/[email protected]/msp/keystore/aaacd899a6362a5c8cc1e6f86d13bfccc777375365bbda9c710bb7119993d71c_sk" },
"adminPrivateKey": { "pem": "-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMG ... utE5HtrGM\n-----END PRIVATE KEY-----\n" },
- You need to specify the following keys in the connection profile for using Fabric CA to retrieve certificate:
-
client.caCredential
- id
- passowrd
-
client.adminCredential
- affiliation
-
organizations.[org name]
- certificateAuthorities
"client": { "tlsEnable": true, "caCredential": { "id": "admin", "password": "adminpw" }, "adminCredential": { "id": "exploreradmin", "password": "exploreradminpw", "affiliation": "org1.department1" }, "enableAuthentication": true,
"organizations": { "org1": { "mspid": "Org1ExampleCom", "peers": ["peer0-org1"], "certificateAuthorities": ["ca0"] } },
-
Refer to the following sample connection files:
examples/net1/connection-profile/test-network-ca.json
(for using Docker)- To use this profile, modify
docker-compose.yaml
as below:diff --git a/docker-compose.yaml b/docker-compose.yaml index 9478ca1..ea6ae74 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -46,7 +46,7 @@ services: - LOG_CONSOLE_STDOUT=true - DISCOVERY_AS_LOCALHOST=false volumes: - - ./examples/net1/config.json:/opt/explorer/app/platform/fabric/config.json + - ./examples/net1/config-ca.json:/opt/explorer/app/platform/fabric/config.json - ./examples/net1/connection-profile:/opt/explorer/app/platform/fabric/connection-profile - /fabric-path/fabric-samples/test-network/organizations:/tmp/crypto - walletstore:/opt/explorer/wallet
- To use this profile, modify
app/platform/fabric/connection-profile/test-network-ca.json
(for using source tree)- To use this profile, modify
app/platform/fabric/config.json
as below:diff --git a/app/platform/fabric/config.json b/app/platform/fabric/config.json index f99d37b..9825060 100644 --- a/app/platform/fabric/config.json +++ b/app/platform/fabric/config.json @@ -2,7 +2,7 @@ "network-configs": { "test-network": { "name": "Test Network", - "profile": "./connection-profile/test-network.json" + "profile": "./connection-profile/test-network-ca.json" } }, "license": "Apache-2.0"
- To use this profile, modify
-
- You need to specify the following keys:
- organizations.[org name]
- adminPrivateKey
- signedCert
"client": { "tlsEnable": true, "adminCredential": { "id": "exploreradmin", "password": "exploreradminpw", }, "enableAuthentication": true,
"organizations": { "org1": { "mspid": "Org1ExampleCom", "adminPrivateKey": { "path": "[path to private key]" }, "peers": ["peer0-org1"], "signedCert": { "path": "[path to cert]" } } },
- organizations.[org name]
- When you set an identity label to
clientTlsIdentity
in the connection profile and store identity, which is correspondent with it, into the wallet (EXPLORER_ROOTDIR/wallet
), client TLS (mutual TLS) is enabled."client": { "clientTlsIdentity": "clientTlsId" }
-
You can also configure multiple profiles in
app/platform/fabric/config.json
for monitoring multiple organizations in a single Explorer instance. It's quite straightforward. You just need to prepare config.json as below and connection profile for each organization (e.g.org1-network.json
&org2-network.json
). Note that you need to initialize your backend database once when applying v1.0.0-rc3 and above first time in your local environment. Because we've changed database schema in backend database since this version.{ "network-configs": { "org1-network": { "name": "org1-network", "profile": "./connection-profile/org1-network.json" }, "org2-network": { "name": "org2-network", "profile": "./connection-profile/org2-network.json" } }, "license": "Apache-2.0" }
- Configure Hyperledger Explorer for HTTPS based on this link CONFIG-HTTPS-HLEXPLORER.md
- Modify
app/explorerconfig.json
to update sync properties - Please restart Explorer if any changes made to explorerconfig.json
- Ensure same configuration in Explorer explorerconfig.json if sync process is running from different locations
"sync": {
"type": "host",
"platform": "fabric",
"blocksSyncTime": "1"
},
"sync": {
"type": "local",
"platform": "fabric",
"blocksSyncTime": "1"
},
sync
: sync type.local
(run with Explorer) orhost
(standalone)platform
: platform nameblocksSyncTime
: sync interval in minute
-
By using the following environmet variables, you can control log level of each component (app, db and console). You can set these
ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < MARK < OFF
string to each level. Each file is rolled by both date (7days) and size (8MB).- LOG_LEVEL_APP
- Log level regarding application layer. The logs are written to
logs/app/app.log
. - default
DEBUG
- Log level regarding application layer. The logs are written to
- LOG_LEVEL_DB
- Log level regarding backend layer. The logs are written to
logs/db/db.log
. - default
DEBUG
- Log level regarding backend layer. The logs are written to
- LOG_LEVEL_CONSOLE
- Log level regarding console. The logs are written to
logs/console/console.log
. - default
INFO
- Log level regarding console. The logs are written to
- LOG_CONSOLE_STDOUT
- You can switch the destination of console log from file to standard output.
- default
false
- LOG_LEVEL_APP
- Modify an example of
docker-compose.yaml
to align with your environment- networks > mynetwork.com > external > name
networks: mynetwork.com: external: name: net_byfn
- services > explorer.mynetwork.com > volumes
- Connection config file path (ex. ./examples/net1/config.json)
- Connection profile directory path (ex. ./examples/net1/connection-profile, which is referred from config.json)
- Directory path for crypto artifacts of fabric network (ex. ./examples/net1/crypto)
volumes: - ./examples/net1/config.json:/opt/explorer/app/platform/fabric/config.json - ./examples/net1/connection-profile:/opt/explorer/app/platform/fabric/connection-profile - ./examples/net1/crypto:/tmp/crypto
- When you connect the explorer to your fabric network through bridge network, you need to set
DISCOVERY_AS_LOCALHOST
tofalse
for disabling hostname mapping intolocalhost
.explorer.mynetwork.com: ... environment: ... - DISCOVERY_AS_LOCALHOST=false
- In this docker-compose.yaml, two named volumes are allocated for persistent data (for Postgres data and user wallet), if you would like to clear these named volumes, run the following:
docker-compose down -v
- networks > mynetwork.com > external > name
-
By default, the value of each read/write set is encoded by UTF-8. If you want to change the type of encoding, you can configure with the following property in the connection profile. Please refer to Buffer | Node.js v14.7.0 Documentation for the supported encoding.
"client": { "rwSetEncoding": "hex" }
- By putting a proxy server (NGINX server), you can change domain that users access. (e.g. change from
http://my.example.com
tohttp://my.example.com/explorer
.- First, prepare configuration file
nginx_subdomain.conf
on root directory of explorer project for NGINX server as follow.server { location /explorer/ { proxy_pass http://explorer.mynetwork.com:8080/; } location / { proxy_pass http://explorer.mynetwork.com:8080/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_set_header Host $host; } }
- Add a service of proxy server to
docker-compose.yaml
diff --git a/docker-compose.yaml b/docker-compose.yaml index 9478ca1..a0c9d03 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -57,3 +57,14 @@ services: condition: service_healthy networks: - mynetwork.com + + my-custom-nginx-container: + image: nginx:latest + container_name: my-custom-nginx-container + hostname: my-custom-nginx-container + volumes: + - ./nginx_subdomain.conf:/etc/nginx/conf.d/default.conf + ports: + - 80:80 + networks: + - mynetwork.com
- Start the proxy server with
docker-compose up -d
and accesshttp://localhost/explorer
.
- First, prepare configuration file