Skip to content

Bootstrap

Bootstrap nodes help new nodes join the network, while static peers provide guaranteed connections. This chapter covers bootnodes, seeds, persistent peers, and how to pin your node to a trusted peer set — plus how that differs across ecosystems.


Bootnodes are well-known, long-running nodes that help new nodes discover peers. They are the “phone book” of a P2P network: a new node knows a few bootnodes’ addresses out-of-band (hardcoded or configured), asks them for peers, and then leaves.

NEW NODE BOOTNODE PEER NETWORK
│ │ │
│ 1. "Who do you know?" │ │
├───────────────────────────▶│ │
│ │ 2. share peer table │
│◀───────────────────────────┤ │
│ 3. connect directly │ │
├──────────────────────────────────────────────────────────▶│
│ 4. discovery continues via 5. bootnode drops out │
│ DiscV5 / gossip (connection no longer needed)
Terminal window
# geth: pass one or more bootnode ENRs
geth --bootnodes "enr:-KG4QOtcL...@bootnode.mainnet.ethdisco.net:30303"
# Multiple bootnodes
geth --bootnodes \
"enr:...@node1:30303,enr:...@node2:30303,enr:...@node3:30303"
TermEcosystemMeaning
BootnodeEthereumKnown ENRs for initial DiscV5 bootstrap
SeedCosmos/CometBFT, BitcoinKnown node addresses in config.toml / -seednode that provide peer lists
EntrypointSolanaHardcoded gossip addresses (--entrypoint entrypoint.mainnet-beta.solana.com:8001)
Well-known peersPolkadotNodes shipped in chain_spec for bootstrapping

  • Guaranteed connectivity (independent of discovery)
  • Useful for private networks and sentry→validator links
  • Backup peers when discovery is unreliable

Geth loads static peers from static-nodes.json in the data directory (there is no config.toml for this — and --staticnodes is not a geth flag):

Terminal window
# <datadir>/geth/static-nodes.json
# (plain JSON array of enode:// or enr:// URLs)
echo '["enode://abc123...@peer1:30303","enode://def456...@peer2:30303"]' \
> /data/ethereum/geth/static-nodes.json
# For older geth versions the file is <datadir>/static-nodes.json
Terminal window
geth attach http://localhost:8545
> admin.addPeer("enode://abc123...@peer1:30303")
# → true
> admin.peers

config.toml — persistent_peers are kept regardless of discovery; the sentry architecture depends on them:

~/.gaia/config/config.toml
[p2p]
seeds = "id@seed1:26656,id@seed2:26656"
persistent_peers = "id@sentry1:26656,id@sentry2:26656"
pex = true # false on a validator behind sentries

bitcoin.conf — -addnode forces a connection even if the peer isn’t useful; -connect restricts to ONLY those peers:

# bitcoin.conf
# Add a trusted peer (will try to keep both directions)
addnode=1.2.3.4:8333
# Restrict all connections to these (private/regtest style):
# connect=1.2.3.4:8333

Solana nodes “trust” --known-validator addresses for snapshot + gossip bootstrap instead of persistent peers:

Terminal window
solana-validator --entrypoint entrypoint.mainnet-beta.solana.com:8001 \
--known-validator <KNOWN_VALIDATOR_PUBKEY>

  • Always configure multiple bootnodes/seeds — a single hardcoded address is a single point of failure (and a trust risk if compromised).
  • Verify the address format before pasting: enode://<pubkey>@ip:port / enr: for Ethereum, id@host:26656 for Cosmos.
  • Private networks & sentries: use static/persistent peers + disable discovery (--nodiscover, pex = false) so only your controlled peers join.
  • After changing peer config, verify with admin.peers (geth) or curl localhost:26657/net_info (Cosmos) before declaring the node healthy.

  • Bootnodes for initial peer discovery
  • Static peers for guaranteed connections
  • Use multiple for redundancy
  • Ethereum: static-nodes.json or admin.addPeer (no --staticnodes flag)
  • Cosmos: seeds + persistent_peers in config.toml
  • Bitcoin: addnode / connect; Solana: --entrypoint + --known-validator

Last Updated: 2026-09-28