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 Network

  • Validator/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.  
  1. blockchain    
  2. ├── accounts.txt    
  3. ├── genesis.json    
  4. ├── node1    
  5. │   ├── geth    
  6. │   ├── keystore    
  7. │   ├──    
  8. │   ├── password.txt    
  9. │   └── static-nodes.json    
  10. ├── node2    
  11. │   ├── geth    
  12. │   ├── keystore    
  13. │   ├──    
  14. │   ├── password.txt    
  15. │   └── static-nodes.json    
  16. └── node3    
  17.     ├── geth    
  18.     ├── keystore    
  19.     ├──        
  20.     ├── password.txt    
  21.     └── static-nodes.json  
Create a main directory
  1. mkdir blockchain    
  2. $ cd blockchain    
  4. 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
  1. blockchain$ geth --datadir node1/ account new    
  3. Your new account is locked with a password. Please give a password. Do not forget this password.    
  4. Password:    
  5. Repeat password:    
  7. Your new key was generated    
  9. Public address of the key:   0x5D9DD2d7ea19D886F6D69c7E14e4F4Eeb922F8d4    
  10. Path of the secret key file: node1/keystore/UTC--2020-07-29T15-48-00.687512615Z--5d9dd2d7ea19d886f6d69c7e14e4f4eeb922f8d4    
Node 2
  1. blockchain$ geth --datadir node2/ account new    
  3. Your new account is locked with a password. Please give a password. Do not forget this password.    
  4. Password:    
  5. Repeat password:    
  7. Your new key was generated    
  9. Public address of the key:   0x80051706C32359A75389EA36dDEbA2159067C360    
  10. Path of the secret key file: node2/keystore/UTC--2020-07-29T15-54-17.548848773Z--80051706c32359a75389ea36ddeba2159067c360    
Node 3
  1. blockchain$ geth --datadir node3/ account new    
  3. Your new account is locked with a password. Please give a password. Do not forget this password.    
  4. Password:    
  5. Repeat password:    
  7. Your new key was generated    
  9. Public address of the key:   0xf189Ee2c9b61487Fe26C72b8a0ba52f453E71c25    
  10. 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.
  1. blockchain$ echo '0x5D9DD2d7ea19D886F6D69c7E14e4F4Eeb922F8d4' >> accounts.txt
  2. blockchain$ echo '0x80051706C32359A75389EA36dDEbA2159067C360' >> accounts.txt
  3. blockchain$ echo '0xf189Ee2c9b61487Fe26C72b8a0ba52f453E71c25' >> accounts.txt
To make the process easier, save the password of each node to the respective folder.
  1. blockchain$ echo 'pwd@node1' > node1/password.txt
  2. blockchain$ echo 'pwd@node2' > node2/password.txt
  3. 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.
  1. blockchain$ puppeth
Specify the chain id
  1. Please specify a network name to administer (no spaces, hyphens or capital letters please)
  2. > 1515
As we want to generate a new genesis file, choose the first option.  
  1. What would you like to do? (default = create)    
  2.  1. Create new genesis from scratch    
  3.  2. Import already existing genesis    
  4. 1  
Select proof-of-authority. 
  1. Which consensus engine to use? (default = clique)    
  2.  1. Ethash - proof-of-work    
  3.  2. Clique - proof-of-authority    
  4. 2    
For the fast transaction, hence provide 1 second. 
  1. How many seconds should blocks take? (default = 15)    
  2. 1  
Provide accounts created previously 
  1. Which accounts are allowed to seal? (mandatory at least one)    
  2. 0x5D9DD2d7ea19D886F6D69c7E14e4F4Eeb922F8d4    
  3. 0x80051706C32359A75389EA36dDEbA2159067C360    
  4. 0xf189Ee2c9b61487Fe26C72b8a0ba52f453E71c25    
  5. > 0x  
Provide accounts to get some free ethers  
  1. Which accounts should be pre-funded? (advisable at least one)    
  2. > 0x5D9DD2d7ea19D886F6D69c7E14e4F4Eeb922F8d4    
  3. > 0x80051706C32359A75389EA36dDEbA2159067C360    
  4. > 0xf189Ee2c9b61487Fe26C72b8a0ba52f453E71c25    
  5. > 0x     
  1. Should the precompile-addresses (0x1 .. 0xff) be pre-funded with 1 wei? (advisable yes)    
  2. yes   
  1. Specify your chain/network ID if you want an explicit one (default = random)    
  2. 1515 
  3. Configured new genesis block 
The genesis block is configured, now we need to export the configuration into a file. 
  1. What would you like to do? (default = stats)    
  2.  1. Show network stats    
  3.  2. Manage existing genesis    
  4.  3. Track new remote server    
  5.  4. Deploy network components    
  6. 2    
  1. 1. Modify existing configurations    
  2. 2. Export genesis configurations    
  3. 3. Remove genesis configuration    
  4. 2       
  1. Which folder to save the genesis specs into? (default = current)    
  2.   Will create 1515.json, 1515-aleth.json, 1515-harmony.json, 1515-parity.json    
  3. // enter to create in existing folder   
  5. INFO [07-29|16:33:29.147] Saved native genesis chain spec path=1515.json  
  6. ERROR[07-29|16:33:29.147] Failed to create Aleth chain spec err="unsupported consensus engine"  
  7. ERROR[07-29|16:33:29.147] Failed to create Parity chain spec err="unsupported consensus engine"  
  8. INFO [07-29|16:33:29.149] Saved genesis chain spec client=harmony path=1515-harmony.json   
  1. What would you like to do? (default = stats)    
  2.  1. Show network stats    
  3.  2. Manage existing genesis    
  4.  3. Track new remote server    
  5.  4. Deploy network components    
  7. > ^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.
  1. "clique": {    
  2.       "period": 0,    
  3.       "epoch": 30000    
  4.     }    
Initialize the Nodes
Each node must initialize with the same genesis file. 
  1. blockchain$ geth --datadir node1/ init genesis.json  
  2. blockchain$ geth --datadir node2/ init genesis.json  
  3. 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.  
  1. 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 
  1. enode://e832f6b25b2025ecb8a192439255557944a5e1c12175f72a7f1b79de811b94f3f11f930d9dcbf0389429ecba579856185f231930fbaf86a09d1b8c8071555f8e@   
Node 2
  1. 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
  1. enode://0142f6ce892526b3c3a99fa986e5f58770ddddec88a8a0752542469006cac9dcd364386f8ce31ac2fe3fb58e5583108df21df4dd20497ab2a25b7056a60ae964@    
Node 3
  1. 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
  1. enode://6948ac526196e3b0e71bf6718a83924d5471aaae1e763a66a0a615eb92b3ee62c1fbb896553e1187f1012cb11b0d154d431c77d3fe2489c6452b47cb113c98ce@   
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,
  1. blockchain/node1$touch static-nodes.json    
Add all three enodes into it. 
  1. [       
  2.   "enode://e832f6b25b2025ecb8a192439255557944a5e1c12175f72a7f1b79de811b94f3f11f930d9dcbf0389429ecba579856185f231930fbaf86a09d1b8c8071555f8e@",    
  4.   "enode://0142f6ce892526b3c3a99fa986e5f58770ddddec88a8a0752542469006cac9dcd364386f8ce31ac2fe3fb58e5583108df21df4dd20497ab2a25b7056a60ae964@",    
  6.   "enode://6948ac526196e3b0e71bf6718a83924d5471aaae1e763a66a0a615eb92b3ee62c1fbb896553e1187f1012cb11b0d154d431c77d3fe2489c6452b47cb113c98ce@"    
  7. ]   
Copy that json file to other nodes. 
  1. blockchain/node1$cp static-nodes.json /home/dmdesai/blockchain/node2/    
  2. 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.  
  1. blockchain/node1$touch  
  1. 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 &    
  3. echo "Geth started on node 1"  
Repeat this process for node2 and node3, then run the script file for each. 
  1. blockchain/node1$sh    
  2. blockchain/node2$sh     
  3. blockchain/node3$sh    
Attach Geth with the following command 
  1. blockchain/node1$ geth attach geth.ipc  
  3. Welcome to the Geth JavaScript console!  
  4. instance: Geth/v1.9.18-stable-f5382591/linux-amd64/go1.14.2  
  5. coinbase: 0x5d9dd2d7ea19d886f6d69c7e14e4f4eeb922f8d4  
  6. at block: 0 (Wed Jul 29 2020 16:30:59 GMT+0000 (UTC))  
  7. datadir: /home/rsa-key-20200717/blockchain/node1  
  8. 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  
  9. >  
Check if the other two nodes are connected or not. It should show the peer count 2. 
  1. > net.peerCount    
  2. 2  
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
  1. $ ps ax | grep geth
  3. $ kill <process id>  

  4. $ 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.