Geth (go-ethereum) is the official Go implementation of an Ethereum execution-layer client. It connects to the Ethereum peer-to-peer network, downloads and verifies the blockchain, maintains the current world state, executes the Ethereum Virtual Machine (EVM), and exposes a complete JSON-RPC interface for reading chain data and broadcasting transactions. The main binary is geth; the repository also ships a suite of focused command-line tools (abigen, evm, devp2p, ethkey, era, rlpdump, abidump, blsync, and more).
This guide covers installing Geth, running a node on mainnet and the test networks, managing accounts, using the JavaScript console and JSON-RPC APIs, operating the companion tools, and troubleshooting common problems. Written from the source at commit f5c62d0.
Important
Since Ethereum's transition to proof-of-stake (The Merge), Geth alone is not a full Ethereum node. Geth handles the execution layer (transactions, state, the EVM) but no longer drives consensus. You must run a separate consensus-layer client (also called a beacon node — for example Lighthouse, Prysm, Teku, Nimbus, or Lodestar) alongside Geth. The two communicate over the authenticated Engine API (default
localhost:8551) using a shared JWT secret. A Geth process with no consensus client attached will sync peer data but will never advance to the chain head.
1. Quick Start
The fastest path to a synced mainnet node is to build Geth, generate a JWT secret, start Geth with the Engine API enabled, and point a consensus client at it.
# 1. Build geth from source (requires Go 1.24+)
git clone https://github.com/ethereum/go-ethereum.git
cd go-ethereum
make geth
# 2. Create the JWT secret shared with your consensus client
openssl rand -hex 32 | tr -d "\n" > /etc/ethereum/jwt.hex
# 3. Start geth on mainnet with the Engine API and HTTP-RPC enabled
./build/bin/geth \
--mainnet \
--http --http.api eth,net,web3 \
--authrpc.jwtsecret /etc/ethereum/jwt.hex \
--authrpc.addr localhost --authrpc.port 8551
INFO [06-04|10:00:00.000] Starting Geth on Ethereum mainnet...
INFO [06-04|10:00:00.100] Maximum peer count ETH=50 total=50
INFO [06-04|10:00:00.200] Set global gas cap cap=50,000,000
INFO [06-04|10:00:01.000] Started P2P networking self=enode://...@127.0.0.1:30303
INFO [06-04|10:00:01.500] Looking for peers peercount=0 tried=12 static=0
Note
Geth will print
WARN ... Post-merge network, but no beacon client seen. Please launch one to follow the chain!until you connect a consensus client. This is expected on a fresh start.
Then launch your consensus client with the matching JWT secret and Engine API endpoint. Once both are running, Geth begins snap sync and reaches the head within hours.
Attach a console to inspect the node:
./build/bin/geth attach
Welcome to the Geth JavaScript console!
instance: Geth/v1.16.0-stable/linux-amd64/go1.24.0
at block: 0 (Thu Jan 01 1970 00:00:00 GMT+0000)
datadir: /home/user/.ethereum
modules: admin:1.0 debug:1.0 eth:1.0 net:1.0 rpc:1.0 txpool:1.0 web3:1.0
>
2. Installation
Geth requires Go 1.24.0 or newer to build from source. A C compiler is needed for the bundled secp256k1 and blst cgo packages.
2.1 Build from source
Linux / macOS
git clone https://github.com/ethereum/go-ethereum.git
cd go-ethereum
make geth
# binary lands in ./build/bin/geth
Build all tools
# Builds geth plus abigen, evm, devp2p, ethkey, era, rlpdump, etc.
make all
# binaries land in ./build/bin/
Plain go build
go build -o geth ./cmd/geth
go build -o abigen ./cmd/abigen
The make geth target embeds version and git-commit metadata into the binary. After building, verify the result:
./build/bin/geth version
Geth
Version: 1.16.0-stable
Git Commit: f5c62d0...
Architecture: amd64
Go Version: go1.24.0
Operating System: linux
Tip
Place
./build/binon yourPATH(or copygethto/usr/local/bin) so you can invokegethdirectly instead of by full path. The remainder of this guide assumesgethis on yourPATH.
2.2 Docker
The repository includes a Dockerfile. Build and run a container, mapping a host directory for persistent chain data and exposing the RPC and P2P ports:
docker build -t geth .
docker run -d --name geth-node \
-v /srv/geth:/root/.ethereum \
-p 8545:8545 -p 30303:30303 -p 30303:30303/udp \
geth \
--mainnet --http --http.addr 0.0.0.0 --http.api eth,net,web3 \
--authrpc.addr 0.0.0.0 --authrpc.jwtsecret /root/jwt.hex
Warning
Binding
--http.addr 0.0.0.0exposes the JSON-RPC server on all interfaces. Only do this behind a firewall or reverse proxy. See Securing your node.
2.3 Hardware and disk requirements
| Resource | Mainnet recommendation |
|---|---|
| CPU | 4+ cores |
| RAM | 16 GB+ (32 GB for archive) |
| Disk | Fast SSD/NVMe; a snap-synced full node is large and grows continuously. Plan for terabyte-class storage and headroom. |
| Network | Stable broadband; open TCP+UDP port 30303 for best peering |
Caution
Geth's chain data must live on an SSD or NVMe drive. Spinning disks (HDD) cannot keep up with state access during sync or block import and will cause the node to fall behind the chain head indefinitely.
Note
Geth automatically shuts down to protect your filesystem when free disk space runs low. The threshold is controlled by
--datadir.minfreedisk(in MB). Monitor free space and keep ample headroom.
3. Running a Node
3.1 The data directory
Geth stores everything — chain database, state, keystore, node key, and IPC socket — under a single data directory (datadir). The default location is platform-specific:
| Platform | Default datadir |
|---|---|
| Linux | ~/.ethereum |
| macOS | ~/Library/Ethereum |
| Windows | %LOCALAPPDATA%\Ethereum |
Override it with --datadir:
geth --datadir /srv/geth/mainnet --mainnet
You can relocate just the bulky ancient (frozen) data with --datadir.ancient and pre-merge Era history with --datadir.era, which is useful when chain data spans multiple volumes.
3.2 Selecting a network
Geth selects mainnet by default. Use a network flag to choose a pre-configured network instead:
| Flag | Network |
|---|---|
--mainnet |
Ethereum mainnet (default) |
--sepolia |
Sepolia — pre-configured proof-of-stake test network |
--holesky |
Holesky — pre-configured proof-of-stake test network |
--hoodi |
Hoodi — pre-configured proof-of-stake test network |
--dev |
Ephemeral single-node proof-of-authority network with a pre-funded developer account, mining enabled |
--networkid <int> |
Explicitly set a custom network ID (for private networks) |
# Run a Sepolia testnet node
geth --sepolia --http --http.api eth,net,web3 \
--authrpc.jwtsecret /etc/ethereum/jwt.hex
Note
The network flags are mutually exclusive. For private networks, use
--networkidtogether with a custom genesis (see Private networks).
3.3 Connecting a consensus client (the Engine API)
Geth exposes a separate, authenticated RPC endpoint dedicated to the consensus client — the Engine API. It listens on localhost:8551 by default and is protected by a JWT secret rather than being publicly reachable.
# Generate a 32-byte hex JWT secret once
openssl rand -hex 32 | tr -d "\n" > /etc/ethereum/jwt.hex
Pass the same file to both Geth and your consensus client:
geth --mainnet \
--authrpc.addr localhost \
--authrpc.port 8551 \
--authrpc.vhosts localhost \
--authrpc.jwtsecret /etc/ethereum/jwt.hex
| Engine API flag | Default | Purpose |
|---|---|---|
--authrpc.addr |
localhost |
Listening address for authenticated APIs |
--authrpc.port |
8551 |
Listening port for authenticated APIs |
--authrpc.vhosts |
localhost |
Accepted virtual hostnames (server enforced; * wildcard allowed) |
--authrpc.jwtsecret |
(auto-generated in datadir) | Path to the JWT secret shared with the consensus client |
Important
If you do not pass
--authrpc.jwtsecret, Geth generates a secret at<datadir>/geth/jwtsecreton startup. Your consensus client must be pointed at that exact file. Specifying the path explicitly on both sides avoids confusion.
Tip
blsync(shipped in this repository) is a lightweight beacon-chain light client that can drive Geth's Engine API for testing or low-resource setups. It is not a substitute for a full consensus client on mainnet but is handy for experimentation — see Section 9.8.
3.4 Sync modes
Geth supports two blockchain sync modes, chosen with --syncmode:
| Mode | Behavior |
|---|---|
snap (default) |
Downloads recent state via the snap protocol, then fills in blocks. Fastest way to reach the head. |
full |
Re-executes every block from genesis, rebuilding state locally. Slower but executes the entire history. |
geth --mainnet --syncmode full # full re-execution from genesis
geth --mainnet --syncmode snap # default — fast state sync
The amount of historical state and indexes Geth retains is governed by garbage-collection and history flags:
| Flag | Default | Purpose |
|---|---|---|
--gcmode |
full |
full prunes old state; archive keeps all historical state (huge disk use) |
--state.scheme |
path |
State storage scheme: path (modern, prunable) or hash (legacy) |
--history.state |
90,000 blocks | Recent blocks to retain state history for (path scheme; 0 = entire chain) |
--history.transactions |
~1 year | Recent blocks to keep the transaction index for (0 = entire chain) |
--history.logs |
~1 year | Recent blocks to keep the log-search index for (0 = entire chain) |
--history.chain |
all |
Block-body/receipt retention: all, postmerge, or postprague |
Tip
Run an archive node (every historical state, queryable at any block) with
--gcmode archive --syncmode full. Expect dramatically larger disk usage and longer sync times than a pruned full node. Only run archive if you specifically need historical-state queries.
Caution
Switching
--state.schemeor--gcmodeon an existing database is not a live toggle. The scheme is fixed at database creation; changing it generally requires re-syncing or an explicit migration. Decide before your first sync.
3.5 Developer mode
For local contract development and testing, --dev spins up an ephemeral, single-node proof-of-authority chain with a pre-funded account and instant or interval mining — no consensus client required:
geth --dev --http --http.api eth,net,web3,debug --datadir /tmp/geth-dev
INFO [06-04|10:00:00.000] Using developer account address=0x71562b71999873DB5b286dF957af199Ec94617F7
INFO [06-04|10:00:00.000] Starting Geth in ephemeral dev mode...
| Flag | Purpose |
|---|---|
--dev |
Ephemeral PoA dev network, mining enabled, pre-funded account |
--dev.period <n> |
Block period in seconds (0 = mine only when a transaction is pending) |
--dev.gaslimit <n> |
Initial block gas limit |
Warning
Dev-mode chain data is ephemeral — it lives in a temporary directory and is wiped on restart unless you pass an explicit
--datadir. Never use developer mode for anything requiring persistence or real value.
3.6 Graceful shutdown
Stop Geth with Ctrl-C (or SIGINT/SIGTERM to the process). Geth flushes in-memory state to disk on shutdown.
Caution
Do not
kill -9(SIGKILL) a running Geth. An ungraceful kill can leave the trie cache unflushed, forcing a slow state-recovery rewind on the next start, or in rare cases require a resync. Always allow Geth time to shut down cleanly.
4. Managing Accounts
Geth stores accounts as encrypted keystore files under <datadir>/keystore. Each file holds one private key encrypted with a password you choose.
Important
Account management commands operate on the local keystore only. The legacy
personalRPC namespace for remote account unlocking has been removed from Geth — there is nopersonal_unlockAccountover RPC. For programmatic signing, manage keys withethkey, an external signer (--signer), or a hardware wallet.
4.1 Create a new account
geth account new
Your new account is locked with a password. Please give a password. Do not forget this password.
Password:
Repeat password:
Your new key was generated
Public address of the key: 0xfcad0b19bb29d4674531d6f115237e16afce377c
Path of the secret key file: /home/user/.ethereum/keystore/UTC--2026-06-04T...--fcad0b19...
- You can share your public address with anyone. Others need it to interact with you.
- You must NEVER share the secret key with anyone! The key controls access to your funds!
- You must BACKUP your key file! Without the key, it's impossible to access account funds!
- You must REMEMBER your password! Without the password, it's impossible to decrypt the key!
For non-interactive (scripted) use, supply a password file:
geth account new --password /path/to/password.txt
Warning
Passing
--passwordreads the password from a plaintext file. This is intended for test networks and known-safe automated environments only. Never store a mainnet account password on disk in plaintext.
4.2 List accounts
geth account list
Account #0: {7ef5a6135f1fd6a02593eedc869c6d41d934aef8} keystore:///home/user/.ethereum/keystore/UTC--2016-03-22T12-57-55...
Account #1: {f466859ead1932d743d622cb74fc058882e8648a} keystore:///home/user/.ethereum/keystore/aaa
4.3 Import a private key
geth account import /path/to/key.prv
Address: {fcad0b19bb29d4674531d6f115237e16afce377c}
The key file must contain an unencrypted private key in hexadecimal. Geth encrypts it with a password you provide and writes a new keystore file.
4.4 Update (re-encrypt) an account
geth account update f466859ead1932d743d622cb74fc058882e8648a
This prompts for the current password and a new one — use it to change a password or migrate an old keystore format to the current one.
4.5 Import a presale wallet
geth wallet import /path/to/presale.wallet
4.6 Lightweight key derivation
For resource-constrained machines, --lightkdf reduces the RAM and CPU cost of key derivation at the expense of KDF strength:
geth account new --lightkdf
Caution
--lightkdfmakes keystore files faster to brute-force. Use it only on test networks or where the account holds no real value.
4.7 Hardware wallets
Geth can monitor and manage USB hardware wallets (Ledger, Trezor, KeepKey-class devices) and smartcard wallets when enabled:
geth --usb --mainnet
| Flag | Purpose |
|---|---|
--usb |
Enable monitoring and management of USB hardware wallets |
--pcscdpath <path> |
Path to the smartcard daemon (pcscd) socket file |
Connected wallets and their derived accounts then appear in admin.peers-style listings and are usable for signing through the node.
5. The JavaScript Console
Geth includes an interactive JavaScript console built on the web3 object, extended with Geth-specific management namespaces.
5.1 Opening a console
# Start a node AND open a console in one process
geth --mainnet console
# Attach a console to an ALREADY-RUNNING node over IPC (recommended)
geth attach
# Attach over HTTP or WebSocket
geth attach http://localhost:8545
geth attach ws://localhost:8546
Tip
Prefer
geth attach(over the IPC socket) for day-to-day inspection. It connects to your running node without starting a second instance and has full access to all local namespaces regardless of which APIs you exposed over HTTP/WS.
Pass custom HTTP headers to the target when attaching to a remote endpoint:
geth attach -H "Authorization: Bearer <token>" https://node.example.com
5.2 Console namespaces
The console exposes these management namespaces (in addition to standard web3/eth methods):
| Namespace | What it covers |
|---|---|
eth |
Accounts, balances, blocks, transactions, calls, gas estimation |
net |
Peer count, listening status, network ID |
web3 |
Utility helpers (hashing, unit conversion, encoding) |
admin |
Node info, peer management, start/stop RPC servers, import/export chain |
debug |
Tracing, state dumps, profiling, database introspection |
txpool |
Pending/queued transaction pool contents and status |
miner |
Block-building parameters (gas limit, extra data, fee recipient) |
clique |
Proof-of-authority signer management (PoA networks only) |
rpc |
RPC module listing |
dev |
Developer-mode helpers |
5.3 Common console commands
// Current sync status (false once fully synced)
eth.syncing
// Latest block number
eth.blockNumber
// Balance of an address, converted to ether
web3.fromWei(eth.getBalance("0xfcad0b19bb29d4674531d6f115237e16afce377c"), "ether")
// Number of connected peers
net.peerCount
// Node identity and enode URL
admin.nodeInfo.enode
// Connected peers
admin.peers
// Pending transaction pool snapshot
txpool.status
> eth.syncing
{
currentBlock: 19000000,
highestBlock: 19000123,
startingBlock: 18999000,
...
}
5.4 Peer management from the console
// Manually connect to a peer by enode URL
admin.addPeer("enode://<pubkey>@<ip>:30303")
// Add a peer that bypasses connection limits
admin.addTrustedPeer("enode://<pubkey>@<ip>:30303")
// Remove a peer
admin.removePeer("enode://<pubkey>@<ip>:30303")
5.5 Preloading scripts and one-off execution
# Preload JS helper files into the console
geth attach --preload /path/to/helpers.js
# Execute a single statement and exit
geth attach --exec "eth.blockNumber"
Note
The standalone
geth js <file>subcommand is deprecated. Usegeth attach --execor--preloadinstead.
6. JSON-RPC, WebSocket, IPC, and GraphQL
Geth speaks JSON-RPC over four transports. Each transport is disabled by default except IPC.
6.1 Enabling the transports
| Transport | Enable flag | Default address | Default port |
|---|---|---|---|
| IPC (local socket) | enabled by default (--ipcdisable to turn off) |
<datadir>/geth.ipc |
— |
| HTTP | --http |
localhost |
8545 |
| WebSocket | --ws |
localhost |
8546 |
| GraphQL | --graphql (rides on the HTTP server) |
(HTTP address) | 8545 |
| Engine API (auth) | always on for consensus client | localhost |
8551 |
geth --mainnet \
--http --http.addr localhost --http.port 8545 --http.api eth,net,web3,txpool \
--ws --ws.addr localhost --ws.port 8546 --ws.api eth,net,web3 \
--graphql \
--authrpc.jwtsecret /etc/ethereum/jwt.hex
Important
The default API module set for HTTP and WebSocket is
net,web3only. You must explicitly list namespaces with--http.api/--ws.apito exposeeth,txpool,debug, etc. Theengineandethnamespaces are served on the authenticated port automatically for the consensus client.
6.2 Key RPC server flags
| Flag | Default | Purpose |
|---|---|---|
--http.api |
net,web3 |
Comma-separated namespaces offered over HTTP |
--http.corsdomain |
(none) | Domains allowed for cross-origin requests (browser enforced) |
--http.vhosts |
localhost |
Accepted virtual hostnames (server enforced; * wildcard) |
--http.rpcprefix |
/ |
HTTP path prefix on which JSON-RPC is served |
--ws.origins |
(none) | Origins allowed to open WebSocket connections |
--ipcpath |
geth.ipc |
IPC socket/pipe filename within the datadir |
--rpc.gascap |
50,000,000 | Gas cap for eth_call/eth_estimateGas (0 = infinite) |
--rpc.txfeecap |
1 ether | Max transaction fee allowed via RPC (0 = no cap) |
--rpc.evmtimeout |
(set) | Timeout for eth_call (0 = infinite) |
--rpc.batch-request-limit |
(set) | Maximum number of requests in a batch |
6.3 Making JSON-RPC calls
Over HTTP with curl:
curl -s -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
{"jsonrpc":"2.0","id":1,"result":"0x121eac0"}
Get an account balance:
curl -s -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"eth_getBalance","params":["0xfcad0b19bb29d4674531d6f115237e16afce377c","latest"],"id":1}'
Over IPC with the bundled tooling or any socket client:
geth attach --exec "eth.blockNumber"
6.4 GraphQL
When --graphql is set (alongside an enabled HTTP server), Geth serves a GraphQL endpoint and the interactive GraphiQL explorer:
geth --mainnet --http --graphql
# GraphQL endpoint: http://localhost:8545/graphql
# GraphiQL UI: http://localhost:8545/graphql/ui
curl -s -X POST http://localhost:8545/graphql \
-H "Content-Type: application/json" \
--data '{"query":"{ block { number hash } }"}'
Note
GraphQL can only start if the HTTP server is also started (
--http). Enabling--graphqlwithout--httphas no effect.
6.5 Environment-variable equivalents
Every Geth flag has a matching environment variable of the form GETH_<FLAG_NAME> (uppercased, dots/dashes replaced with underscores). For example, --http.port 8545 is equivalent to GETH_HTTP_PORT=8545. This is convenient for containerized deployments.
GETH_HTTP=true GETH_HTTP_API=eth,net,web3 geth --mainnet
7. Monitoring and Metrics
Geth can export operational metrics for dashboards and alerting.
geth --mainnet \
--metrics \
--metrics.addr 127.0.0.1 --metrics.port 6060
This serves metrics over HTTP. The standalone metrics server exposes:
| Path | Content |
|---|---|
/debug/metrics |
Geth's internal metrics registry (JSON) |
/debug/metrics/prometheus |
Prometheus-format metrics for scraping |
/debug/vars |
Go expvar variables |
To push metrics to InfluxDB instead of (or in addition to) scraping:
InfluxDB v1
geth --metrics --metrics.influxdb \
--metrics.influxdb.endpoint http://localhost:8086 \
--metrics.influxdb.database geth \
--metrics.influxdb.username geth --metrics.influxdb.password secret
InfluxDB v2
geth --metrics --metrics.influxdbv2 \
--metrics.influxdb.endpoint http://localhost:8086 \
--metrics.influxdb.token <token> \
--metrics.influxdb.bucket geth \
--metrics.influxdb.organization my-org
Tip
A standard monitoring stack is Geth → Prometheus (scraping
/debug/metrics/prometheus) → Grafana. The most useful health signals areeth.syncing(should befalse), peer count, and chain-head block age.
Geth also supports OpenTelemetry tracing for RPC requests via the --rpc.telemetry* family of flags (endpoint, sampling ratio, basic-auth credentials), for sites that already operate an OTLP collector.
8. Database and History Maintenance
These geth subcommands operate on the local database. Most require the node to be stopped first.
8.1 Importing and exporting blocks
# Export the canonical chain to a file
geth export /backup/chain.rlp
# Export a block range (first and last block numbers)
geth export /backup/chain.rlp 0 1000000
# Import a previously exported chain file
geth import /backup/chain.rlp
8.2 Era history archives
Geth uses Era files for compact pre-merge and historical block archives:
# Export blockchain history to Era archives
geth export-history /backup/era
# Import an Era archive
geth import-history /backup/era
# Fetch era1 files (pre-merge history) from an HTTP endpoint
geth download-era --dir /backup/era
8.3 Pruning history
# Prune block bodies and receipts up to a point (frees disk)
geth prune-history
Warning
History pruning is irreversible for the pruned range. A pruned node can no longer serve those historical bodies/receipts to peers or to local queries. Keep an archive elsewhere if you need them.
8.4 Inspecting and repairing the database
# Print genesis JSON for the configured network
geth dumpgenesis
# Dump a specific block's state
geth dump <blockHashOrNumber>
# Low-level database operations
geth db inspect-trie ...
geth db metadata
geth db check-state-content # verify state is cryptographically correct
8.5 Resetting the database
# Remove blockchain and state databases (keeps your keystore!)
geth removedb
Remove this database? [y/N]
Important
geth removedbdeletes chain and state data but does not touch yourkeystoredirectory — your accounts are safe. Afterremovedb, the node re-syncs from scratch on next start. This is the standard fix for a corrupted database.
8.6 Snapshot maintenance
geth snapshot verify-state # recompute and verify the state root against the snapshot
geth snapshot prune-state # prune stale state using the snapshot
8.7 Initializing a custom genesis
geth --datadir /srv/private init genesis.json
Caution
geth initis a destructive action that defines which network the datadir participates in. Run it only on a fresh datadir or one you intend to reinitialize.
9. Companion Tools
Building with make all produces these standalone binaries alongside geth.
9.1 abigen — Go bindings from contract ABIs
Generates type-safe Go bindings for Ethereum smart contracts.
abigen --abi token.abi --pkg main --type Token --out token.go
abigen --combined-json build/combined.json --pkg main --out contracts.go
abigen --abi token.abi --bin token.bin --pkg main --type Token --out token.go --v2
| Flag | Purpose |
|---|---|
--abi |
Path to the contract ABI JSON (- for STDIN) |
--bin |
Path to contract bytecode (generates a deploy method) |
--combined-json |
Combined-JSON output from the Solidity compiler |
--pkg |
Go package name for the generated binding (required) |
--type |
Struct name for the binding (default = package name) |
--out |
Output file (default = stdout) |
--exc |
Comma-separated types to exclude |
--alias |
Comma-separated function/event renames (orig1=alias1,...) |
--v2 |
Generate v2 bindings |
9.2 evm — standalone EVM and state-transition tool
Executes EVM bytecode and runs Ethereum state tests outside a full node.
# Run a full state transition (t8n — used by test fixtures)
evm transition --input.alloc alloc.json --input.env env.json --input.txs txs.json \
--output.result result.json
# Trace execution of EVM code
evm --trace --trace.format json run <bytecode>
| Subcommand | Purpose |
|---|---|
transition (alias t8n) |
Execute a full state transition |
verkle (alias vkt) |
Binary-trie helpers |
run |
Execute raw EVM bytecode |
Tracing flags (--trace, --trace.format json\|struct\|md, --trace.nomemory, --trace.nostack, --trace.nostorage) control the opcode-level trace output.
9.3 devp2p — P2P network diagnostics
A toolkit for the Ethereum devp2p discovery and wire protocols.
devp2p enrdump <enr> # decode an Ethereum Node Record
devp2p discv4 ping <enode> # ping a node over discovery v4
devp2p discv5 ... # discovery v5 operations
devp2p dns ... # DNS-based node-list operations
devp2p rlpx ... # RLPx transport operations
| Subcommand | Purpose |
|---|---|
enrdump |
Pretty-print an Ethereum Node Record (ENR) |
key |
Node-key utilities |
discv4 / discv5 |
Discovery protocol v4 / v5 operations |
dns |
DNS node-list tooling |
nodeset |
Manage node sets |
rlpx |
RLPx transport operations |
9.4 ethkey — offline key management
Operates on key files without a running node.
ethkey generate keyfile.json # create a new key file
ethkey inspect keyfile.json # show address / public key
ethkey signmessage keyfile.json "hello"
ethkey verifymessage <address> <signature> "hello"
ethkey changepassword keyfile.json
| Subcommand | Purpose |
|---|---|
generate |
Create a new key file |
inspect |
Print address/public key (add --json for machine output) |
signmessage |
Sign a message with the key |
verifymessage |
Verify a signed message |
changepassword |
Re-encrypt the key with a new password |
9.5 era — Era archive inspection
era block --dir ./eras --network mainnet 15000000 # print a block from an Era store
era info --dir ./eras 1000 # epoch information
era verify --dir ./eras roots.txt # verify against expected accumulator roots
9.6 rlpdump — decode RLP
Pretty-prints RLP-encoded data (the encoding Ethereum uses for blocks, transactions, and network messages).
echo "0xc20102" | rlpdump
9.7 abidump — interpret ABI calldata
Decodes raw transaction calldata against the bundled 4byte signature database.
abidump a9059cbb000000000000000000000000ea0e2dc7d65a50e77fc7e84bff3fd2a9e781ff5c0000000000000000000000000000000000000000000000015af1d78b58c40000
Info: transfer(address to, uint256 value)
9.8 blsync — beacon light client
Drives Geth's Engine API from a beacon-chain light client, useful for testing the execution client without a full consensus node:
blsync --mainnet \
--beacon.api https://beacon.example.com \
--blsync.engine.api http://localhost:8551 \
--blsync.jwtsecret /etc/ethereum/jwt.hex
Note
Without
--blsync.engine.api,blsyncperforms a dry run (it follows the beacon chain but does not drive an execution client).
9.9 workload and fetchpayload
workload runs RPC workload/benchmark queries against a node; fetchpayload fetches an Engine-API payload. Both are development and testing utilities rather than everyday operational tools.
10. Common Tasks (Recipes)
10.1 Run a fully-validating mainnet node
# 1. JWT secret
openssl rand -hex 32 | tr -d "\n" > /etc/ethereum/jwt.hex
# 2. Geth (execution layer)
geth --mainnet \
--datadir /srv/geth \
--http --http.api eth,net,web3 --http.addr 127.0.0.1 \
--authrpc.jwtsecret /etc/ethereum/jwt.hex \
--metrics --metrics.addr 127.0.0.1
# 3. Start your consensus client pointed at http://localhost:8551 with the same jwt.hex
10.2 Query an address balance without writing code
geth attach --exec 'web3.fromWei(eth.getBalance("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"),"ether")'
10.3 Watch sync progress
watch -n 5 'geth attach --exec "eth.syncing"'
10.4 Run a private network
# On every node:
geth --datadir ./node1 init genesis.json
geth --datadir ./node1 --networkid 12345 \
--nodiscover --http --http.api eth,net,web3,admin \
--port 30303
# Connect nodes manually with admin.addPeer(...) from the console
10.5 Generate Go bindings for a contract and use them
solc --combined-json abi,bin Token.sol > build/Token.json
abigen --combined-json build/Token.json --pkg contracts --out contracts/token.go
10.6 Back up and restore accounts
# Back up: copy the keystore directory (and remember each password!)
cp -r ~/.ethereum/keystore /backup/keystore
# Restore: place files back; Geth picks them up automatically
cp -r /backup/keystore ~/.ethereum/
Tip
The keystore directory is portable between nodes and platforms — copying it is the entire backup. The password is not stored in the file; back it up separately and securely.
11. How It Works (Concepts)
A brief conceptual model; for architecture and internals see the Admin Guide.
11.1 Execution layer vs. consensus layer
Since The Merge, Ethereum runs on two cooperating clients per node:
- Execution layer (Geth): maintains the account/state database, mempool, and EVM; executes transactions; serves user JSON-RPC.
- Consensus layer (beacon node): runs proof-of-stake, attests, and tells the execution client which block is canonical.
They communicate over the Engine API (authenticated, port 8551). The consensus client sends engine_forkchoiceUpdated and engine_newPayload calls; Geth executes and validates the payloads.
11.2 Snap sync
Snap sync downloads a recent snapshot of account and storage state directly from peers (the snap protocol), rather than re-executing every historical block. This is why a fresh node reaches the head in hours instead of weeks. After state arrives, Geth backfills block bodies and switches to full validation.
11.3 State storage: path vs. hash scheme
Geth's modern default is the path-based state scheme (--state.scheme path), which stores trie nodes by path and supports efficient online pruning of historical state. The legacy hash-based scheme keys nodes by hash. The scheme is chosen at database creation and is not toggled live.
11.4 Securing your node
Caution
The JSON-RPC interface is powerful. Anyone who can reach an exposed
eth/debug/adminendpoint can read your node's data and submit transactions. Follow these rules:
- Keep
--http.addr/--ws.addrbound tolocalhostunless you have a firewall and reverse proxy in front.- Never expose
adminordebugnamespaces to untrusted networks.- Protect the Engine API JWT secret file (
chmod 600); it authenticates your consensus client.- Use
--http.vhosts/--http.corsdomainto restrict which hosts and origins may call the node.- Account passwords and keystore files are your funds — back them up offline and never share them.
12. Troubleshooting
Errors below are formatted as the message Geth prints, its cause, the fix, and how to prevent recurrence.
Error: Post-merge network, but no beacon client seen. Please launch one to follow the chain!
- Cause: Geth is running on a post-merge network with no consensus client attached to the Engine API.
- Solution: Start a consensus-layer client (Lighthouse, Prysm, Teku, Nimbus, Lodestar, or
blsyncfor testing) pointed at Geth's--authrpc.port(8551) with the same JWT secret. - Prevention: Always run a consensus client alongside Geth on mainnet and testnets.
Error: Failed to read JWT secret / consensus client cannot authenticate
- Cause: Geth and the consensus client are using different JWT secret files, or the file is missing/unreadable.
- Solution: Generate one secret (
openssl rand -hex 32 | tr -d "\n" > jwt.hex) and pass the same path to both via--authrpc.jwtsecret(Geth) and your CL's equivalent flag. - Prevention: Specify the JWT path explicitly on both clients rather than relying on the auto-generated
<datadir>/geth/jwtsecret.
Error: Fatal: Failed to load the private key: invalid character '...' at end of key file
- Cause:
geth account importwas given a file that is not a clean hex private key (extra characters, trailing newline issues, or a keystore JSON instead of a raw key). - Solution: Ensure the file contains only the 64-hex-character private key. Use
ethkey inspectto validate a key file. - Prevention: Export raw keys carefully; for keystore files use the keystore directory directly rather than
account import.
Error: could not decrypt key with given password
- Cause: Wrong password for the keystore file during
wallet import,account update, or unlocking. - Solution: Re-enter the correct password. There is no recovery if the password is lost — the key is unrecoverable without it.
- Prevention: Store account passwords in a secure password manager at creation time.
Error: Fatal: Passwords do not match
- Cause: The two password entries during
account new/account updatediffered. - Solution: Re-run and enter the same password both times.
Symptom: Node stuck at Looking for peers / peercount=0
- Cause: P2P port blocked, NAT misconfiguration, or no reachable bootnodes.
- Solution: Open TCP and UDP port
30303on your firewall/router. Set--nat extip:<your-public-ip>if behind NAT, or--nat upnp/--nat pmpfor automatic mapping. - Prevention: Forward port
30303(both protocols) when running behind a router.
Symptom: Sync never completes / eth.syncing keeps moving but head never reached
- Cause: Slow disk (HDD), insufficient peers, or no consensus client driving fork choice.
- Solution: Move chain data to NVMe/SSD; ensure a consensus client is attached; verify peer count is healthy (
net.peerCount). - Prevention: Always run on fast storage and keep the consensus client running.
Error: database contains incompatible genesis / wrong network on start
- Cause: The datadir was initialized for a different network or genesis than the flag you passed.
- Solution: Use a separate
--datadirper network, orgeth removedband re-init/re-sync for the intended network. - Prevention: Keep one datadir per network.
Symptom: Node shuts down with a low-disk message
- Cause: Free disk space dropped below
--datadir.minfreedisk(MB), triggering Geth's auto-shutdown protection. - Solution: Free space or move chain data to a larger volume; consider
--gcmode full(not archive) and history pruning. - Prevention: Provision generous storage headroom and monitor free space.
Symptom: Slow startup with a long state-recovery rewind after a crash
- Cause: Geth was killed ungracefully (
kill -9or power loss), leaving the trie cache unflushed. - Solution: Let the recovery complete; it rewinds to the last flushed state and replays. If the database is corrupt,
geth removedband re-sync. - Prevention: Always shut Geth down with
Ctrl-C/SIGTERMand allow it to finish.
Error: exceeds block gas limit / gas required exceeds allowance on eth_call
- Cause: A call or estimate exceeded the RPC gas cap (
--rpc.gascap, default 50,000,000). - Solution: Raise
--rpc.gascap(or set0for unlimited) if you genuinely need larger calls; otherwise review the call. - Prevention: Keep call gas within sane bounds; raise the cap deliberately.
Error: method <name> does not exist/is not available
- Cause: The namespace for that method was not exposed on the transport you called.
- Solution: Add the namespace to
--http.api/--ws.api(e.g. includedebugortxpool), or usegeth attachover IPC which exposes local namespaces. - Prevention: Enumerate the namespaces you need when enabling HTTP/WS.
13. Frequently Asked Questions
Q: Is Geth a complete Ethereum node by itself? No. Geth is the execution-layer client. Since The Merge you must also run a consensus-layer (beacon) client connected over the Engine API. Geth alone will not follow the chain head.
Q: Which consensus clients work with Geth?
Any standards-compliant consensus client — Lighthouse, Prysm, Teku, Nimbus, or Lodestar — connected to Geth's --authrpc endpoint with a shared JWT secret. For testing, the bundled blsync light client can drive the Engine API.
Q: What's the difference between snap and full sync?
snap (default) downloads recent state directly from peers and reaches the head fastest. full re-executes every block from genesis, rebuilding state locally. Neither, by itself, keeps all historical state — that's what archive mode is for.
Q: How do I run an archive node?
geth --syncmode full --gcmode archive. Expect much larger disk usage and longer sync. Only needed for historical-state queries.
Q: Where are my accounts stored?
In <datadir>/keystore as encrypted JSON files. Back up that directory (and remember each password). The directory is portable between nodes.
Q: Can I unlock an account over RPC like older Geth versions?
No. The personal RPC namespace has been removed. Sign with an external signer (--signer), a hardware wallet, or manage keys offline with ethkey.
Q: What ports does Geth use?
P2P: 30303 (TCP+UDP). HTTP-RPC: 8545. WebSocket: 8546. Engine API (auth): 8551. Metrics: 6060 (when enabled with --metrics.port).
Q: How do I expose RPC to another machine safely?
Bind --http.addr 0.0.0.0 only behind a firewall/reverse proxy, restrict --http.vhosts and --http.corsdomain, expose only the eth,net,web3 namespaces, and never expose admin/debug publicly.
Q: Which networks does Geth support out of the box?
Mainnet plus the Sepolia, Holesky, and Hoodi proof-of-stake test networks, and an ephemeral --dev PoA network. Older testnets (Goerli, Rinkeby, Ropsten) are no longer included.
Q: How do I reset a corrupted database without losing my accounts?
geth removedb. It deletes chain/state data but leaves the keystore directory intact, then re-syncs on next start.
Q: What is the era / --datadir.era directory?
Era files are compact archives of historical (largely pre-merge) blocks. You can export/import them with geth export-history/import-history and fetch them with geth download-era. Storing them on a separate volume via --datadir.era keeps the main database lean.
Q: How do I generate Go code to interact with a contract?
Use abigen with the contract ABI (and optionally bytecode) to produce a type-safe Go binding.
Q: Does Geth still mine?
Geth does not perform proof-of-work mining. On a post-merge network the consensus client requests block payloads and Geth's payload builder constructs them. The miner.* flags configure block-building parameters (gas ceiling, extra data, fee recipient), not PoW mining.
Q: How do I see what my node is doing in real time?
Watch the logs, or geth attach and inspect eth.syncing, eth.blockNumber, net.peerCount, txpool.status, and admin.peers.
14. Command and Flag Reference
14.1 geth subcommands
| Subcommand | Purpose |
|---|---|
account |
Manage accounts (list, new, update, import) |
wallet |
Manage presale wallets (import) |
init |
Bootstrap and initialize a new genesis block |
dumpgenesis |
Dump the genesis JSON configuration to stdout |
import / export |
Import/export the blockchain to/from a file |
import-history / export-history |
Import/export Era history archives |
download-era |
Fetch era1 (pre-merge history) files over HTTP |
import-preimages |
Import the preimage database from an RLP stream |
prune-history |
Prune block bodies and receipts up to a point |
dump |
Dump a specific block's state from storage |
console |
Start a node and open an interactive JS console |
attach |
Attach a JS console to a running node |
js |
(Deprecated) Execute JavaScript files |
db |
Low-level database operations (metadata, inspect-trie, check-state-content, delete, put, inspect-history, …) |
removedb |
Remove blockchain and state databases (keeps keystore) |
snapshot |
Snapshot maintenance (prune-state, verify-state, …) |
bintrie |
Binary-trie operations (convert) |
version / license |
Print version / license information |
dumpconfig |
Dump the effective configuration as TOML |
show-deprecated-flags |
List deprecated flags |
14.2 Most-used flags
| Flag | Default | Purpose |
|---|---|---|
--datadir <dir> |
platform-specific | Data directory for databases and keystore |
--mainnet / --sepolia / --holesky / --hoodi |
--mainnet |
Select a pre-configured network |
--dev |
off | Ephemeral developer PoA network |
--networkid <int> |
mainnet ID | Custom network ID |
--syncmode <mode> |
snap |
snap or full |
--gcmode <mode> |
full |
full (prune) or archive (keep all state) |
--http |
off | Enable HTTP-RPC server |
--http.api <list> |
net,web3 |
Namespaces over HTTP |
--ws |
off | Enable WebSocket-RPC server |
--graphql |
off | Enable GraphQL (needs --http) |
--authrpc.jwtsecret <file> |
auto | JWT secret for the Engine API |
--authrpc.port <port> |
8551 |
Engine API port |
--port <port> |
30303 |
P2P listening port |
--bootnodes <enodes> |
network default | Comma-separated bootstrap enode URLs |
--nat <spec> |
any |
NAT mapping (any|none|upnp|pmp|extip:<IP>|stun:<IP:PORT>) |
--maxpeers <n> |
50 | Maximum network peers (0 disables networking) |
--metrics |
off | Enable metrics collection |
--cache <MB> |
1024 (varies) | Megabytes of memory for internal caching |
--verbosity <0-5> |
3 | Logging verbosity (via debug flags) |
14.3 Default ports
| Service | Port | Protocol |
|---|---|---|
| P2P (discovery + transport) | 30303 |
TCP + UDP |
| HTTP-RPC | 8545 |
TCP |
| WebSocket-RPC | 8546 |
TCP |
| Engine API (authenticated) | 8551 |
TCP |
| Metrics (when enabled) | 6060 |
TCP |
14.4 RPC / console namespaces
| Namespace | Console | Description |
|---|---|---|
eth |
✓ | Core chain, accounts, transactions, calls |
net |
✓ | Network/peer info |
web3 |
✓ | Client version and utility helpers |
txpool |
✓ | Transaction pool inspection |
debug |
✓ | Tracing, state dumps, profiling |
admin |
✓ | Node and peer management |
miner |
✓ | Block-building parameters |
clique |
✓ | PoA signer management (clique networks) |
engine |
— | Engine API (authenticated port, for the consensus client) |
rpc |
✓ | RPC module listing |