Setting up an Ethereum private testnet is a crucial step for developers who want to experiment with smart contracts, decentralized applications (dApps), or blockchain behavior in a controlled environment. This guide walks you through the complete process of building a functional Ethereum private network using Geth, the Go implementation of Ethereum. We'll cover genesis block configuration, node initialization, peer connection, and transaction testing—ensuring you gain hands-on experience without risking real funds.
Whether you're new to blockchain development or expanding your testing infrastructure, this tutorial provides clear, actionable steps compatible with Ubuntu systems.
Install Geth on Ubuntu
Geth is one of the most widely used Ethereum clients, enabling users to run a full Ethereum node. It supports private network creation, making it ideal for local development and testing.
To install Geth on Ubuntu, execute the following commands in your terminal:
sudo apt-get install software-properties-common
sudo add-apt-repository -y ppa:ethereum/ethereum
sudo apt-get update
sudo apt-get install ethereumThese commands add the official Ethereum repository and install the latest stable version of Geth. Once installed, you can verify the installation by running:
geth versionThis confirms that Geth is ready for use.
👉 Learn how to interact with Ethereum networks using developer tools.
Configure a Custom Genesis Block
The genesis block is the first block in any blockchain and defines the initial state and rules of your private network. To create a custom genesis file (CustomGenesis.json), define key parameters such as chain ID, difficulty, gas limit, and pre-funded accounts.
Here’s an example configuration:
{
"config": {
"chainId": 3131,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
"difficulty": "200000000",
"gasLimit": "2100000",
"alloc": {
"7df9a875a174b3bc565e6424a0050ebc1b2d1d82": { "balance": "300" },
"f41c74c9ae680c1aa78f42e5647a62f353b7bdde": { "balance": "400" }
}
}Key Parameters Explained
chainId: Prevents replay attacks by uniquely identifying your network.homesteadBlock: Set to0to enable Homestead-era protocol rules from launch.difficulty: Lower values allow faster mining—ideal for testing.gasLimit: Sets the maximum gas per block; adjust based on expected transaction load.alloc: Pre-funds specific addresses with ether for immediate use.
Save this file as CustomGenesis.json in a dedicated project directory.
Initialize the Private Blockchain
With the genesis file ready, initialize the blockchain data folder using the init command:
geth --datadir /path/to/data init /path/to/CustomGenesis.jsonReplace /path/to/data with your desired data directory (e.g., ~/privatechain-eth/data). This command creates the necessary internal structure for your blockchain, including the genesis block.
Launch the First Node
Start your first Geth node with a comprehensive set of options tailored for private network operation:
geth \
--identity "ETH-MainNode" \
--rpc \
--rpcport "6060" \
--rpccorsdomain "*" \
--datadir "/home/lyh/privatechain-eth/data" \
--port "30303" \
--nodiscover \
--maxpeers 5 \
--rpcapi "admin,db,eth,debug,miner,net,shh,txpool,personal,web3" \
--networkid 3131 \
consoleUnderstanding Core Flags
--nodiscover: Disables automatic peer discovery, enhancing security in private setups.--networkid 3131: Ensures only nodes with the same ID can connect.--rpcand--rpcapi: Enable JSON-RPC interface for external tool integration.--rpccorsdomain "*": Allows web applications to interact with the node (use cautiously in production).console: Launches the interactive JavaScript console for real-time commands.
Once launched, you’ll enter the Geth JavaScript console where you can manage accounts, mine blocks, and send transactions.
Connect Multiple Nodes
To simulate a distributed network, set up a second node using the same genesis configuration and data directory path (adjusted for its local system).
Retrieve Node Information
On the first node, run:
> admin.nodeInfoThis returns detailed node information including the enode URL—a unique identifier used for peer connections. Example output:
enode://09444457dd475ac1a81948c5066602d23abd49407cae33edef929c9d96374396496f97b1a8fb1c22d36d990e90ed16a2a4faf3fd2ae63c08f4f58ee6249bcec7@[::]:30303Replace [::] with the actual IP address of the first machine (e.g., 192.168.1.10) so the second node can reach it.
Add Peer from Second Node
In the second node's console, execute:
> admin.addPeer("enode://[email protected]:30303")Confirm connection success by checking peer count:
> net.peerCount
1A return value of 1 indicates successful node-to-node communication.
👉 Explore secure ways to manage blockchain nodes and wallets.
Test Transactions Across Nodes
Now that both nodes are connected and synchronized, let’s validate functionality by creating accounts, mining ether, and transferring funds.
Create Accounts on Both Nodes
In each console:
> personal.newAccount()You’ll be prompted to set a password. The command returns a new Ethereum address like:
- Node 1:
"0xa9436991e002986f58d948d79e737df190c4f26b" - Node 2:
"0xf7be2382f03cf7dd8ed5e59253a7b9321aac20ec"
Start Mining
Since new accounts have zero balance, activate mining to generate ether:
On Node 1:
> miner.setEtherbase("0xa9436991e002986f58d948d79e737df190c4f26b")
> miner.start(1)On Node 2:
> miner.setEtherbase("0xf7be2382f03cf7dd8ed5e59253a7b9321aac20ec")
> miner.start(1)Let mining run briefly (a few seconds), then stop with miner.stop().
Send a Transaction
Unlock the sender account:
> personal.unlockAccount("0xa9436991e002986f58d948d79e737df190c4f26b")Send 10 ether to Node 2:
> eth.sendTransaction({
from: "0xa9436991e002986f58d948d79e737df190c4f26b",
to: "0xf7be2382f03cf7dd8ed5e59253a7b9321aac20ec",
value: web3.toWei(10, "ether")
})The transaction hash will be returned. Wait a moment for confirmation via mining.
Verify Balance
Check if funds were received:
> eth.getBalance("0xf7be2382f03cf7dd8ed5e59253a7b9321aac20ec")If successful, the balance should reflect the transferred amount plus mined rewards.
Frequently Asked Questions (FAQ)
What is an Ethereum private testnet used for?
A private testnet allows developers to simulate Ethereum network behavior locally. It's ideal for testing smart contracts, debugging dApps, or learning blockchain mechanics without using real ETH or impacting the mainnet.
Why use Geth instead of other clients like Parity/OpenEthereum?
Geth is well-documented, actively maintained, and integrates seamlessly with developer tools like Truffle and MetaMask. Its widespread adoption makes it a reliable choice for both beginners and professionals.
Can I access my private network from another machine?
Yes—ensure your firewall allows traffic on port 30303 (P2P) and 6060 (RPC), and bind Geth to a public IP if needed using --rpcaddr. Avoid exposing RPC publicly in insecure environments.
How do I reset my private blockchain?
Delete the data directory specified in --datadir, then reinitialize with geth init. This wipes all accounts, transactions, and mined blocks.
Is it safe to use "--rpccorsdomain *" and "--rpc"?
These settings are acceptable in isolated development environments but should never be used in production. For public-facing nodes, restrict CORS domains and disable unnecessary APIs.
What are common issues when connecting nodes?
Common problems include incorrect enode URLs (especially unresolved [::]), firewall restrictions, mismatched network IDs, or differing genesis files. Always double-check configuration consistency across nodes.
👉 Securely manage your blockchain assets with trusted platforms.
Core Keywords
- Ethereum private testnet
- Geth setup
- Genesis block configuration
- Node connection Ethereum
- Local blockchain development
- Smart contract testing
- Mining on private Ethereum network
- JSON-RPC Ethereum
By following this guide, you’ve successfully built and tested a two-node Ethereum private network—laying the foundation for advanced development and experimentation.