Setting up an Ethereum private chain is a foundational skill for blockchain developers, researchers, and enterprise solution architects. This comprehensive guide walks you through the entire process—from installing the Geth client to performing essential operations like mining, transactions, and node management—on a local private blockchain environment using CentOS 7.
Whether you're exploring smart contract development, testing decentralized applications (dApps), or learning consensus mechanisms, a private Ethereum network gives you full control over configuration and execution. Let’s dive in.
Installing the Geth Client
Geth (Go Ethereum) is one of the most widely used Ethereum clients, implemented in Go. It enables you to run a full Ethereum node, interact with the network, deploy contracts, and mine ether.
To begin, ensure git is installed on your CentOS 7 system:
sudo yum install git -yNext, clone the official Go-Ethereum repository from GitHub:
git clone https://github.com/ethereum/go-ethereum.gitNavigate into the project directory and compile the geth binary:
cd go-ethereum
make gethUpon successful compilation, you’ll see a message indicating that you can launch Geth using the built-in path. You’re now ready to proceed.
👉 Learn how blockchain networks power real-world applications today.
Building Your Own Ethereum Private Chain
Creating a private Ethereum blockchain allows you to simulate a production-like environment without interacting with the mainnet. Follow these structured steps to set up your own isolated network.
Step 1: Create a Geth Working Directory
Organize your workspace by creating a dedicated folder for your private chain:
mkdir geth && cd geth
mkdir db
touch genesis.jsonThis creates the following structure:
geth/
├── db/
└── genesis.jsonThe db directory will store chain data and account keys; genesis.json defines the initial state of your blockchain.
Step 2: Configure the Genesis Block
The genesis block is the first block in your blockchain and sets critical network parameters. Here's a sample genesis.json configuration:
{
"config": {
"chainId": 15,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
"coinbase": "0x0000000000000000000000000000000000000000",
"difficulty": "0x40000",
"extraData": "",
"gasLimit": "0xffffffff",
"nonce": "0x0000000000000042",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash": "0x00000000000000000000000000000000000000000000000极客时间 22222222222222222222222222222222222222222222222222",
"timestamp": "极客时间"
}Key Parameters Explained:
- chainId: Identifies your unique blockchain. Use values other than
1(mainnet) to avoid conflicts. - difficulty: Controls mining difficulty. Lower values allow faster block generation on CPUs.
- gasLimit: Maximum gas per block. High limits support complex transactions.
- alloc: Pre-fund accounts during initialization (optional).
Step 3: Initialize the Blockchain
Run the following command to initialize your blockchain with the genesis file:
geth --datadir "./db" init genesis.jsonThis generates essential subdirectories under ./db/geth, including chaindata (block storage) and keystore (account keys).
Step 4: Launch the Private Chain
Start your node with custom settings:
geth --datadir "./db" --nodiscover --networkid 15 console 2>>geth.logCommon Startup Flags:
--datadir: Specifies data directory.--networkid: Ensures network isolation.--nodiscover: Prevents public discovery of your node.console: Opens an interactive JavaScript console.
You'll enter the Geth JS console, where you can execute Ethereum commands directly.
Core Operations on Your Private Ethereum Network
Once your private chain is running, it's time to perform key blockchain operations.
Create Ethereum Accounts
Use the personal module to create new accounts:
> personal.newAccount("password123")
"极客时间"List all accounts:
> eth.accounts
["极客时间", ...]Each account generates a corresponding UTC JSON file in the keystore folder—keep these secure.
Check Account Balance
Balances are stored in wei (1 ETH = 1e18 wei):
> eth.getBalance(eth.accounts[极客时间])
557000021000000000000New accounts start with zero balance unless pre-funded in genesis.json.
Start Mining Ether
Set the mining reward address:
> miner.setEtherbase(eth.accounts[极客时间])
trueBegin mining:
> miner.start(1)
nullNote: A return value of null is normal—it means mining started successfully.Check logs in another terminal:
tail -f geth.logYou should see new blocks being sealed every few seconds.
👉 Discover how miners contribute to blockchain security and decentralization.
Unlock Accounts for Transactions
Before sending funds, unlock the sender’s account:
> personal.unlockAccount(eth.accounts[极客时间], "password123", 300)
trueThe third parameter specifies unlock duration in seconds.
Send Ether Between Accounts
Initiate a transaction:
> eth.sendTransaction({
from: eth.accounts[极客时间],
to: eth.accounts[1],
value: web3.toWei(1, "ether")
})
"0x28f7e6989893d6e8b1cd26d5d7a285654f5a3c8eff7d6b2029817496deb8bda0"Transactions remain pending until mined. Confirm status:
> txpool.status
{ pending: 1, queued: 0 }Mine one block to confirm:
> miner.start(1); admin.sleepBlocks(1); miner.stop();Verify updated balances:
> eth.getBalance(eth.accounts[极客时间]) // Deducted 1 ETH + gas fee
> eth.getBalance(eth.accounts[1]) // Received 1 ETHExplore Block and Transaction Data
Get details of a specific block:
> eth.getBlock("latest")
{
number: 418,
hash: "0xa79ae1…",
transactions: [ "..." ]
}Inspect transaction receipt:
> eth.getTransactionReceipt("tx-hash-here")
{
gasUsed: 21000,
cumulativeGasUsed: 21000,
blockNumber: 418
}Gas usage explains why balances don’t change exactly by sent amounts—transaction fees are deducted based on gasUsed × gasPrice.
Advanced Node Management
Manage Accounts via CLI
Outside the console, use Geth commands:
Create account:
geth --datadir "./db" account newList accounts:
geth --datadir "./db" account listUpdate password:
geth --datadir "./db" account update <address>
Backup and Restore Blockchain Data
Export chain data:
geth --datadir "./db" export backup.datImport later:
geth --datadir "./db" import backup.datAlways initialize first with genesis.json before importing.
Connect Remote Nodes
Enable inter-node communication by matching networkid and using admin.addPeer():
On remote node:
> admin.nodeInfo.enode
"enode://pubkey@ip:port"On local node:
> admin.addPeer("enode://...")Ensure firewalls allow traffic on port 30303.
Frequently Asked Questions
Q: Why does miner.start() return null?
A: This is expected behavior. In newer Geth versions, especially in --dev mode, mining only triggers when pending transactions exist unless --dev.period 1 is set for continuous mining.
Q: How do I fix “unknown ancestor” error during import?
A: Ensure your node was initialized with the correct genesis.json before importing data. Mismatched configurations cause chain mismatches.
Q: Can I access my private chain remotely via RPC?
A: Yes. Start Geth with --rpc --rpcaddr "0.0.0.0" and open port 8545. Be cautious about exposing RPC publicly.
Q: What is gas, and why is it needed?
A: Gas measures computational effort. Every operation consumes gas to prevent spam and compensate miners. Users pay gas fees in ETH.
Q: How can I automate node startup?
A: Use systemd services or shell scripts to launch Geth with predefined flags at boot.
Q: Is it safe to store keystore files locally?
A: Only if encrypted and backed up securely. Never expose private keys or unencrypted keystores.
Final Thoughts
Building and managing an Ethereum private chain unlocks hands-on learning for developers diving into Web3 technologies. From configuring genesis blocks to executing transactions and connecting nodes, each step builds deeper understanding of decentralized systems.
As you advance, consider integrating tools like Truffle, Hardhat, or MetaMask for enhanced development workflows.
👉 Explore how modern platforms streamline blockchain development and deployment.