Skip to content

RPC / full node (L5)

An RPC node is a non-validating full node — the L5 fleet that serves eth_getProof (EIP-1186) and JSON-RPC to wallets, dApps, the block explorer, and the edge / light clients that verify their reads against it. It runs the same beacond + bera-reth stack as a validator but with PAYLOAD_BUILDER=false and no signing key. This page covers install → deploy → operate on the public testnet (chain-id 473374).

It serves edge/light clients

Edge nodes are verifying light clients — they hold no state and fetch proofs from this fleet. Your node must serve CometBFT RPC (/status, /commit, /block) and EL eth_getProof at the needed depth on a fixed, reachable address. See Edge node.

Hardware

vCPURAMDiskAWSBaremetal
832 GB1–2 TB NVMe (pruned; archive = larger)m6i.2xlarge + gp3/io2 1–2 TB8-core, 32–64 GB, 2 TB NVMe

A non-validating node tolerates restarts and a residential line — you can run one cheaply at home behind a VPN tunnel. The EL state under DATA_DIR/el grows continuously; archive RPC nodes (EL_SYNC_MODE= empty) grow much larger — provision 1–2 TB and expect to expand. Full matrix and cost tiers: Hardware specs.

Install

Every host needs the shared base — see Prerequisites: Docker Engine + Compose v2, an NVMe volume at DATA_DIR, NTP time-sync, a host firewall, and the non-root UID (10000:10000).

bash
git clone https://github.com/foreseerco/block-l1-evm-mainnet krypton
sudo mkdir -p /opt/krypton/deploy
sudo cp krypton/l1/from-source/deploy/{docker-compose.yml,.env.example,bootstrap.sh,nftables.conf,krypton-node.service} /opt/krypton/deploy/
cd /opt/krypton/deploy
sudo cp .env.example .env

Images (pin by @sha256 digest in production — see Building the images):

LayerImage
CLghcr.io/foreseerco/krypton-beacond:v1.3.9-473374
ELghcr.io/foreseerco/krypton-bera-reth:v1.3.3

Deploy

An RPC node always joins an existing testnet — it never runs the genesis ceremony and holds no validator key. You need the published bundle URL and the EL_BOOTNODES / CL_SEEDS peer strings. See Genesis & the network bundle.

Configure .env (rpc preset)

Set the shared core (MONIKER, EXT_IP, EL_BOOTNODES, CL_SEEDS, paths), then uncomment the rpc preset:

VarValueWhy
KRYPTON_ROLErpcdocumentation only
PAYLOAD_BUILDERfalsenon-validating
RPC_HOSTa VPN/WireGuard addr (e.g. 10.8.0.5)never a public IP
RPC_APIeth,net,web3,debugthe public wallet/dApp namespace
EL_SYNC_MODE--full, or empty for archivearchive serves deep historical proofs
EL_MEM_LIMIT24gper the HW matrix
CL_MEM_LIMIT6g

Never expose JSON-RPC publicly

The RPC node's 8545 is bound to RPC_HOST — a VPN/WireGuard or peered-subnet address only, never 0.0.0.0 on a public host without auth. The firewall intentionally does not open 8545. Front public access with a reverse proxy / auth gateway, not a raw public bind. See TLS / reverse proxy (Caddy) and Ports & firewall.

Bring it up

bash
BUNDLE_URL=https://…/krypton-testnet-bundle.tar.gz sudo -E ./bootstrap.sh
# then run under systemd:
sudo cp krypton-node.service /etc/systemd/system/
sudo systemctl daemon-reload && sudo systemctl enable --now krypton-node
journalctl -u krypton-node -f

The explorer's indexer node is separate

The public wallet/dApp RPC above and the RPC node that backs the block explorer (Blockscout @ kryscan.com) are not the same node.

Indexer node: private, archive, trace-enabled

Blockscout deploys against a separate RPC node that is:

  • Archive (EL_SYNC_MODE= empty) — full historical state, much larger disk.
  • Trace-enabledRPC_API=eth,net,web3,debug,trace (the trace/debug namespaces, which the public wallet RPC does not expose).
  • Private — reachable only by the explorer stack, not the public, and provisioned with extra headroom because Blockscout is RPC-heavy.

Do not point public wallet traffic at the indexer node, and do not expose trace on the public RPC. See Block explorer.

Operate

Config recap

  • Public RPC: pruned or archive as needed, RPC_API=eth,net,web3,debug, bound to a VPN address.
  • Indexer RPC (explorer only): archive + trace, private.
  • Both keep CometBFT RPC (26657) on loopback and metrics (9001) private.

Monitoring signals

See Monitoring for the Prometheus + Grafana stack. Quick checks (run from the VPN side for the RPC bind):

SignalCommandHealthy
Synccurl -s http://127.0.0.1:26657/status | jq '.result.sync_info'catching_up: false, height climbing
Peers (CL)curl -s http://127.0.0.1:26657/net_info | jq '.result.n_peers'> 0, stable
EL heightcast block-number --rpc-url http://<rpc-bind>:8545climbing
Chain-idcast chain-id --rpc-url http://<rpc-bind>:8545473374
eth_getProofa proof request at your serving depthreturns a proof, not an error

The compose healthchecks (EL: tool-free TCP connect to 8551; CL: curl /health) are visible via docker compose ps. Logs are JSON-file, rotated 20m × 5.

Upgrade & rollback

Same coordinated, pinned-digest flow as any node: edit KRYPTON_CL_IMAGE / KRYPTON_EL_IMAGE in .env to the agreed digests, then sudo systemctl restart krypton-node. Stop order is CL first, then EL:

bash
docker compose stop cl      # 5m grace
docker compose stop el      # 2m grace

Rollback: revert the digests and restart. An RPC node holds no key, so there is no double-sign hazard — but archive nodes re-sync slowly, so avoid unnecessary head rollbacks.

Troubleshooting

SymptomLikely causeFix
No peersWrong EXT_IP; firewall; bad bootnodes/seedsConfirm EXT_IP; open 30303 tcp+udp + 26656 tcp; recheck peer strings
Stuck syncFew peers; slow disk; EL behindCheck peers; confirm NVMe; check EL logs for MDBX/IO errors
eth_getProof errors on old blocksNode is pruned, not archiveRun archive (EL_SYNC_MODE= empty) if serving deep historical proofs
Engine auth 401sEL/CL JWT mismatchBoth mount the same JWT_PATH; restart both; 0600/correct owner
EL OOM / restartsEL_MEM_LIMIT too low; archive disk fullRaise mem per matrix; expand the NVMe; on AWS use gp3/io2
RPC unreachable from a client8545 bound to loopback, or VPN downSet RPC_HOST to the VPN addr; confirm the WireGuard interface is up

More in Troubleshooting.

Security

  • Public surface is only the P2P ports (30303, 26656). JSON-RPC (8545) goes behind a VPN/WireGuard bind — never a public 0.0.0.0/0 rule. Engine API (8551), CometBFT RPC (26657), and metrics (9001) stay loopback/VPN-only. See Ports & firewall.
  • Containers run as a non-root UID; DATA_DIR is 0700; the JWT is 0600; the bundle is mounted read-only; images pinned by digest; SSH to an admin CIDR.
  • The trace/debug namespaces are powerful — keep trace to the private indexer node and gate even debug behind the VPN.

Status

These deploy artifacts are config-validated but not yet run end-to-end on real cloud/baremetal hardware. Treat your first RPC node as a bring-up — verify chain-id, peers, sync, and a sample eth_getProof before edge/light clients rely on it. Mainnet (47337) reuses this procedure post-audit. See Networks & chain IDs.

Operator docs. Testnet chain-id 473374; mainnet 47337 (gated on external audit). Not financial advice.