Setup Your Private Ethereum Network With Geth

The enterprise blockchain market is huge, and there are different solutions available to implement blockchain for enterprise -- Hyperledger, Corda, and Ethereum are the well-known providers. You can set up enterprise blockchain in different ways, on a cloud, or on-premise. Here in this post, we'll learn how you can setup a private ethereum blockchain on your server.

OS and Software

  • OS: Ubutu 16.04 server
  • Software: Geth Version: 1.9.18-stable

Validator nodes

We will use proof of authority (PoA) consensus to setup the private network. In PoA-based networks, transactions and blocks are validated by approved accounts, known as validators or sealer. The process is automated and does not require validators to be constantly monitoring their computers.

PoA algorithms rely on a set of N trusted nodes called the authorities. We'll create three sealer nodes to validate the transactions.

Types of Nodes in PoA NetworkValidator/Authority - Validate, confirm transactions, and add new blocks into blockchain.

  • Full Node - This node keeps a copy of the full blockchain.

Here is the structure we'll build in this tutorial. A full template can be found from the attachment of this article.  

├── accounts.txt    
├── genesis.json    
├── node1    
│   ├── geth    
│   ├── keystore    
│   ├──    
│   ├── password.txt    
│   └── static-nodes.json    
├── node2    
│   ├── geth    
│   ├── keystore    
│   ├──    
│   ├── password.txt    
│   └── static-nodes.json    
└── node3    
    ├── geth    
    ├── keystore    
    ├── password.txt    
    └── static-nodes.json

Create a main directory

$ mkdir blockchain    
$ cd blockchain    
blockchain$ mkdir node1 node2 node3  

Create validator accounts

The account required public-private keys to interact with the blockchain. Hence we need to create new accounts for validators.

Node 1

blockchain$ geth --datadir node1/ account new    
Your new account is locked with a password. Please give a password. Do not forget this password.    
Repeat password:    
Your new key was generated    
Public address of the key:   0x5D9DD2d7ea19D886F6D69c7E14e4F4Eeb922F8d4    
Path of the secret key file: node1/keystore/UTC--2020-07-29T15-48-00.687512615Z--5d9dd2d7ea19d886f6d69c7e14e4f4eeb922f8d4

Node 2

blockchain$ geth --datadir node2/ account new    
Your new account is locked with a password. Please give a password. Do not forget this password.    
Repeat password:    
Your new key was generated    
Public address of the key:   0x80051706C32359A75389EA36dDEbA2159067C360    
Path of the secret key file: node2/keystore/UTC--2020-07-29T15-54-17.548848773Z--80051706c32359a75389ea36ddeba2159067c360

Node 3

blockchain$ geth --datadir node3/ account new    
Your new account is locked with a password. Please give a password. Do not forget this password.    
Repeat password:    
Your new key was generated    
Public address of the key:   0xf189Ee2c9b61487Fe26C72b8a0ba52f453E71c25    
Path of the secret key file: node3/keystore/UTC--2020-07-29T15-56-15.523088698Z--f189ee2c9b61487fe26c72b8a0ba52f453e71c25

Note that keystore files automatically generated inside node folders, and keystore files can be found inside the keystore directory.

Save Credentials

For future use, we'll copy these three wallet address to a text file.

blockchain$ echo '0x5D9DD2d7ea19D886F6D69c7E14e4F4Eeb922F8d4' >> accounts.txt
blockchain$ echo '0x80051706C32359A75389EA36dDEbA2159067C360' >> accounts.txt
blockchain$ echo '0xf189Ee2c9b61487Fe26C72b8a0ba52f453E71c25' >> accounts.txt

To make the process easier, save the password of each node to the respective folder.

blockchain$ echo 'pwd@node1' > node1/password.txt
blockchain$ echo 'pwd@node2' > node2/password.txt
blockchain$ echo 'pwd@node3' > node2/password.txt 

Create your Genesis file

Geth comes with different tools included; if you're using tar file, you need to install it separately. Puppeth is a tool to create a new genesis file by selecting different options.

blockchain$ puppeth

Specify the chain id

Please specify a network name to administer (no spaces, hyphens or capital letters please)
> 1515

As we want to generate a new genesis file, choose the first option.  

What would you like to do? (default = create)    
 1. Create new genesis from scratch    
 2. Import already existing genesis    
> 1  

Select proof-of-authority. 

Which consensus engine to use? (default = clique)    
 1. Ethash - proof-of-work    
 2. Clique - proof-of-authority    
> 2    

For the fast transaction, hence provide 1 second. 

How many seconds should blocks take? (default = 15)    
> 1 

Provide accounts created previously 

Which accounts are allowed to seal? (mandatory at least one)    
> 0x5D9DD2d7ea19D886F6D69c7E14e4F4Eeb922F8d4    
> 0x80051706C32359A75389EA36dDEbA2159067C360    
> 0xf189Ee2c9b61487Fe26C72b8a0ba52f453E71c25    
> 0x 

Provide accounts to get some free ethers  

Which accounts should be pre-funded? (advisable at least one)    
> 0x5D9DD2d7ea19D886F6D69c7E14e4F4Eeb922F8d4    
> 0x80051706C32359A75389EA36dDEbA2159067C360    
> 0xf189Ee2c9b61487Fe26C72b8a0ba52f453E71c25    
> 0x
Should the precompile-addresses (0x1 .. 0xff) be pre-funded with 1 wei? (advisable yes)    
> yes  
Specify your chain/network ID if you want an explicit one (default = random)    
> 1515 
Configured new genesis block 

The genesis block is configured, now we need to export the configuration into a file. 

What would you like to do? (default = stats)    
 1. Show network stats    
 2. Manage existing genesis    
 3. Track new remote server    
 4. Deploy network components    
> 2
1. Modify existing configurations    
2. Export genesis configurations    
3. Remove genesis configuration    
> 2
Which folder to save the genesis specs into? (default = current)    
  Will create 1515.json, 1515-aleth.json, 1515-harmony.json, 1515-parity.json    
> // enter to create in existing folder   
INFO [07-29|16:33:29.147] Saved native genesis chain spec path=1515.json  
ERROR[07-29|16:33:29.147] Failed to create Aleth chain spec err="unsupported consensus engine"  
ERROR[07-29|16:33:29.147] Failed to create Parity chain spec err="unsupported consensus engine"  
INFO [07-29|16:33:29.149] Saved genesis chain spec client=harmony path=1515-harmony.json
What would you like to do? (default = stats)    
 1. Show network stats    
 2. Manage existing genesis    
 3. Track new remote server    
 4. Deploy network components    
> ^C //ctrl+C to quit puppeth

You should see the 1515.json created inside blockchain folder, rename it to genesis.json and delete the generated file that ends in -harmony.json.

Modify the Genesis file 

Set block sealing period to 0, this will automatically force geth to only create a new block whenever there is a transaction in the network.

"clique": {    
      "period": 0,    
      "epoch": 30000    

Initialize the Nodes

Each node must initialize with the same genesis file. 

blockchain$ geth --datadir node1/ init genesis.json  
blockchain$ geth --datadir node2/ init genesis.json  
blockchain$ geth --datadir node3/ init genesis.json 

Run the Nodes

We'll run node using geth with different available options. For reusable purposes, you can create a shell script. Put all the options you want to enable in one huge command.

Go inside the node1 directory and run the command.  

blockchain/node1$geth --nousb --datadir=$pwd --syncmode 'full' --port 30310 --miner.gasprice 0 --miner.gastarget 470000000000 --http --http.addr 'localhost' --http.port 8545 --http.api admin,eth,miner,net,txpool,personal,web3 --mine --allow-insecure-unlock --unlock "0x5D9DD2d7ea19D886F6D69c7E14e4F4Eeb922F8d4" --password password.txt  
  • --nousb Disables monitoring for and managing USB hardware wallets.
  • --datadir=$pwd Data directory for the databases and keystore.
  • --syncmode 'full' Enables full chain sync (default: "fast").
  • --port 3030 assign port geth process.
  • --miner.gasprice 0 On private network we don't want to pay anything, so make it zero.
  • --miner.gastarget 470000000000 use same as the genesis file. However, actual gaslimit is dynamic for new block and depends on the previous block.
  • --http Enable the HTTP-RPC server.
  • --http.addr 'localhost' HTTP-RPC server listening interface (default: "localhost").
  • --http.port 8545 HTTP-RPC server listening port (default: 8545).
  • --http.api Buch of apis to be used over RPC calls.
  • --mine Enable mining.
  • --allow-insecure-unlock Allow insecure account unlocking when account-related RPCs are exposed by http.
  • --unlock "0x251B7dC42D7472314fE4d6c3b9CAD2fb5927d7c8" Account to unlock, we'll use the address of node1.
  • --password password.txt Password file to use for non-interactive password input

Additional Parameters

  • --rpccorsdomain "*" Comma separated list of domains from which to accept cross origin requests (browser enforced).
  • --rpcvhosts="*" Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.
  • --miner.threads value Number of CPU threads to use for mining (default: 0).

When you run the node, you will find the enode in the log, copy that enode and keep it with you.

Node 1 


Node 2

blockchain/node2$geth --nousb --datadir=$pwd --syncmode 'full' --port 30311 --miner.gasprice 0 --miner.gastarget 470000000000 --http --http.addr 'localhost' --http.port 8546 --http.api admin,eth,miner,net,txpool,personal,web3 --mine --allow-insecure-unlock --unlock "0x80051706C32359A75389EA36dDEbA2159067C360" --password password.txt  

Enode for node2


Node 3

blockchain/node3$geth --nousb --datadir=$pwd --syncmode 'full' --port 30312 --miner.gasprice 0 --miner.gastarget 470000000000 --http --http.addr 'localhost' --http.port 8547 --http.api admin,eth,miner,net,txpool,personal,web3 --mine --allow-insecure-unlock --unlock "0xf189Ee2c9b61487Fe26C72b8a0ba52f453E71c25" --password password.txt  

Enode for node3


Now you have all three enodes, we'll use this to connect all the nodes.

Prepare static-nodes.json file

Geth has a different feature to connect to the network, we'll use static nodes. It generally used when you know the peers and we always want to connect with them.\

Crate static-nodes.json in node1 and add values of enodes as follows,

blockchain/node1$touch static-nodes.json

Add all three enodes into it. 


Copy that json file to other nodes. 

blockchain/node1$cp static-nodes.json /home/dmdesai/blockchain/node2/    
blockchain/node1$cp static-nodes.json /home/dmdesai/blockchain/node3/  

Start all the nodes

To make the process simpler, create a shall script file and paste a huge command into it.  

nohup geth --nousb --datadir=$pwd --syncmode 'full' --port 30310 --miner.gasprice 0 --miner.gastarget 470000000000 --http --http.addr 'localhost' --http.port 8545 --http.api admin,eth,miner,net,txpool,personal,web3 --mine --allow-insecure-unlock --unlock "0x5D9DD2d7ea19D886F6D69c7E14e4F4Eeb922F8d4" --password password.txt &    
echo "Geth started on node 1"

Repeat this process for node2 and node3, then run the script file for each. 


Attach Geth with the following command 

blockchain/node1$ geth attach geth.ipc  
Welcome to the Geth JavaScript console!  
instance: Geth/v1.9.18-stable-f5382591/linux-amd64/go1.14.2  
coinbase: 0x5d9dd2d7ea19d886f6d69c7e14e4f4eeb922f8d4  
at block: 0 (Wed Jul 29 2020 16:30:59 GMT+0000 (UTC))  
datadir: /home/rsa-key-20200717/blockchain/node1  
modules: admin:1.0 clique:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0  

Check if the other two nodes are connected or not. It should show the peer count 2. 

> net.peerCount    

Your private blockchain is ready! You can make a transaction on one node, and it will be synced with the connected peers.

Stop the nodes

$ ps ax | grep geth
$ kill <process id>  

$ kill -9 <process id> //kill the process forcefully

What’s next ?

We will see how you can connect nodes of different servers, so even if one server is down, the second one can process transactions.



Similar Articles