Co-authored-by: Cursor <cursoragent@cursor.com>
Besu Node Lists — Single Source of Truth
Purpose: One canonical static-nodes.json and permissions-nodes.toml used by all Chain 138 Besu nodes (validators, sentries, RPCs). Both are essential:
- static-nodes.json — Bootstrap peers; Besu connects to these on startup (
static-nodes-file). - permissions-nodes.toml — Allowlist; only nodes in this list can join the network (
permissions-nodes-config-file). Besu expects TOML (do not usepermissioned-nodes.json).
These files must be identical on every node for permissioning and discovery to work correctly.
Deploy: Run from repo root:
./scripts/deploy-besu-node-lists-to-all.sh
See docs/06-besu/MASTER_DOCS_AND_NODE_LISTS_REVIEW.md for context and BESU_NODES_FILE_REFERENCE.md for VMID↔IP mapping.
Contents
| File | Format | Use |
|---|---|---|
static-nodes.json |
JSON array of enode URLs | Besu --static-nodes-file; bootstrap peers |
permissions-nodes.toml |
TOML nodes-allowlist=[...] |
Besu --permissions-nodes-config-file; allowlist (Besu expects TOML—do not use permissioned-nodes.json) |
When to update
- New node (e.g. 1504, 2102): Get the node’s enode (e.g. from
admin_nodeInfoor the node’s data dir), add it to both files here, then run the deploy script. - Node removed: Remove its enode from both files and redeploy.
- Regenerate all (no duplicates): Run
bash scripts/besu/collect-enodes-from-all-besu-nodes.shto collect from every node (admin_nodeInfo orbesu public-key export), merge with existing for unreachable nodes, and overwrite both files. - Fix failures only: Run
bash scripts/besu/collect-enodes-from-all-besu-nodes.sh --missing-onlyto try only VMIDs whose IP is not yet in the list (no full 32-node sweep). - Generate missing node keys: Run
bash scripts/besu/generate-node-keys-for-missing-vmids.sh [--force] [--collect]to create/data/besu/key(64-hex) only for VMIDs not yet in the list. Use--forceto overwrite PEM/wrong-format keys; use--collectto run collect --missing-only after. Containers without Besu (1505–1508, 2501–2505) are supported via helper nodes (1504 on ml110, 2500 on r630-01). - Install Besu permanently on nodes missing it: Run
bash scripts/besu/install-besu-permanent-on-missing-nodes.shto install Besu (23.10.3) in 1505–1508 and 2501–2505, deploy config/genesis/node lists, and enable+start the service so RPC/sentry runs after reboot.
Sentry 1504 (.154)
1504 may not expose RPC (8545). Once the sentry has run and created /data/besu/nodekey, get the enode from the nodekey (run from Proxmox host ml110):
ssh root@192.168.11.10 "pct exec 1504 -- /opt/besu/bin/besu public-key export --node-private-key-file=/data/besu/nodekey --format=enode 2>/dev/null" | sed 's/@[0-9.]*:/@192.168.11.154:/'
If RPC is enabled on 1504:
ssh root@192.168.11.10 "pct exec 1504 -- curl -s -X POST -H 'Content-Type: application/json' --data '{\"jsonrpc\":\"2.0\",\"method\":\"admin_nodeInfo\",\"params\":[],\"id\":1}' http://127.0.0.1:8545" | jq -r '.result.enode'
Add the enode to both static-nodes.json and permissions-nodes.toml, then run ./scripts/deploy-besu-node-lists-to-all.sh.
RPC Core-2 (2102 / .212)
When VMID 2102 is created and Besu RPC is running, add its enode to both files and redeploy. See RPC_CORE_2_NATHAN_SFVALLEY2_TUNNEL.md.
Verify enodes and IPs
Run from repo root to ensure enode addresses and IPs are correct and consistent:
bash scripts/verify/verify-besu-enodes-and-ips.sh
This checks: (1) static-nodes.json and permissions-nodes.toml match, (2) each IP matches the expected VMID, (3) no duplicate node keys (same key for two IPs). See ENODE_IP_VERIFICATION_20260208.md for a recent run and how to fix the VMID 2401 duplicate enode.