Two-Node Setup of a Private Ethereum on AWS with Contract Deployment (Part 1)

From time to time I plan to emulate an Ethereum environment. The idea behind is to observe how Ethereum nodes work to each other, and how different accounts interact in transaction and contract deployment. For testing, most contract deployment example nowadays is mainly on testrpc or testnet, but how the contract works among nodes is still new to me.

I deploy this two-node setup on AWS. As I do not use any special features on AWS, it should be applicable to another cloud environment.

My setup is inspired by the work from JJ’s World (link), and after testing this for several times with modification, I document the whole process I have done, and share some experience here about the whole process.

I also use the Voting contract developed by Mahesh Murthy (link). This is a simple contract that best illustrates how a contract works in the chain.

This by no means is a detailed step-by-step guide. I omit certain steps and make reference to some work done by others. For example, the detailed operation of AWS EC2, including launching a new instance with a setup like access key, security group, etc. can be found here (link).


Read Part Two Here


There are two parts in this setup.

Part 1: Create a 2-node Ethereum network with private blockchain, and accounts on the two nodes can send ether to each other.

Part 2: Deploy a contract from one node, and both accounts can access and execute functions on this contract.


Step 1: Launch two EC2 instances.


Use t2.medium (2 vCPU, 4 GB RAM) with default 8G SSD. Pick Ubuntu OS. Make sure that the two nodes are with the same security group, which allows TCP 30303 (or 30000-30999 as I may use more ports on this range). Port 30303 by default is for peering among nodes.



Experience Sharing

  • I first tried t2.micro as it is the free-tier offer. However, mining was not successful (“DAG” loop without ether reward). I next tried t2.small and mining worked. However, when I deployed contract (see Part 2), the rpc was unstable. Finally, I found t2.medium good enough for my setup.


  • I usually STOP the instance after testing (to save money). Please note that the public IP address of the EC2 instance will be changed after you START it back. This does not have an impact on our setup here as I am using the private IP address of these instances for peering. Private IP address remains even after I STOP/START the instance. In any case if Public IP address is needed, the peering still works, but you may need to change the peering address every time.


Step 2: Install geth client on Node 1


Access to Node 1 with ssh and proper key. Follow the recommended process (link) for geth installation. Install from PPA is good enough.

Node 1	

$ sudo apt-get install software-properties-common
$ sudo add-apt-repository -y ppa:ethereum/ethereum
$ sudo apt-get update
$ sudo apt-get install ethereum


and verify it with $ which geth and you will see that geth is installed properly.


Step 3: Prepare the Genesis.json

This same Genesis.json is applied to both nodes, as it is to ensure both nodes having the same genesis block. Here is the Genesis.json I used, which is adopted from here (link). I take out the initial allocation as I don’t need to modify the address on this file in each new setup. Each account will gain some ethers once it starts mining.



"config": {

"chainId": 15,

"homesteadBlock": 0,

"eip155Block": 0,

"eip158Block": 0


"nonce": "0x0000000000000042",

"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",

"difficulty": "0x200",

"alloc": {},

"coinbase": "0x0000000000000000000000000000000000000000",

"timestamp": "0x00",

"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",

"gasLimit": "0xffffffff",

"alloc": {




Keep this file somewhere and later scp to the nodes, or just copy and paste with an editor on both nodes.


Step 4: Init the geth with Genesis.json


Node 1	

$ geth init Genesis.json


Step 5: Launch geth now

It is good practice to have two screens in parallel (or a split terminal). One screen is the console while another shows the log. Open a new terminal and ssh to Node 1, and keep reading the log.

Node 1	$ geth --nodiscover console 2>> eth.log
another terminal $ tail -F eth.log

Two-Node Setup of a Private Ethereum on AWS with Contract Deployment

Experience Sharing

  • In many examples, it is recommended to use –datadir to specify the directory for private ethereum blockchain. This is good practice when you are interacting with different chains. My example is an isolated environment. Therefore I omit this option, and my private chain is stored in the directory ~/.ethereum/.


Step 6: Create an Account on Node 1

Node 1 geth
> personal.newAccount()

> eth.getBalance(eth.accounts[0]) OR > web3.fromWei(eth.getBalance(eth.accounts[0]), ether)


Now we have an account on this node (always check it with > eth.accounts[0] or > eth.coinbase). And currently, there is no ether in the account balance as we have not allocated any in Genesis.json.


Step 7: Start Mining

We can begin mining process.

  1. From the log terminal, we will see “Generating DAG in progress” and after an epoch, a block is being mined.
  2. Once a block is mined, 5 ethers are added to the account balance. This is a good indicator whether mining is successful or not.
  3. If we keep mining, the amount of account balance keeps increasing as more new blocks are mined.


Node 1 geth	

> miner.start()
> eth.getBalance(eth.accounts[0])


Feel free to keep mining, or we can turn it off by > miner.stop().

Now Node 1 is ready. Let’s work on Node 2.


Step 8: Repeat Step 2-6 on Node 2


Make sure the same Genesis.json is used when init the blockchain on Node 2.

Do not start mining as we want Node 2 on the same blockchain as Node 1 (through Peering).


Step 9: Peering

Now we begin peering the two nodes. There are several ways to peer. Here I am using “admin addPeer” to do the peering: in Node 2, add Node 1 enode information for peering.

First, check both nodes that there is no peering.

Node 1	> admin.peers
Node 2	> admin.peers


Obtain enode information from Node 1

Node 1	> admin.nodeInfo.enode


We will get something like this:



Add this information to Node 2. Change the [::] with the Private Address of Node 1.

Node 2	

> admin.addPeer("enode://c667fdf1f6846af74ed14070ef9ffeee33e98ff8ab0dd43f67415868974d8205e0fb7f55f6f37e9e1ebb112adfc0b88755714c7bc83a7ac47d30f8eb53118687@")


After that check, both nodes and they are peering each other.

Node 1	> admin.peers
Node 2	> admin.peers


The left-hand-side is Node 1 and right-hand-side is Node 2. Note that after > addPeer() on Node 2, two nodes are peered. We do not need to do the same thing on Node 1.


Also, from the log, we see that, after peering, we see “Block synchronization started” and “Imported new chain segment” on Node 2 log (bottom-right terminal).


Experience Sharing

  • Make sure to use the same Genesis.json to initiate the blockchain. In one trial I forgot to init step and peering was unsuccessful.
  • AWS EC2 instance comes with a private IP address and a public IP address. Both works fine in add peering, but using private IP address is more convenient as it is not changed after instance STOP/START.


Step 10: Send Ethers Between Accounts


As both nodes are in the same Ethereum blockchain, we will send some ethers between the accounts. In this example, 10 ethers are sent from the account of Node 1 to account of Node 2. This is one of the best ways to verify if the setup is successful.


Node 1	

> web3.fromWei(eth.getBalance(eth.coinbase), ether)
> personal.unlockAccount(eth.coinbase)
> eth.sendTransaction({from: eth.coinbase, to: "0xabc65de992289401dcff3a70d4fcfe643f7d2271", value: web3.toWei(10, ether)})
> miner.start()

Node 2	> web3.fromWei(eth.getBalance(eth.coinbase), ether)


Two-Node Setup of a Private Ethereum on AWS with Contract Deployment

Note that we see “pending transaction” as this transaction is not mined yet. Once we start mining in Node 1, the transaction is done and account balance on Node 2 is now 10 ethers.


And we see 45 ethers in Node 1 (not the expected 20-10=10 ethers). It is because Node 1 keeps receiving mining reward (5 ethers per block). The balance will keep increasing until we stop mining.



Now we complete the first part: we build a two-node private Ethereum blockchain on AWS. You can go directly to next part to deploy contract, r stop the process and EC2 instance for future use. In case peering is changed for any reasons, you can re-peering the nodes with Step 9 above.


Like what you read? Give us one like or share it to your friends


Join Blockgeeks

Create an account to access our exclusive point system, get instant notifications for new courses, workshops, free webinars and start interacting with our enthusiastic blockchain community. Don’t miss out and join right now!

Already have an account? Sign In


    Stay tuned. I sent out already and guess it would be there soon.


    Thanks a lot for sharing!

    I’m a newbie, the mining starts following your instructions…I’m wondering if I close the console, is mining stopped as well? Do I have to keep the console open while mining?

    Is it similar process for bitcoins mining?

    Thank you!


    Hi Eric,

    It depends on how you “close” the console. I usually find the geth gone after I exit the console and therefore the mining should have stopped. However, if my ssh session timeout, and when I login back my EC2 instance the geth process is still there. If so, the mining should be still there and you can geth attach to reach the console again.

    You can always check if geth is still running.

    HTH. It’s just my experience but worthy to make a trial.

    cheers, kc


    I remembered that I had experiences on a similar issue for remote desktop session manager, we had to log in to the same session to keep up with all processes.

    There must be a similar session manager for SSH connection.

    I’ll be doing more digging out and get back to you if I can find something.

    I was initially looking for ETHER cloud mining solutions, so new about all this, it took me some time after having learned about Ether wallet, address, GPU/CPU/ASCI, POW/POS…and realized this testing block-chain environment is not about a real mining solution.
    Ethereum must have a great future, Solidity programming, contracts must have a lot of applications in real world.

    Back to my question I had for session manager, I guess that to install a Ubuntu remote desktop, run commands from the console, it might help to keep the same session alive.

    Thanks for your articles, first time I really read an article about blockchain, I also went through the articles and guides on Blockgeeks! Great job!


    Glad to hear that. There are some very new development around blockchain beside mining: recently I am trying several stuff like Hyperledger, Quorum, and the latest Coco framework. All center on enterprise use of blockchain, which brings enterprise value on blockchain beside cryptocurrency. Have fun!

    Hi, I think it’s a setup issue with AWS. Please make sure the two nodes are with the same security group. Also please note that the public IP address of the EC2 instance will be changed after you START it back. This does not have an impact on our setup here as I am using the private IP address of these instances for peering. Private IP address remains even after I STOP/START the instance. In any case if Public IP address is needed, the peering still works, but you may need to change the peering address every time. Hope this helps.

    Thx for the great article, I’m also looking at AWS’s ethereum template and failed to setup. Have you looked into it? It seems very completed having the load balancing server, Bastion Host, etc…

    @Richard Fu

    Hi Richard,

    I never try the AWS template (and other clouds as well). As you can see it’s just on a VM. Always wish to do it the hard way to avoid lock-in.


    Great article, but I’m still having issues peering the nodes together. They use the same AWS security group and can telnet to each other. I’m using the above instructions with Geth v1.8.16 and have the first node working great – it’s mining and can sendTransactions via CLI and MetaMask… any suggestions?