133 Commits

Author SHA1 Message Date
9f6ca383ac linea-mainnet: disable eth_getProof on pruned geth upstream for rpc-us-40
DRPC gateway probes eth_getProof and marks the upstream 81% unavailable
when the pruned geth node returns 'header not found'. This is a false
positive - the node is healthy and advancing. Disable eth_getProof on the
linea pruned geth upstream to prevent DRPC from marking it unavailable.

Mirrors the existing pattern for BSC minimal in rpc-us-41.yaml.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-21 15:13:02 +00:00
d2c2de7341 deploy: regenerate compose from vibe-node main ed4a4cd8a117 2026-06-21 10:52:36 +00:00
d9d8920752 xlayer-mainnet: set OP_NODE_L2_SKIP_SYNC_START_CHECK=false for op-node v0.1.5.1
In xlayer/op-node:v0.1.5.1, the =true path triggers an infinite
'Found highest L2 block with canonical L1 origin. Skip further sanity check
and jump to the safe head' loop that prevents block derivation entirely.
Setting =false restores normal startup: op-node advances through the check
and begins deriving blocks. No newer op-node image exists (v0.1.5.1 is latest).

Affects all xlayer-mainnet op-node variants (geth, reth) as they share
the same op-node consensus layer.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-21 09:19:43 +00:00
1758c921d7 deploy: regenerate compose from vibe-node main ed38c887a775 2026-06-21 06:52:38 +00:00
f7b585307e lisk/mainnet: add isthmusTime, jovianTime, karstTime fork timestamps to genesis.json 2026-06-21 06:03:35 +00:00
39df507eee deploy: regenerate compose from vibe-node main 7ab720b29b61 2026-06-21 01:24:43 +00:00
9e666ca476 starknet: bump pathfinder v0.22.3→v0.22.6
Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-20 22:41:24 +00:00
f713744bb8 deploy: regenerate compose from vibe-node main 9920718c233e 2026-06-20 13:05:30 +00:00
377d3af961 deploy: regenerate compose from vibe-node main 15f7736e5719 2026-06-20 08:30:13 +00:00
sebastian
a54459e55f Merge pull request 'shibarium heimdall: fix REST listen flag (--laddr not --rest-server.addr)' (#17) from shibarium-heimdall-restflag into main
Reviewed-on: #17
2026-06-20 04:41:36 +00:00
rob
25b0ab049c shibarium heimdall: fix REST listen-address flag (--laddr, not --rest-server.addr)
heimdall crash-looped on 'unknown flag: --rest-server.addr'. Per heimdalld start
--help, the bone-fork binary takes --rest-server (bool) to enable REST/LCD and
--laddr (default tcp://0.0.0.0:1317) for its listen address — there is no
--rest-server.addr. Swap it. (The rest_server-injection + idempotent-init fixes
from the prior PR worked: init now skips re-init, fetches the heimdall-109 genesis,
no more 'rest_server already defined'.)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 04:30:59 +00:00
8471404897 deploy: regenerate compose from vibe-node main 2b1459ec36c8 2026-06-20 04:22:01 +00:00
rob
39d2fa93e2 shibarium heimdall init.sh: stop injecting rest_server (crash fix) + idempotent init
heimdall crash-looped on 'toml: key rest_server is already defined'. init.sh
inserted 'rest_server = true' after [rpc] on EVERY boot (non-idempotent), piling up
duplicates; rest_server is not a valid CometBFT config.toml key anyway — REST is
enabled by the --rest-server flag in the start command.

- Remove the rest_server / rest_server_addr config injection.
- Self-heal: strip any previously-injected rest_server lines (so already-corrupted
  volumes recover on next boot — no volume wipe needed).
- Guard heimdalld init to first boot only (config.toml absent) so restarts don't
  reset node identity or re-parse the existing config.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 03:24:37 +00:00
fb3dc6214c deploy: regenerate compose from vibe-node main 388142ccafa4 2026-06-20 03:01:11 +00:00
rob
9fc368f405 shibarium: build heimdall from source (cometbft.Dockerfile)
A parallel change reverted this to FROM shibaone/heimdall:v1.0.7-bone — an image
that exists on no registry, so the heimdall build fails. Restore the source build:
clone shibaone/heimdall@${CL_VERSION}, make install, then layer the CometBFT init
entrypoint. Pairs with vibe-node PR (node_build + standalone service name).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 02:56:17 +00:00
6ce0fc2346 deploy: regenerate compose from vibe-node main c66ad823f9e3 2026-06-20 00:58:03 +00:00
7ce0428db4 erigon3: bump Dockerfile VERSION from v3.0.7 to v3.4.4 2026-06-19 16:36:18 +00:00
b72cf641a9 deploy: regenerate compose from vibe-node main 666f653d478a 2026-06-19 16:03:20 +00:00
5891d050f9 deploy: regenerate compose from vibe-node main 59f3f7f3cf2e 2026-06-19 14:40:16 +00:00
196744cf4f deploy: regenerate compose from vibe-node main 276ea4d82e62 2026-06-19 14:29:52 +00:00
rob
4dd902e9af Merge branch 'issue-63' 2026-06-19 14:19:50 +00:00
a7e9d4a65d deploy: regenerate compose from vibe-node main 60976572a3c4 2026-06-19 13:05:25 +00:00
sebastian
8c46b66bdc Merge pull request 'shibarium: build bor + heimdall from source (bone fork, chain 109)' (#12) from shibarium-bone-fork-fix into main
Reviewed-on: #12
2026-06-19 13:02:00 +00:00
rob
ee21a0245e shibarium: build bor + heimdall from source (no published images)
shibaone ships no docker images for the bone fork — only source + .deb config
packages — so both Dockerfiles must clone+build, not FROM a (nonexistent) image.

- bor.Dockerfile: clone shibaone/bor@${BOR_VERSION}, make bor, cp build/bin/bor
  (was: alpine + wrong /src/build/bor path). golang:1.22.1 like upstream.
- cometbft.Dockerfile: clone shibaone/heimdall@${CL_VERSION}, make install
  (was: FROM shibaone/heimdall:v1.0.7-bone — that tag does not exist on any
  registry), then layer the CometBFT init entrypoint.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 11:46:00 +00:00
65695472f1 shibarium: set heimdall CL_VERSION to v1.0.7-bone in cometbft.Dockerfile 2026-06-19 11:20:45 +00:00
bda550eef6 shibarium: add bone fork build-from-source assets
- Update heimdall init.sh with heimdall-109 chain_id and mainnet seeds
- Update cometbft.Dockerfile with v1.0.7-bone version
- Add bor.Dockerfile for building shibaone/bor from source at v1.3.9-bone

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-19 11:05:34 +00:00
59ff415fdb cronos: add mainnet EVM chain (chain-id 25) as client-type node
Add cronosd cometbft.Dockerfile and init.sh for Cronos EVM mainnet.
- Dockerfile: layer cometbft-common.sh + init.sh onto upstream cronos image
- init.sh: adapted from haqq pattern with EVM JSON-RPC on 8545, WS on 8546,
  CometBFT RPC on 26657, P2P on 10521, chain-id cronosmainnet_25-1
- Statesync via ct_configure_statesync, genesis from official repo
- Pruning: custom with keep-recent=100, interval=19

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-19 09:35:50 +00:00
efcb1f451a deploy: regenerate compose from vibe-node main 0fd15005e080 2026-06-19 09:22:31 +00:00
ee13d0dd23 deploy: regenerate compose from vibe-node main e5b5567e535a 2026-06-19 06:48:10 +00:00
6d8920d659 deploy: regenerate compose from vibe-node main fb44bc5499e8 2026-06-19 06:28:21 +00:00
sebastian
5076c90a12 Merge pull request 'Bump reth latest→v2.1.0' (#10) from vupd/53-reth-v2.1.0 into main
Reviewed-on: #10
2026-06-19 06:23:20 +00:00
bcdd950eb6 reth: bump Dockerfile RETH_VERSION from v1.4.3 to v2.1.0 2026-06-19 05:36:38 +00:00
a17a21b55f shibarium: add heimdall node ASSET (cometbft.Dockerfile, init.sh) 2026-06-19 05:25:31 +00:00
rob
aefcd41a88 status sweep: cap check-health per node (timeout) so one stuck node can't wedge fleet rpc-update
A hung check-health.sh (aztec-testnet, looping on an unresponsive reference RPC)
blocked show-status.sh's parallel 'wait' for 3.5h, hanging the whole fleet
rpc-update and holding the deploy lock. Each curl was bounded (-m 3) and the
retry loop capped (3x), but the call itself wasn't time-bounded.
- sync-status.sh: wrap each check-health.sh call in 'timeout ${HC_TIMEOUT:-30}'
  (-> exit 124 + 'timeout' status on overrun).
- show-status.sh: wrap the whole per-node sync-status.sh call in
  'timeout ${SYNC_TIMEOUT:-60}' so the parallel wait can never block forever.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 03:57:18 +00:00
9ee59cf9fa deploy: regenerate compose from vibe-node main 9053889ed7bb 2026-06-19 03:45:34 +00:00
rob
9ad7565f97 deploy: regenerate compose from vibe-node main f843789776db 2026-06-18 16:34:36 +00:00
sebastian
30e866802a Merge pull request 'check-health.sh: retry logic for hash comparison (fix false-positive forked)' (#8) from issue-42 into main
Reviewed-on: #8
2026-06-18 16:08:31 +00:00
rob
c56542ade0 deploy: regenerate compose from parent main 1ecbe0739ddc 2026-06-18 15:19:10 +00:00
rob
e9ed1c0cd3 check-health.sh: add retry logic for hash comparison to fix false-positive forked status 2026-06-18 14:49:34 +00:00
rob
a3a78cb3be deploy: regenerate compose from parent main 3cc8d26c8d58 2026-06-18 13:44:07 +00:00
rob
7d00f3a1ce deploy: regenerate compose from parent main 0abbb3abd857 2026-06-18 11:20:34 +00:00
rob
6bb0b19f45 Harden restore-volumes.sh against silent restore truncation and incomplete-download skips
- BUG 1: Add error checking after tar extraction for both LOCAL and REMOTE-CACHE branches
  - Check exit status of tar -I zstd -xf commands
  - Print error to stderr and exit non-zero on failure
  - Prevents silent truncation where corrupt/incomplete backup extracts partial data
  - Mirrors existing remote-STREAM branch error handling
- BUG 2: Fix REMOTE branch to resume incomplete aria2c downloads
  - Check for presence of <file>.aria2 control file as incomplete signal
  - aria2c -c continues/resumes download when .aria2 file exists
  - Only skip download when file exists AND no .aria2 control file remains
  - aria2 deletes .aria2 sidecar on successful completion, making it a reliable signal
- Maintain all existing flags: aria2c -c -Z -x8 -j8 -s8 -d
- Preserve reth guard logic and static-file offload behavior unchanged

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-17 16:22:50 +00:00
rob
6ddb18dbc5 Fix /slowdisk static-file offload: add reth guard and --keep-directory-symlink
- Add RETH GUARD to clone-backup.sh and clone-node.sh: when the config name
  contains 'reth', skip the whole /slowdisk static-file symlink offload and
  extract everything onto the primary disk (equivalent to --no-slowdisk).
  This matches the already-correct restore-volumes.sh behavior.
  Reason: reth refuses to start when its static_files directory is a symlink,
  failing at boot with 'failed to create dir static_files: File exists'.

- Add --keep-directory-symlink to all tar extraction options in both scripts
  for the SLOWDISK path. This allows tar to extract files THROUGH the
  pre-created directory symlinks instead of trying to mkdir over them
  (which fails with 'Cannot mkdir: File exists'). This matches the
  already-correct restore-volumes.sh behavior.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-17 16:07:21 +00:00
rob
27d0ea0d28 op/doma: rename celestia relay to op-alt, add mainnet op-alt relay, vendor mainnet rollup.json
- Rename doma testnet relay from celestia to op-alt (ghcr.io/celestiaorg/op-alt-da)
- Add op-alt relay for doma mainnet with image tag 0.15.0 (not v0.15.0)
- Vendor complete mainnet rollup.json with alt_da (GenericCommitment)
- Fix per-network relay settings: namespace + CELESTIA_*_RPC env vars
- Switch mainnet op-geth to use vendored rollup.json (bind-mounted)

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-17 14:02:34 +00:00
rob
1944662053 op/doma/testnet: fix celestia relay image tag from v0.15.0 to 0.14.0-mocha
Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-17 11:21:56 +00:00
rob
fc03d6ddf6 op/doma/testnet: add Celestia Alt-DA support (celestiaorg/op-alt-da:v0.15.0)
- Add relay template (templates/relays/celestia.doma.yml) for op-alt-da
- Add celestia relay config to op/doma stack in context.yml
- Add relay: celestia to op/doma testnet in config.yml
- Add op-node.doma.yml template with ALTDA env vars gated on relay_name
- Update op/doma/testnet/rollup.json with complete config including alt_da block

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-17 10:40:59 +00:00
4ea0bed344 doma-testnet: vendor rollup.json with chain_op_config
Conduit's testnet rollup.json (doma-dev-ix58nm4rnd) omits chain_op_config,
crashing op-node v1.19.0 with 'cfg.Rollup.ChainOpConfig is nil'. Vendor a
complete rollup.json (chain_op_config eip1559 6/50/250, confirmed identical
in mainnet rollup.json and testnet genesis optimism config) plus the
post-fjord fork times baked in, mounted via custom_config so op-node uses
the local file instead of curling Conduit's incomplete one.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 02:50:29 +00:00
f4b42ff530 doma-testnet: add op-reth variant on conduit-op-reth (chain 97476, L1 sepolia)
Doma testnet (Conduit slug doma-dev-ix58nm4rnd) on Conduit's purpose-built
conduit-op-reth image - better-tested for Conduit chains than upstream op-geth.
Fork times granite/holocene/isthmus/jovian (missing from Conduit's bare
rollup.json) supplied via env/op/doma/testnet/node.env. Experiment to validate
a clean canonical sync before redoing mainnet on op-reth.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 02:31:25 +00:00
9921391cfa doma-mainnet: add OP_NODE_OVERRIDE_JOVIAN=1769065201 (Conduit rollup.json omits it)
Conduit's bare rollup.json for doma-mainnet omits jovian_time entirely, but the
EL genesis activates Jovian at 1769065201. Without the override op-node has no
Jovian fork time and mis-derives at the boundary (chain forks off canonical).
Same fix pattern as bob-sepolia. Override comes from env/op/doma/mainnet/node.env.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 01:39:58 +00:00
cd7f05997b berachain: bump beacon-kit v1.3.4 -> v1.4.0-rc3 (Bepolia Fusaka/Fulu fork)
Bepolia activated the Fusaka/Fulu hard fork at 2026-05-27 16:00 UTC (unix
1779897600), which ships new EVM-inflation-withdrawal values. beacon-kit
v1.3.4 (pre-fork) crash-loops replaying the fork-boundary block 20513284:
'first withdrawal is not the EVM inflation withdrawal' (RestartCount 3742 on
us-41). The EL (bera-reth v1.4.0) already speaks the Fusaka engine API
(newPayloadV4P11 etc.) and accepted the post-fork block, so only the CL is
behind. v1.4.0-rc3 sets the Fulu fork time + new inflation values. Applies
to all berachain chains' beacon-kit default; only bepolia is deployed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 00:54:30 +00:00
5fda0b60bc telegraf: run as root + bypass gosu drop to read docker.sock GID-independently
The container ran as user 0:994 and accessed the docker socket via group
membership, but the host docker group GID is auto-assigned and varies per
host (e.g. uk-8 is 988, not 994), so the hardcoded gid silently breaks
telegraf's docker input wherever it differs (uk-8 was in a restart loop:
permission denied on /var/run/docker.sock). Run as root (0:0) with
entrypoint [telegraf] to skip the image's gosu privilege-drop, so telegraf
reads the socket as its owner regardless of the host docker gid. Works
uniformly fleet-wide; no regression on hosts where the gid happened to match.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 15:11:26 +00:00
fe94f3b605 doma: op-node consensus-layer sync (node_sync)
op-geth was stuck at genesis (block 0, 0 L2 peers for 31h) because execution-layer
snap-sync had no peers. node_sync=true -> OP_NODE_SYNCMODE=consensus-layer (derive
L2 from L1) + geth --syncmode=full. Diagnosed by cursor on de-13.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 14:23:25 +00:00
9ce0e14cd6 Revert "monitoring: enable cadvisor diskIO metrics"
This reverts commit a5081013f3.
2026-06-16 10:17:23 +00:00
941a0aa691 Revert "monitoring: run node_exporter on host network"
This reverts commit d48713cb15.
2026-06-16 10:10:01 +00:00
d48713cb15 monitoring: run node_exporter on host network
netdev (netlink) was reading the container's own veth (idle) -> node_network_*
showed ~0 on every host. Host network lets it see real host interfaces, so
bandwidth (egress vs tariff quota) works. Removed networks/expose (exclusive
with network_mode:host).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 10:06:55 +00:00
a5081013f3 monitoring: enable cadvisor diskIO metrics
Adds diskIO to cadvisor --enable_metrics so per-container disk read/write
(container_fs_reads/writes_bytes_total) is exposed — lets node attribution
name which node is the noisy IO neighbor, not just flag the host.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 10:01:33 +00:00
6d65582af4 monitoring: scrape cadvisor/nodeexporter/telegraf at /metrics not /
prometheus-scrape.metrics_path was '/' which made prometheus-docker-sd scrape
the HTML root and fail with 'INVALID is not a valid start token', leaving the
targets up=0. Fixes per-container (cadvisor) + host (node_exporter) metrics so
they can be wired into the DRPC insights MCP for per-node resource attribution.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 09:06:57 +00:00
2761625c15 utils: add mint-grafana-service-account-token.sh
Mint a Viewer Grafana service-account token on a host and print it to stdout,
so each box's local Grafana (dshackle + node_exporter + cadvisor) can be wired
into the DRPC insights MCP (grafana_servers.yaml). Idempotent SA, fresh token
per call.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 08:59:46 +00:00
1134a3774a sync-status: dRPC-homogeneous block-lag status + fix never-used reference fallbacks
Match the dRPC gateway's per-chain "how many blocks behind is ok" model instead of a
fixed 2s/5s timestamp tolerance:
- check-health.sh: compare the reference head vs local head by BLOCK NUMBER and classify
  with the chain's dRPC lag thresholds (LAGGING_LAG/SYNCING_LAG, in blocks, from
  chains.yaml). dRPC uses the two thresholds inconsistently across chains (sometimes
  lagging<syncing, sometimes the reverse) so the smaller is the online boundary and the
  larger the syncing/drop boundary. Defaults 2/6 when a chain has no thresholds.
- multicurl.sh: also skip responses with result:null (a lagging endpoint lacking the
  requested block) so the fallback reference URLs are actually tried. Previously the first
  endpoint's {"result":null} was accepted as success -> fallbacks never ran, and the null
  reference hash made check-health report false "forked" (the online/forked flapping).
- sync-status.sh: resolve the lag thresholds (by drpc slug or chain id) and export
  LAGGING_LAG/SYNCING_LAG.
- reference-rpc-endpoint.sh: add --lags and --block-time-ms lookups.
- reference-rpc-endpoint.json: regenerated with per-chain block_time_ms + lagging_lag +
  syncing_lag (additive).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 05:55:55 +00:00
rob
df6c17f5cc arb nitro minimal: prune-cycle model (.prune.yml --init.prune=minimal)
Revert to the prune-cycle model for minimal nodes: the normal compose serves
RPC with no --init.prune, and a generated .prune.yml runs --init.prune=minimal,
driven periodically by prune-if-prunable (same mechanism as pruned/full). Minimal
nodes are seeded from a pruned backup, then pruned to minimal.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 05:43:09 +00:00
577ac5d7f2 bsc minimal: disable eth_getProof on dshackle upstream
Minimal BSC nodes lack the state to serve eth_getProof and return
"header not found" (especially while catching up after a restart). The
drpc gateway probes eth_getProof and marks the WHOLE upstream unavailable
on failure, so e.g. bsc-mainnet-bsc-minimal on us-32 showed unavailable in
US-East despite the node being online and at head.

Disable eth_getProof on bsc minimal upstreams only (network=bsc,
db_type=minimal) so they stay available for every other method. Archive/
pruned bsc and all other nodes keep serving getProof.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 05:29:55 +00:00
677a98d9bd xlayer: archive-only reth on OKX xlayer/op-reth image + snapshot reth.toml
X Layer mainnet/testnet op-reth now use the OKX xlayer/op-reth:v0.0.4.1 fork
(generic op-reth can't read the X Layer DB format), the image's built-in
xlayer-<network> chain spec, --rpc.legacy-url for post-snapshot history gap-fill,
and the OKX archive-compatible reth.toml (light pruning only: merkle_changesets
distance=10064). Switched the reth profile from full_trace to archive_trace and
deleted the pruned variants — a "pruned" compose over archive snapshot data
crash-loops on a block-height mismatch. Requires the official OKX reth snapshot
pre-loaded into the volume; do NOT sync from scratch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 04:35:28 +00:00
rob
fd283122f5 arb nitro minimal: self-prune via --init.prune=minimal in normal compose
Correct the minimal-node model: the minimal compose itself carries
--init.prune=minimal (prunes to genesis+head on start) instead of relying on a
separate .prune.yml — otherwise a minimal node was byte-identical to pruned in
normal operation and had no way to enforce minimal state. Removed the redundant
minimal .prune.yml files.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 04:19:09 +00:00
95f9da1e73 bob-sepolia: consensus-layer sync + debug_geth L1 + Jovian override (unstick)
op-node was following the sequencer tip in execution-layer mode while op-reth stayed
at genesis (blocks buffered, never canonical). Switch to consensus-layer sync so
op-node drives L1 derivation, add op-reth --disable-discovery, and use debug_geth
(eth_getBlockReceipts) for the L1 RPC kind — "basic" per-tx receipts hit "receipt 0
has unexpected nil block number" on the Sepolia L1 endpoint. OP_NODE_OVERRIDE_JOVIAN
=1772548201 is belt-and-suspenders (jovian_time already in rollup.json). Applies to
all bob-sepolia EL variants. Regenerated from the vibe-node generator.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 04:14:34 +00:00
fbd498aaa2 superseed-sepolia: consensus-layer sync + debug_geth L1 + drop genesis blob fields
op-reth/op-geth sepolia now run op-node consensus-layer sync (empty DB is never
P2P-backfilled) with --disable-discovery, derive L1 via debug_geth against an
operator-set full-history Sepolia RPC (SUPERSEED_SEPOLIA_L1_EXECUTION_RPC, falling
back to ETHEREUM_SEPOLIA_EXECUTION_RPC), and serve a genesis.json with the invalid
top-level excessBlobGas/blobGasUsed nulls removed (eip1559DenominatorCanyon=250
retained). Regenerated from the vibe-node generator.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 04:05:05 +00:00
ad56365253 cometbft: WS Upgrade matcher case-insensitive + ct_ensure_wasm + statesync-skip-if-data
Per cursor cosmos handoff. (1) Traefik WS router rule Headers(Upgrade,websocket) is
case-SENSITIVE -> clients sending 'Upgrade: WebSocket' (python websocket-client) fall
through to the RPC router (200/400 not 101). rpc-client.yml now emits
HeadersRegexp(Upgrade,(?i)websocket) for all split-WS chains; regenerated cosmos+avalanche.
(2) Refactor into cometbft-common.sh: ct_configure_statesync skips if data/application.db
exists; new ct_ensure_wasm seeds CosmWasm/IBC-08 wasm (statesync omits them). init.sh calls
both. README documents wasm/version/WS gotchas. 45 other split-WS composes get HeadersRegexp
on their next regen.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 03:27:19 +00:00
c07fb81a56 op-node: default L1 RPC kind basic -> standard (eth_getBlockReceipts)
Our L1 geth (e.g. rpc-de-31 ethereum-mainnet-geth) returns null for the
per-tx receipt path on historical blocks but serves eth_getBlockReceipts
fine. op-node's 'basic' kind only uses the per-tx batch, so chains
deriving from genesis (e.g. Katana) hit the broken path immediately;
chains already synced past it don't. 'standard' uses eth_getBlockReceipts
and keeps the per-tx batch as fallback (strict superset of 'basic'), so
it is safe for every OP-stack node.

Flips OP_NODE_L1_RPC_KIND default across all 176 op-node compose files.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 03:26:02 +00:00
576530e68f gaiad: v27.4.0 + statesync-skip-if-data + wasm-snapshot seed (port cursor host fix)
Live chain is v27.4.0 (abci_info); v25.3.2 halts at the v26/v27 upgrade heights (ghcr
lags but v27.4.0 IS pullable). Statesync omits CosmWasm + IBC 08-wasm files -> gaia panics
'wasmlckeeper failed initialize pinned codes / Error opening Wasm file'. init.sh now: skip
statesync if data/application.db exists (idempotent restart, preserves a restored snapshot);
on fresh statesync, seed wasm from polkachu cosmos_wasmonly.tar.lz4. Porting cursor's host
fix into the repo (host /root/rpc edits get reverted by run-rpc-update re-clone).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 03:08:02 +00:00
b4922e7fd3 gaiad: traefik split-WS router -> /websocket (CometBFT WS endpoint)
dshackle's WS head subscription hit the RPC root (got HTTP 200, not a WS upgrade).
Set client_ws_path=/websocket -> rpc-client.yml emits the avalanche-style priority-100
WS router (Header Upgrade:websocket -> replacepath /websocket) so WS reaches CometBFT's
/websocket. RPC router unchanged (stripprefix -> root).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 01:53:12 +00:00
rob
48683cabba arb nitro: add minimal-prune node variant (--init.prune=minimal)
New minimal profile for arbitrum one/nova/sepolia: a pruned-style node whose
prune cycle uses --init.prune=minimal (most aggressive: genesis+head only)
instead of full. Separate composes so it can be tested independently of the
production pruned nodes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 13:34:22 +00:00
814afc05af gaiad: lead client_staticpeers with polkachu statesync node (direct IP, serves snapshots)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 12:56:56 +00:00
68d77df969 gaiad: set client_staticpeers to live cosmos peers (statesync peer discovery)
The polkachu seed was refusing -> 0 peers -> statesync couldn't discover snapshots.
Use client_staticpeers (cosmos-hub is a CLIENT in our stack) with 8 live peers from
polkachu /net_info. Template now reads client_staticpeers/client_bootnodes (standard attrs).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 12:52:57 +00:00
0df57827f2 cometbft statesync: fix rpc_servers/trust_height/trust_hash (underscore, not hyphen)
CometBFT config.toml uses underscore keys; the sed targeted hyphens (rpc-servers etc.)
so they never matched -> rpc_servers stayed empty -> 'at least 2 RPC servers required,
got 0'. Now section-anchored to [statesync] + [_-] tolerant. (This is also why sei
never held chainhead — same hyphen bug in its bespoke init.)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 12:45:42 +00:00
rob
e8dafa1383 prune: regenerate matching-version .prune.yml + add avalanche offline-pruning
Fixes prune-version drift that corrupted nodes (prune ran an older nitro binary
than the node). All .prune.yml now regenerate from the same config as the normal
compose via client_needs_prune.

- arb nitro: nova/one/sepolia .prune.yml bumped to the node's version (v3.10.1)
- avalanche: add .prune.yml variants that mount a /config/prune chain-config with
  offline-pruning-enabled, plus avalanche/{mainnet,fuji}/prune/C/config.json
- archive profiles are excluded (db_type==pruned gate) so they are never pruned

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 12:40:10 +00:00
fc0bd40523 gaiad: drop invalid --api.*/--grpc.* start flags (printed help + exited)
CometBFT RPC :26657 (the dshackle upstream) is served via rpc.laddr regardless;
minimal 'gaiad start --home --minimum-gas-prices' is the valid invocation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 12:39:47 +00:00
55433a4822 cosmos: fix CometBFT RPC .result wrapping in statesync + sync-status helpers
ct_configure_statesync read .block.header.height (null — CometBFT wraps in .result) so
statesync silently skipped -> gaiad fell back to genesis replay (panic). Use
'.result.X // .X' (robust to wrapped/unwrapped). Same fallback in check-health --cosmos.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 12:36:47 +00:00
0c67fe451b gaiad: drop hardcoded p2p port (auto-assign to avoid host collision w/ morph 26656)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 12:32:45 +00:00
71345092f9 cosmos-hub (gaiad): add compose + init.sh + cometbft.Dockerfile
First pure-cosmos chain (validates the §2 cometbft-common.sh lib via real gaiad init).
Single-binary CometBFT client serving :26657 (dshackle chain=cosmos-hub). Statesync
bootstrap (polkachu) since genesis-replay across gaia governance upgrades is impractical.
gzipped genesis. v25.3.2 (live chain version; registry's v27.4.0 not on ghcr). Params
(chain_id/genesis_url/statesync_rpc/seeds/min_gas) from context.yml.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 12:30:07 +00:00
78c78f5079 sync-status: add cosmos/CometBFT handler (gaiad + cosmos batch)
Cosmos-hub has NO EVM RPC — eth_blockNumber checks don't apply. Add a --cosmos
handler that probes the CometBFT /status method: sync_info.catching_up=false =>
online, else syncing; optional head-gap check vs the drpc reference. sync-status.sh
dispatches protocol=cosmos -> check-health.sh --cosmos. eth/starknet/aztec untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 12:15:54 +00:00
9566a6d23f morph: init container also mkdir /db/data + seed priv_validator_state.json
morphnode panics (open /db/data/...: no such file) without the data dir + initial
validator state. EL healthy; this unblocks the CL.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 12:05:22 +00:00
2adce4cf5a morph: rename node morph-node->morph; add CL config seed (config.toml+genesis.json)
morphnode --mainnet does NOT self-generate config (crash: Config File not found in
/db/config). Add init container that seeds the committed morph/mainnet/node-data/config/
(config.toml + genesis.json, from run-morph-node) into /db/config (no-clobber). Node
renamed morph-node -> morph (cleaner; vol _morph, MORPH_MAINNET_MORPH_* env).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 12:02:56 +00:00
f4ce85bbcd morph-mainnet: add generated compose (Scroll-l2geth EL + op-node-style CL)
EL morph-geth (go-ethereum 2.2.3, --morph --morph-mpt, archive leveldb/hash/mpt,
pure EL driven via engine API) + CL morph-node (node:0.5.7, env-driven, derives from
eth-mainnet L1). Params from authoritative morph-l2/run-morph-node. Fresh L1 derivation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 11:52:26 +00:00
535f51bda2 cometbft: add reusable family-C bootstrap library + docs
Generalizes the berachain beacon-kit init pattern into cometbft-common.sh (sourced
helper lib) so morph-node, gaiad/cosmos batch, shibarium and the EVM-cosmos chains
(haqq/sei/zero-gravity) become thin init.sh overrides. Validated against the real
init flows of beacon-kit, haqq, sei, zero-gravity. README.cometbft.md documents the
pattern (per-chain Dockerfile + thin init.sh + context). berachain stays on its own
beacon-kit.yml (untouched).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 11:26:06 +00:00
fa3f96382c base: bump node-reth client + op-node v0.16.1 -> v1.1.0 (Storage V2 / reth 2.3.0-dev)
For de-33 base V1->V2 migrate-v2 experiment. Global pin per operator;
de-13 prod base only moves on its next run-rpc-update.
2026-06-15 11:16:49 +00:00
237ec1d2e1 apechain: pin official Caldera image apechain-v3.5.6 (revert DAC flip)
Generic nitro v3.10.1 strictly refuses DA on a DAC=false chain, so DAC=true
override did not work (confirmed live: node still errored 'AnyTrust DA usage
set to false'). ApeChain's canonical config is DAC=false; its official build
public.ecr.aws/i6b2w2n6/nitro-node:apechain-v3.5.6 accepts DAC=false + AnyTrust
DAS. Revert DAC to false (canonical) + keep das rest-aggregator.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 11:03:14 +00:00
110c3483cd apechain: enable AnyTrust DAS reader (it IS AnyTrust, not pure rollup)
Live node was 'forked', looping 'no AnyTrust reader configured for AnyTrust
message (header byte 0x88)'. ApeChain (Caldera) posts AnyTrust DA certs; the
earlier 'pure rollup' fix removed the DAS reader. Set chain-config
DataAvailabilityCommittee=true (matching every other AnyTrust chain in repo,
required by nitro v3.10.1 when DA enabled) and add das rest-aggregator
https://apechain.calderachain.xyz/rest-aggregator (from official Caldera node config).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 10:52:30 +00:00
0838787aa8 katana-mainnet: add Jovian (1773066601) fork override for op-geth + op-node
Conduit rollup.json omits post-Fjord fork times; chain is past Jovian so
without it op-geth/op-node mis-execute/mis-derive at the boundary.
2026-06-15 10:38:58 +00:00
be54c7d7cd Revert "superseed-sepolia: add Karst hardfork time (1781712001 = 2026-06-17 16:00:01 UTC)"
This reverts commit ec702984f1.
2026-06-15 10:36:35 +00:00
ec702984f1 superseed-sepolia: add Karst hardfork time (1781712001 = 2026-06-17 16:00:01 UTC)
OP Sepolia network-wide Karst activation. op-node v1.19.0 (pinned) and
conduit-op-reth:latest are Karst-aware; op-node v1.17.0 introduced Karst.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 10:29:17 +00:00
a032f3c9d6 apechain: drop AnyTrust DA flags (it is a pure rollup, DAC=false)
nitro crash-looped: 'AnyTrust DA usage for this chain is set to false but
--node.da.anytrust.enable is set to true'. apechain posts data to Arbitrum One,
not a DAS. Regenerated without DA flags; added parent-chain-is-arbitrum:true to
the chain-info. Derives batches from the Arbitrum One parent + sequencer feed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 09:55:40 +00:00
e68c802d7c Add apechain-mainnet nitro node (Arbitrum Orbit L3 on Arbitrum One)
ApeChain chain 33139, parent Arbitrum One (42161), Caldera infra, $APE gas.
baseConfig.json chain-info from the official Constellation replica nodeConfig
(ArbOS 31, owner 0x5737..601c, full rollup contract set). das/feed/sequencer
point at Caldera; parent-chain = ARBITRUM_ONE_EXECUTION_RPC (no L1 beacon).
pruned-pebble-path + archive-pebble-hash profiles.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 06:45:51 +00:00
450c9d7874 Restore full reference-rpc-endpoint.json (filtered gen truncated it)
The doma --filter run regenerated this global aggregate from only the
doma subset, emptying it. Restore the complete file; doma resolves via
its dshackle label so no reference-endpoint entry is required.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 05:52:52 +00:00
1afe87fe12 Add doma-mainnet op-geth node (Conduit OP-stack, chain 97477)
Conduit OP-stack L2 on Ethereum mainnet L1. Canyon-at-genesis; op-geth
ingests the Conduit genesis.json directly (no op-reth hash pitfall).
Config served from Conduit slug doma-mainnet-qvzsfv8nv0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 05:51:18 +00:00
rob
b24c0f12dd clone-node/clone-backup: add --no-slowdisk override for /slowdisk offload
Mirror the restore-volumes.sh --no-slowdisk capability for live/backup clones.
Both scripts gate the target /slowdisk static-file offload on the target's
SLOWDISK env (case-insensitive, matches the Python-templated 'True') and accept
a --no-slowdisk flag that forces the offload off for one run. When SLOWDISK is
on but the target /slowdisk is too small for the static files, the clone warns
and aborts, telling the operator to re-run with --no-slowdisk.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 05:43:45 +00:00
baf26b234f static-file size/manifest: match offloaded (symlinked) dirs + show offload indicator
find -type d skipped static dirs that are already offloaded (a symlink to /slowdisk is type
l, not d) — so show-static-file-size.sh reported zero static for an offloaded node (e.g. bob
on de-35), and backup-node.sh would drop them from the manifest (breaking re-offload on the
next restore). Match dirs AND symlinks now (root-level entries too).

show-static-file-size.sh also tags each static dir with its location:
[OFFLOADED -> /slowdisk/...], [on-disk], or [BROKEN SYMLINK ...].

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 05:03:16 +00:00
57b5757a85 restore: SLOWDISK gate matches Python-templated "True" (capitalized)
The SLOWDISK value is emitted by Python templates as capitalized booleans (True/False), so
match "True" (also accept manual lowercase "true"); anything else = offload off. --no-slowdisk
sets SLOWDISK=False to override.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 04:58:13 +00:00
6c110c08ed restore: gate offload on SLOWDISK=true (exact) with --no-slowdisk override
Use the single SLOWDISK env var from .env (already set to "true" on the dedicated-extra-disk
hosts, e.g. us-35). Offload runs only when SLOWDISK is exactly the literal "true" (case
matters) and the --no-slowdisk flag was not passed. --no-slowdisk forces it off even when
SLOWDISK=true (extra disk full). Replaces the prior NO_SLOWDISK inversion.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 04:50:06 +00:00
b9efcfe34d restore: invert gate to NO_SLOWDISK (default true) + add --no-slowdisk override flag
Static-file offload gating, clearer semantics:
- NO_SLOWDISK defaults to TRUE (offload OFF) — safe default everywhere.
- A host with a real dedicated extra disk at /slowdisk sets NO_SLOWDISK=false in its .env
  to ENABLE the offload.
- New --no-slowdisk CLI flag forces NO_SLOWDISK=true, overriding the .env false — for when
  the extra disk exists but is full. Flag is parsed position-independently; the positional
  args ($1 compose, $2 remote source) are preserved.

Offload runs only when NO_SLOWDISK is false AND the flag was not passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 04:43:47 +00:00
3caa4ab873 restore: gate static-file offload on SLOWDISK env var (.env), not just /slowdisk presence
A `/slowdisk` directory exists on hosts even when it is just a folder on the root disk
(no dedicated extra disk) — offloading there gives no benefit. Source the host .env and
require SLOWDISK to be set (operator sets it only on hosts with a real extra disk mounted
at /slowdisk) before activating the static-file -> /slowdisk symlink offload. Unset =
normal extract everywhere. Target path stays /slowdisk (the fixed in-container mount).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 04:39:48 +00:00
a9e8fba794 static-file list: fleet-verified rewrite + root-vs-suffix matching
Verified static-file dirs across the reachable fleet via per-host cursor inspection
(de-13/14/16/22/27/30/31/32/35, us-16/41, uk-4). Findings:
- nitro freezers are network-prefixed (arbitrum-one/nitro/l2chaindata/ancient ... up to
  1.3 TB), so the old chain/ and data/ prefixes matched nothing;
- missing: snapshots (erigon3/op-erigon/cosmos), lightchaindata/ancient, nested l2geth
  geth/geth/chaindata/ancient, aztec archiver, nitro classic-msg/ancient;
- bare `ancient` matched nothing (all are nested).

List rewritten to canonical entries. Matching (backup-node.sh manifest + show-static-
file-size.sh) now: entry with NO slash = root-level only (so `snapshots` does NOT catch
postgres pg_logical/snapshots), entry WITH a slash = path-suffix via find -path "*/X"
(matches any prefix: network-prefixed nitro, nested datadirs). The manifest now records
the CONCRETE per-volume path so restore-volumes.sh recreates the exact symlink.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 03:22:26 +00:00
345538954d restore/cleanup: implement static-file -> /slowdisk offload + free it on removal
restore-volumes.sh: pre-create static-file symlinks from the backup's .txt manifest so
the immutable ancient/freezer dirs land on /slowdisk (SSD) and extract THROUGH the
symlinks via tar --keep-directory-symlink (was --dereference, which clobbered them);
hot state stays on the primary disk. Cleans stale /slowdisk targets first (no leak on
re-restore). Safe fallbacks: no /slowdisk / no manifest / no static paths -> normal
extract. Reth excluded (reth dropped whole-dir static-file symlinks).

volume-utils.sh: add delete_slowdisk_targets_for_key() — follows a volume's symlinks and
sweeps the rpc_<key>__data_ pattern under /slowdisk (matches delete-volumes.sh).

cleanup-volumes.sh: free the /slowdisk static data before docker volume rm (was leaking),
and fix the fragile substring used/unused match to an exact name match.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 03:05:04 +00:00
f39e09dac0 hemi mainnet: fix op-geth/op-node startup crashes
- op-geth: drop stray trailing ` \` on --hvm.genesisheader and
  --tbc.leveldbhome (the backslash was decoded as part of the hVM
  genesis header -> "invalid byte U+0020 ' '" crash)
- op-node: add OP_NODE_OVERRIDE_ECOTONE/CANYON/DELTA=1725868497
  (rollup.json carries only regolith_time; without these the later
  fjord override tripped "fork fjord set but prior fork ecotone missing")
- op-node: OP_NODE_BSS_WS no longer wrapped in literal quotes
- bump to Hemi's current pins (mainnet is past isthmus/holocene):
  op-geth 05d4d8f, op-node 7c70d2d

Values mirror hemilabs/hemi-node mainnet scripts/gen.sh + config.json.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 02:27:32 +00:00
3c4492179c arc: Malachite CL is now a proper node component (arc-testnet-node)
Consensus service renamed arc-testnet-consensus -> arc-testnet-node: it is now
generated by templates/nodes/malachite.yml (node: malachite) instead of being
hacked into the arc client template's indexer block. Container body unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 02:19:36 +00:00
2249352c20 op-node: default OP_NODE_L2_ENGINE_RPC_TIMEOUT=120s for all OP-stack nodes
op-node's default engine-API RPC timeout is short; on nodes whose EL responds
slowly to engine_newPayload/forkChoiceUpdated (e.g. boba-mainnet op-reth pruned
during catch-up) op-node times out driving the EL and the execution head freezes
while op-node keeps deriving from L1. Raising the engine RPC timeout to 120s
prevents this class of stall fleet-wide.

Regenerated from env/op/node.env: adds the env var to every op-node service
(116 geth + 40 reth + 22 erigon composes); additions only, no other changes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 15:43:34 +00:00
16057e4875 bob-sepolia: add Jovian to EL genesis; drop redundant op-node override
genesis.json had no jovianTime, so op-geth/op-reth never activated Jovian
and op-node rejected Jovian-era L1-info txs ("unexpected length"). Added
jovianTime=1772548201 to the genesis config (EL source of truth for both
geth and reth). Removed OP_NODE_OVERRIDE_JOVIAN from the op-node env: the
local rollup.json already carries jovian_time, making the override redundant.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 06:28:01 +00:00
36b8243a03 op-reth: emit --disable-discovery (not --nodiscover) for node_sync nodes
op-reth rejects geth's --nodiscover flag, which the op-geth base template
emits for node_sync nodes. Use reth's --disable-discovery instead.

- hashkeychain-testnet: now node_sync/consensus-layer (was execution-layer
  with an empty DB, which could not backfill) + --disable-discovery
- xlayer mainnet/testnet (archive+pruned): --nodiscover -> --disable-discovery
  (these were latently broken on restart)

Fix lives in the op-reth.yml base template so all reth nodes are covered;
the redundant override in op-reth.boba.yml was removed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 06:18:55 +00:00
10deed7819 superseed-sepolia op-reth: use conduit-op-reth image + historicalrpc
Chain 53302 is legacy Canyon-at-genesis (block 0 has no Shanghai
withdrawalsRoot). Upstream op-reth always injects it and computes the wrong
genesis hash 0xfa6f21ae vs canonical 0x7274a90e, so it crash-loops against
the DB. conduit-op-reth has legacy-Canyon genesis compatibility for 53302.

Regenerated from context.yml (reth client_image override) + op-reth.yml
template (historicalrpc for superseed-sepolia fresh-sync backfill).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 06:10:06 +00:00
31309aaac3 bob-sepolia: use local genesis/rollup for all variants, drop Conduit URLs
Conduit's downloaded genesis.json/rollup.json are faulty (rollup.json
lacks chain_op_config + post-Fjord fork times, crashing op-node v1.19.0).
The fixed configs live in op/bob/sepolia/. Removed the client_genesis /
node_rollup_json Conduit URLs from context.yml and regenerated, so all 7
bob-sepolia composes (geth + reth) now bind-mount ./op/bob/sepolia:/config
and drop the curl-from-Conduit init containers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 05:45:55 +00:00
be1f8d33b9 superseed-sepolia: add pectra_blob_schedule_time + fix eip1559DenominatorCanyon
op-node was crashing post-Jovian and the rollup/genesis configs were missing
two fields present in the live sequencer (sepolia.superseed.xyz
optimism_rollupConfig):
- rollup.json: add pectra_blob_schedule_time=1742486400 (L1 Sepolia Pectra)
- genesis.json: eip1559DenominatorCanyon 0 -> 250 (match chain_op_config)

Verified against the live sequencer. Fixes op-node 'unexpected length: 178'
L1-info parse error. karst_time not yet published by the sequencer (Karst
Sepolia ~2026-06-17 16:00 UTC) - to be added once available.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 05:26:56 +00:00
4209d46ba7 Fix bob-sepolia op-reth-pruned-trace: local rollup config for op-node v1.19.0
Conduit's rollup.json lacked chain_op_config and fork times required by op-node v1.19.0, causing a crash loop. Mount op/bob/sepolia locally (genesis + rollup) and drop Conduit init containers.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 07:10:29 +02:00
ff49dc92f5 bob-sepolia: force OP_NODE_OVERRIDE_JOVIAN; drop stale op/bob.by backup
bob-sepolia is past the Jovian hardfork (jovian_time=1772548201). Conduit's
downloaded rollup.json omits jovian_time, so op-node misparsed the 178-byte
Jovian L1-info deposit txs ("data is unexpected length: 178") and the node
stalled at genesis. Add OP_NODE_OVERRIDE_JOVIAN to all bob-sepolia variants.

Remove op/bob.by: an unused local genesis/rollup backup. Source of truth is
the genesis/rollup downloaded from the Conduit URLs in context.yml.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-14 03:16:25 +00:00
db59f360ca boba op-reth: --disable-discovery (op-reth v2.3.0 rejects geth's --nodiscover) for node_sync 2026-06-14 02:43:45 +00:00
44783dfb16 arc-testnet: run containers by numeric uid 0 (distroless images)
Circle's arc-execution/arc-consensus images are distroless with only the
`arc` user and no `root` entry in /etc/passwd, so `user: root` failed with
"unable to find user root". Run by numeric uid 0:0 instead (no passwd
lookup needed; root can write the root-owned named volumes).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 02:19:47 +00:00
84d119219c Add Arc testnet node (Circle L1): arc-execution EL + arc-consensus CL
Generated compose for the new `arc` client. Single self-contained stack:
3 init containers (snapshot download ~84GB, CL key init, socket prep) +
EL (reth-fork, http RPC behind traefik /arc-testnet, dshackle upstream
chain: arc-testnet) + CL (follows relay endpoints, drives EL over shared
IPC sockets). Images pulled anonymously from Circle's public Cloudsmith
registry at 0.7.2. Positional subcommands pinned in entrypoint so
process_yaml's command-sorting can't reorder them.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 02:07:37 +00:00
97d2cfe4aa op-reth sepolia fixes: superseed Jovian fork times, Karst v2.3.1 bump, op-sepolia/soneium template fixes
- superseed-sepolia: add holocene/isthmus/jovian fork times to rollup.json (CL)
  and genesis.json (EL). jovian_time=1768978801 is superseed's chain-specific
  activation (verified live via sepolia.superseed.xyz optimism_rollupConfig);
  the official superseed-xyz/node repo + the old committed config both lacked it,
  causing op-node "failed to parse L1 info deposit tx ... unexpected length: 178".
- op-reth v2.3.0 -> v2.3.1 across all op-reth composes (Karst-mandatory release,
  Sepolia activation Jun 17 2026 16:00 UTC).
- op-sepolia: --chain=optimismsepolia -> optimism-sepolia (invalid chain spec
  prevented op-reth from starting).
- soneium-minato-sepolia (reth/geth/erigon): L1 upstream vars now resolve to
  ETHEREUM_SEPOLIA_* (were ETHEREUM_MINATO-SEPOLIA_*, nonexistent -> no L1 RPC);
  state-cache shell var de-hyphenated; pectra blob-schedule override now emitted.

NOTE: superseed karst_time not yet published by the chain; must be added before
Jun 17 2026 once superseed announces it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 15:06:42 +00:00
9958d4e50d boba-mainnet op-reth: upstream op-reth + vendored patched chainspec (reth-config.json, bedrockBlock=1149019); revive boba on reth from Boba's snapshot (op-geth EOL 2026-05-31) 2026-06-13 14:32:28 +00:00
c4a61bf35c Add op-reth sepolia testnets: unichain-sepolia (registry chain), superseed-sepolia (custom genesis) — Superchain Jun-19 fork fallback 2026-06-13 11:50:30 +00:00
cb556f9df8 Add op-reth variants: unichain-mainnet, hashkey mainnet+testnet (Superchain op-geth->reth migration); add hashkey mainnet config (chainid 177, mainnet.hsk.xyz) which also fixes the previously-empty geth/erigon mainnet composes
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 05:41:41 +00:00
405f36d02f monitoring scripts: protocol dispatch via registry slug + mantle/metis chainid fixes
- sync-status.sh: resolve protocol family from the compose x-upstreams chain
  label via the registry (reference-rpc-endpoint.sh --protocol) instead of
  path-substring guessing; legacy path detection kept as fallback for
  composes without a resolved label. Unknown families report
  'unsupported protocol: X' honestly instead of a bogus eth_chainId error.
  Aztec reference lookup falls back to slug urls when rollup_version is
  not in the registry.
- reference-rpc-endpoint.sh: new --chain <slug> (urls by registry key,
  works for idless non-EVM entries) and --protocol <slug> modes; existing
  chainid and --rollup-version lookups unchanged.
- mantle-sepolia: chainid 5001 -> 5003 (verified live: 0x138b), label and
  --networkid now correct
- metis-sepolia: label resolves via registry override (drpc chains.yaml
  carries wrong id 59901; live chain is 59902, verified via official RPC)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 06:34:31 +00:00
714e8ba07a non-EVM chain labels via full registry import + reference endpoint ladder
- aztec-testnet, solana, ripple x-upstreams now carry their drpc slug as
  chain label (was empty -> dshackle ignored the upstreams)
- reference-rpc-endpoint.json: every chain now has a protocol field
  (eth/bitcoin/solana/ripple/aztec/...) for protocol-family dispatch in
  scripts, plus https://{slug}.drpc.org appended as LAST fallback url
  (independent endpoints stay preferred; overrides win entirely)
- registry grew 247 -> 333 entries (all drpc protocols imported, not just eth)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 06:12:24 +00:00
f5f475cdb1 fix dshackle chain labels: hoodi, rootstock-testnet, ronin-saigon + registry refresh drift
- ethereum-hoodi composes: chain ethereum -> hoodi (was mislabeled as mainnet)
- rootstock-bamboo: chain rootstock -> rootstock-testnet
- ronin-saigon op-reth: empty chain -> ronin-saigon (fresh DRPC registry now
  carries saigon at chainid 202601; stale local upstreams.yml had dropped it)
- assorted regen drift from fresh chain registry

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 05:32:16 +00:00
4b0ce9ca69 aztec-testnet: bump to 4.3.1 (network redeployed, 3.0.2 genesis incompatible) + regen drift
Aztec testnet rollup was redeployed on Sepolia; 3.0.2 computes the old
genesis archive root and crash-loops. 4.3.1 matches the deployed rollup
and bootstraps from snapshot. Verified live on rpc-de-13.

Includes regen drift from current templates for other stale compose files.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 03:33:44 +00:00
83328a5ab5 fix(cleanup-backups): trash-based retention instead of mass rm
The old script grouped backups with cut -d'-' -f1-3, which mis-grouped
volume keys and permanently deleted ~360 archives on 2026-06-11. Replace
with safe retention: group by full volume key regex, keep 3 newest per key,
move excess to /backup/trash, and protect uploading-*, broken_*, and
deprecated-* prefixes.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-11 14:53:03 +02:00
goldsquid
12e5ff8ee1 fix 2026-06-11 18:11:40 +07:00
goldsquid
87af562f1f fix 2026-06-11 17:14:15 +07:00
goldsquid
6ec861bd60 too much to chekc 2026-06-11 17:07:16 +07:00
goldsquid
e69a2b1202 linea besu update 2026-06-11 16:53:37 +07:00
2375dc3ef7 Regenerate compose files: ZKSync v29.17.0, Base new registry, multi-client bumps
Sync compose files with context.yml accumulated updates:
- ZKSync ERA/Abstract/Lens/Sophon external-node: v29.16.0-alpha → v29.17.0 (stable; fixes interop fee 403s)
- Base: registry ghcr.io/base/node-{reth,geth} v0.16.1/v0.15.6 (was oplabs GCR)
- Arbitrum/AlephZero/Connext/Nitro chains: v3.9.9-rc.3 → v3.10.1
- Gnosis reth: v1.1.11-eraimports → v1.2.1
- Gnosis/Linea erigon3: v3.4.0 → v3.4.2
- Polygon bor 2.7.2→2.8.1, erigon3 v3.5.0→v3.6.0
- Prysm v7.1.3→v7.1.4, Besu v26.4.0→v26.5.0
- Blast sepolia v1.4.0→v1.7.0, XRP 3.1.2→3.1.3
- Viction v2.5.1→v2.6.0, Immutable/Linea geth v1.17.2→v1.17.3

Co-Authored-By: Claude Agent <claude@stakesquid.eu>
2026-06-10 19:58:49 +00:00
c0416b4ae6 Add ronin-mainnet and ronin-saigon op-reth (OP-stack migration, May 12 2026)
Ronin migrated from standalone sidechain to OP-stack L2 operated by
Conduit, with EigenDA V2 for data availability. New composes follow
conduitxyz/ronin-migration-reth-docker: conduit-op-reth fork +
op-node v1.16.5 + eigenda-proxy 2.7.0 relay.

- op/ronin/{mainnet,saigon}: Conduit genesis (bedrockBlock patched to
  55577500 / 45528550) and rollup.json (alt_da GenericCommitment injected)
- saigon is a NEW chain post-migration: chainid 202601, L1 sepolia
- also regenerated: xlayer-testnet composes (dshackle chain label was
  corrupted to 'ronin' by an override typo), native ronin/ronin composes
  (upstream labels follow new chain ids), reference-rpc-endpoint.json

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 09:00:45 +00:00
goldsquid
5fd86bdf28 update xlayer 2026-06-10 13:41:18 +07:00
goldsquid
1f7dd60483 genesis for bob-sepolia 2026-06-09 13:02:21 +07:00
e9024c5c17 add op-reth sepolia variants for bob, worldchain, ink
Superchain Sepolia hardfork ~2026-06-19 drops op-geth support; op-erigon is
already broken post-hardfork. op-reth is the migration target for Superchain
members. Generates archive-trace, minimal-trace, and pruned-trace variants
via the 'full_minimal_trace' profile (mirroring base-sepolia / op-sepolia).
2026-06-09 05:37:19 +00:00
2e08acbe07 regenerate drifted celo-sepolia compose files
Pre-existing template change: bind-mount './op/celo/sepolia:/config' migrated to
parameterizable named docker volumes (CELO_SEPOLIA_OP_GETH_*_CONFIG /
CELO_SEPOLIA_OP_GETH_*_NODE_CONFIG with sensible defaults). Surfaced when
running update.sh on top of the current rpc/ submodule HEAD.
2026-06-09 05:37:19 +00:00
404 changed files with 15836 additions and 2791 deletions

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
abstract-mainnet-archive: abstract-mainnet-archive:
image: ${ABSTRACT_EXTERNAL_NODE_IMAGE:-matterlabs/external-node}:${ABSTRACT_MAINNET_EXTERNAL_NODE_VERSION:-v29.17.0} image: ${ABSTRACT_EXTERNAL_NODE_IMAGE:-matterlabs/external-node}:${ABSTRACT_MAINNET_EXTERNAL_NODE_VERSION:-v31.0.0}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
@@ -98,8 +98,8 @@ services:
- traefik.http.routers.abstract-mainnet-external-node-archive.service=abstract-mainnet-external-node-archive - traefik.http.routers.abstract-mainnet-external-node-archive.service=abstract-mainnet-external-node-archive
- ${NO_SSL:-traefik.http.routers.abstract-mainnet-external-node-archive-ws.entrypoints=websecure} - ${NO_SSL:-traefik.http.routers.abstract-mainnet-external-node-archive-ws.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.abstract-mainnet-external-node-archive-ws.tls.certresolver=myresolver} - ${NO_SSL:-traefik.http.routers.abstract-mainnet-external-node-archive-ws.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.abstract-mainnet-external-node-archive-ws.rule=Host(`$DOMAIN`) && (Path(`/abstract-mainnet-archive`) || Path(`/abstract-mainnet-archive/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:-traefik.http.routers.abstract-mainnet-external-node-archive-ws.rule=Host(`$DOMAIN`) && (Path(`/abstract-mainnet-archive`) || Path(`/abstract-mainnet-archive/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- ${NO_SSL:+traefik.http.routers.abstract-mainnet-external-node-archive-ws.rule=(Path(`/abstract-mainnet-archive`) || Path(`/abstract-mainnet-archive/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:+traefik.http.routers.abstract-mainnet-external-node-archive-ws.rule=(Path(`/abstract-mainnet-archive`) || Path(`/abstract-mainnet-archive/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- traefik.http.routers.abstract-mainnet-external-node-archive-ws.middlewares=abstract-mainnet-external-node-archive-stripprefix, ipallowlist - traefik.http.routers.abstract-mainnet-external-node-archive-ws.middlewares=abstract-mainnet-external-node-archive-stripprefix, ipallowlist
abstract-mainnet-archive-db: abstract-mainnet-archive-db:

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
abstract-mainnet: abstract-mainnet:
image: ${ABSTRACT_EXTERNAL_NODE_IMAGE:-matterlabs/external-node}:${ABSTRACT_MAINNET_EXTERNAL_NODE_VERSION:-v29.17.0} image: ${ABSTRACT_EXTERNAL_NODE_IMAGE:-matterlabs/external-node}:${ABSTRACT_MAINNET_EXTERNAL_NODE_VERSION:-v31.0.0}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
@@ -98,8 +98,8 @@ services:
- traefik.http.routers.abstract-mainnet-external-node-pruned.service=abstract-mainnet-external-node-pruned - traefik.http.routers.abstract-mainnet-external-node-pruned.service=abstract-mainnet-external-node-pruned
- ${NO_SSL:-traefik.http.routers.abstract-mainnet-external-node-pruned-ws.entrypoints=websecure} - ${NO_SSL:-traefik.http.routers.abstract-mainnet-external-node-pruned-ws.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.abstract-mainnet-external-node-pruned-ws.tls.certresolver=myresolver} - ${NO_SSL:-traefik.http.routers.abstract-mainnet-external-node-pruned-ws.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.abstract-mainnet-external-node-pruned-ws.rule=Host(`$DOMAIN`) && (Path(`/abstract-mainnet`) || Path(`/abstract-mainnet/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:-traefik.http.routers.abstract-mainnet-external-node-pruned-ws.rule=Host(`$DOMAIN`) && (Path(`/abstract-mainnet`) || Path(`/abstract-mainnet/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- ${NO_SSL:+traefik.http.routers.abstract-mainnet-external-node-pruned-ws.rule=(Path(`/abstract-mainnet`) || Path(`/abstract-mainnet/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:+traefik.http.routers.abstract-mainnet-external-node-pruned-ws.rule=(Path(`/abstract-mainnet`) || Path(`/abstract-mainnet/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- traefik.http.routers.abstract-mainnet-external-node-pruned-ws.middlewares=abstract-mainnet-external-node-pruned-stripprefix, ipallowlist - traefik.http.routers.abstract-mainnet-external-node-pruned-ws.middlewares=abstract-mainnet-external-node-pruned-stripprefix, ipallowlist
abstract-mainnet-db: abstract-mainnet-db:

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
abstract-testnet-archive: abstract-testnet-archive:
image: ${ABSTRACT_EXTERNAL_NODE_IMAGE:-matterlabs/external-node}:${ABSTRACT_TESTNET_EXTERNAL_NODE_VERSION:-v29.17.0} image: ${ABSTRACT_EXTERNAL_NODE_IMAGE:-matterlabs/external-node}:${ABSTRACT_TESTNET_EXTERNAL_NODE_VERSION:-v31.0.0}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
@@ -98,8 +98,8 @@ services:
- traefik.http.routers.abstract-testnet-external-node-archive.service=abstract-testnet-external-node-archive - traefik.http.routers.abstract-testnet-external-node-archive.service=abstract-testnet-external-node-archive
- ${NO_SSL:-traefik.http.routers.abstract-testnet-external-node-archive-ws.entrypoints=websecure} - ${NO_SSL:-traefik.http.routers.abstract-testnet-external-node-archive-ws.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.abstract-testnet-external-node-archive-ws.tls.certresolver=myresolver} - ${NO_SSL:-traefik.http.routers.abstract-testnet-external-node-archive-ws.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.abstract-testnet-external-node-archive-ws.rule=Host(`$DOMAIN`) && (Path(`/abstract-testnet-archive`) || Path(`/abstract-testnet-archive/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:-traefik.http.routers.abstract-testnet-external-node-archive-ws.rule=Host(`$DOMAIN`) && (Path(`/abstract-testnet-archive`) || Path(`/abstract-testnet-archive/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- ${NO_SSL:+traefik.http.routers.abstract-testnet-external-node-archive-ws.rule=(Path(`/abstract-testnet-archive`) || Path(`/abstract-testnet-archive/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:+traefik.http.routers.abstract-testnet-external-node-archive-ws.rule=(Path(`/abstract-testnet-archive`) || Path(`/abstract-testnet-archive/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- traefik.http.routers.abstract-testnet-external-node-archive-ws.middlewares=abstract-testnet-external-node-archive-stripprefix, ipallowlist - traefik.http.routers.abstract-testnet-external-node-archive-ws.middlewares=abstract-testnet-external-node-archive-stripprefix, ipallowlist
abstract-testnet-archive-db: abstract-testnet-archive-db:

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
abstract-testnet: abstract-testnet:
image: ${ABSTRACT_EXTERNAL_NODE_IMAGE:-matterlabs/external-node}:${ABSTRACT_TESTNET_EXTERNAL_NODE_VERSION:-v29.17.0} image: ${ABSTRACT_EXTERNAL_NODE_IMAGE:-matterlabs/external-node}:${ABSTRACT_TESTNET_EXTERNAL_NODE_VERSION:-v31.0.0}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
@@ -98,8 +98,8 @@ services:
- traefik.http.routers.abstract-testnet-external-node-pruned.service=abstract-testnet-external-node-pruned - traefik.http.routers.abstract-testnet-external-node-pruned.service=abstract-testnet-external-node-pruned
- ${NO_SSL:-traefik.http.routers.abstract-testnet-external-node-pruned-ws.entrypoints=websecure} - ${NO_SSL:-traefik.http.routers.abstract-testnet-external-node-pruned-ws.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.abstract-testnet-external-node-pruned-ws.tls.certresolver=myresolver} - ${NO_SSL:-traefik.http.routers.abstract-testnet-external-node-pruned-ws.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.abstract-testnet-external-node-pruned-ws.rule=Host(`$DOMAIN`) && (Path(`/abstract-testnet`) || Path(`/abstract-testnet/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:-traefik.http.routers.abstract-testnet-external-node-pruned-ws.rule=Host(`$DOMAIN`) && (Path(`/abstract-testnet`) || Path(`/abstract-testnet/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- ${NO_SSL:+traefik.http.routers.abstract-testnet-external-node-pruned-ws.rule=(Path(`/abstract-testnet`) || Path(`/abstract-testnet/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:+traefik.http.routers.abstract-testnet-external-node-pruned-ws.rule=(Path(`/abstract-testnet`) || Path(`/abstract-testnet/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- traefik.http.routers.abstract-testnet-external-node-pruned-ws.middlewares=abstract-testnet-external-node-pruned-stripprefix, ipallowlist - traefik.http.routers.abstract-testnet-external-node-pruned-ws.middlewares=abstract-testnet-external-node-pruned-stripprefix, ipallowlist
abstract-testnet-db: abstract-testnet-db:

View File

@@ -0,0 +1,5 @@
{
"chain": {
"info-json": "[{\"chain-id\": 33139, \"parent-chain-id\": 42161, \"chain-name\": \"apechain\", \"chain-config\": {\"chainId\": 33139, \"homesteadBlock\": 0, \"daoForkBlock\": null, \"daoForkSupport\": true, \"eip150Block\": 0, \"eip150Hash\": \"0x0000000000000000000000000000000000000000000000000000000000000000\", \"eip155Block\": 0, \"eip158Block\": 0, \"byzantiumBlock\": 0, \"constantinopleBlock\": 0, \"petersburgBlock\": 0, \"istanbulBlock\": 0, \"muirGlacierBlock\": 0, \"berlinBlock\": 0, \"londonBlock\": 0, \"clique\": {\"period\": 0, \"epoch\": 0}, \"arbitrum\": {\"EnableArbOS\": true, \"AllowDebugPrecompiles\": false, \"DataAvailabilityCommittee\": false, \"InitialArbOSVersion\": 31, \"EigenDA\": false, \"InitialChainOwner\": \"0x5737cdbb3a67001441c0da8b86e6b1826705601c\", \"GenesisBlockNum\": 0}}, \"rollup\": {\"bridge\": \"0x6B71AFb4b7725227ab944c96FE018AB9dc0434b8\", \"inbox\": \"0x1B98e4ED82Ee1a91A65a38C690e2266364064D15\", \"sequencer-inbox\": \"0xE6a92Ae29E24C343eE66A2B3D3ECB783d65E4a3C\", \"rollup\": \"0x374de579AE15aD59eD0519aeAf1A23F348Df259c\", \"validator-utils\": \"0xaB36aec5517C346D21b9C19429BAA5aa87D17fCa\", \"validator-wallet-creator\": \"0x5a6C98F6A60BDC02cE4d8AD43b4Fc88Fe5b38856\", \"deployed-at\": 247653199}, \"parent-chain-is-arbitrum\": true}]"
}
}

View File

@@ -0,0 +1,144 @@
---
x-logging-defaults: &logging-defaults
driver: json-file
options:
max-size: "10m"
max-file: "3"
# Usage:
#
# mkdir rpc && cd rpc
#
# git init
# git remote add origin https://github.com/StakeSquid/ethereum-rpc-docker.git
# git fetch origin vibe
# git checkout origin/vibe
#
# docker run --rm alpine sh -c "printf '0x'; head -c32 /dev/urandom | xxd -p -c 64" > .jwtsecret
#
# env
# ...
# IP=$(curl ipinfo.io/ip)
# DOMAIN=${IP}.traefik.me
# COMPOSE_FILE=base.yml:rpc.yml:arb/nitro/apechain-mainnet-nitro-archive-pebble-hash.yml
#
# docker compose up -d
#
# curl -X POST https://${IP}.traefik.me/apechain-mainnet-archive \
# -H "Content-Type: application/json" \
# --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
services:
apechain-mainnet-archive:
image: ${APECHAIN_NITRO_IMAGE:-public.ecr.aws/i6b2w2n6/nitro-node}:${APECHAIN_MAINNET_NITRO_VERSION:-apechain-v3.5.6}
sysctls:
# TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
net.ipv4.tcp_no_metrics_save: 1 # Disable metrics cache
net.ipv4.tcp_rmem: 4096 87380 16777216 # Increase TCP read buffers
net.ipv4.tcp_wmem: 4096 87380 16777216 # Increase TCP write buffers
net.core.somaxconn: 32768 # Higher connection queue
# Memory/Connection Management
# net.core.netdev_max_backlog: 50000 # Increase network buffer
net.ipv4.tcp_max_syn_backlog: 30000 # More SYN requests
net.ipv4.tcp_max_tw_buckets: 2000000 # Allow more TIME_WAIT sockets
ulimits:
nofile: 1048576 # Max open files (for RPC/WS connections)
user: root
expose:
- 8545
command:
- --conf.file=/config/baseConfig.json
- --execution.caching.archive=true
- --execution.caching.database-cache=${APECHAIN_MAINNET_NITRO_ARCHIVE_PEBBLE_HASH_DATABASE_CACHE:-2048}
- --execution.caching.snapshot-cache=${APECHAIN_MAINNET_NITRO_ARCHIVE_PEBBLE_HASH_SNAPSHOT_CACHE:-400}
- --execution.caching.trie-clean-cache=${APECHAIN_MAINNET_NITRO_ARCHIVE_PEBBLE_HASH_TRIE_CLEAN_CACHE:-600}
- --execution.caching.trie-dirty-cache=${APECHAIN_MAINNET_NITRO_ARCHIVE_PEBBLE_HASH_TRIE_DIRTY_CACHE:-1024}
- --execution.forwarding-target=https://rpc.apechain.com/http
- --execution.rpc.gas-cap=5500000000
- --execution.rpc.log-history=0
- --execution.sequencer.enable=false
- --http.addr=0.0.0.0
- --http.api=eth,net,web3,arb,txpool,debug
- --http.corsdomain=*
- --http.port=8545
- --http.vhosts=*
- --metrics
- --metrics-server.addr=0.0.0.0
- --metrics-server.port=6070
- --node.batch-poster.enable=false
- --node.data-availability.enable=true
- --node.data-availability.rest-aggregator.enable=true
- --node.data-availability.rest-aggregator.urls=https://apechain.calderachain.xyz/rest-aggregator
- --node.feed.input.url=wss://apechain.calderachain.xyz/feed
- --node.sequencer=false
- --node.staker.enable=false
- --parent-chain.connection.url=https://arb1.arbitrum.io/rpc
- --persistent.chain=/root/.arbitrum/apechain-mainnet-archive
- --persistent.db-engine=pebble
- --ws.addr=0.0.0.0
- --ws.origins=*
- --ws.port=8545
restart: unless-stopped
stop_grace_period: 5m
networks:
- chains
volumes:
- ${APECHAIN_MAINNET_NITRO_ARCHIVE_PEBBLE_HASH_DATA:-apechain-mainnet-nitro-archive-pebble-hash}:/root/.arbitrum
- ./arb/apechain/arbitrum-one:/config
- /slowdisk:/slowdisk
logging: *logging-defaults
labels:
- prometheus-scrape.enabled=true
- prometheus-scrape.port=6070
- prometheus-scrape.path=/debug/metrics/prometheus
- traefik.enable=true
- traefik.http.middlewares.apechain-mainnet-nitro-archive-pebble-hash-stripprefix.stripprefix.prefixes=/apechain-mainnet-archive
- traefik.http.services.apechain-mainnet-nitro-archive-pebble-hash.loadbalancer.server.port=8545
- ${NO_SSL:-traefik.http.routers.apechain-mainnet-nitro-archive-pebble-hash.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.apechain-mainnet-nitro-archive-pebble-hash.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.apechain-mainnet-nitro-archive-pebble-hash.rule=Host(`$DOMAIN`) && (Path(`/apechain-mainnet-archive`) || Path(`/apechain-mainnet-archive/`))}
- ${NO_SSL:+traefik.http.routers.apechain-mainnet-nitro-archive-pebble-hash.rule=Path(`/apechain-mainnet-archive`) || Path(`/apechain-mainnet-archive/`)}
- traefik.http.routers.apechain-mainnet-nitro-archive-pebble-hash.middlewares=apechain-mainnet-nitro-archive-pebble-hash-stripprefix, ipallowlist
volumes:
apechain-mainnet-nitro-archive-pebble-hash:
x-upstreams:
- id: $${ID}
labels:
provider: $${PROVIDER}
connection:
generic:
rpc:
url: $${RPC_URL}
ws:
frameSize: 20Mb
msgSize: 50Mb
url: $${WS_URL}
chain: apechain
method-groups:
enabled:
- debug
- filter
methods:
disabled:
enabled:
- name: txpool_content # TODO: should be disabled for rollup nodes
# standard geth only
- name: debug_getRawBlock
- name: debug_getRawTransaction
- name: debug_getRawReceipts
- name: debug_getRawHeader
- name: debug_getBadBlocks
# non standard geth only slightly dangerous
- name: debug_intermediateRoots
- name: debug_dumpBlock
# standard geth and erigon
- name: debug_accountRange
- name: debug_getModifiedAccountsByNumber
- name: debug_getModifiedAccountsByHash
# non standard geth and erigon
- name: eth_getRawTransactionByHash
- name: eth_getRawTransactionByBlockHashAndIndex
...

View File

@@ -0,0 +1,146 @@
---
x-logging-defaults: &logging-defaults
driver: json-file
options:
max-size: "10m"
max-file: "3"
# Usage:
#
# mkdir rpc && cd rpc
#
# git init
# git remote add origin https://github.com/StakeSquid/ethereum-rpc-docker.git
# git fetch origin vibe
# git checkout origin/vibe
#
# docker run --rm alpine sh -c "printf '0x'; head -c32 /dev/urandom | xxd -p -c 64" > .jwtsecret
#
# env
# ...
# IP=$(curl ipinfo.io/ip)
# DOMAIN=${IP}.traefik.me
# COMPOSE_FILE=base.yml:rpc.yml:arb/nitro/apechain-mainnet-nitro-pruned-pebble-path.yml
#
# docker compose up -d
#
# curl -X POST https://${IP}.traefik.me/apechain-mainnet \
# -H "Content-Type: application/json" \
# --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
services:
apechain-mainnet:
image: ${APECHAIN_NITRO_IMAGE:-public.ecr.aws/i6b2w2n6/nitro-node}:${APECHAIN_MAINNET_NITRO_VERSION:-apechain-v3.5.6}
sysctls:
# TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
net.ipv4.tcp_no_metrics_save: 1 # Disable metrics cache
net.ipv4.tcp_rmem: 4096 87380 16777216 # Increase TCP read buffers
net.ipv4.tcp_wmem: 4096 87380 16777216 # Increase TCP write buffers
net.core.somaxconn: 32768 # Higher connection queue
# Memory/Connection Management
# net.core.netdev_max_backlog: 50000 # Increase network buffer
net.ipv4.tcp_max_syn_backlog: 30000 # More SYN requests
net.ipv4.tcp_max_tw_buckets: 2000000 # Allow more TIME_WAIT sockets
ulimits:
nofile: 1048576 # Max open files (for RPC/WS connections)
user: root
expose:
- 8545
command:
- --conf.file=/config/baseConfig.json
- --execution.caching.archive=${APECHAIN_MAINNET_ARCHIVE_DB:-false}
- --execution.caching.database-cache=${APECHAIN_MAINNET_NITRO_PRUNED_PEBBLE_PATH_DATABASE_CACHE:-2048}
- --execution.caching.snapshot-cache=${APECHAIN_MAINNET_NITRO_PRUNED_PEBBLE_PATH_SNAPSHOT_CACHE:-400}
- --execution.caching.state-scheme=path
- --execution.caching.trie-clean-cache=${APECHAIN_MAINNET_NITRO_PRUNED_PEBBLE_PATH_TRIE_CLEAN_CACHE:-600}
- --execution.caching.trie-dirty-cache=${APECHAIN_MAINNET_NITRO_PRUNED_PEBBLE_PATH_TRIE_DIRTY_CACHE:-1024}
- --execution.forwarding-target=https://rpc.apechain.com/http
- --execution.rpc.gas-cap=5500000000
- --execution.sequencer.enable=false
- --http.addr=0.0.0.0
- --http.api=eth,net,web3,arb,txpool,debug
- --http.corsdomain=*
- --http.port=8545
- --http.vhosts=*
- --metrics
- --metrics-server.addr=0.0.0.0
- --metrics-server.port=6070
- --node.batch-poster.enable=false
- --node.data-availability.enable=true
- --node.data-availability.rest-aggregator.enable=true
- --node.data-availability.rest-aggregator.urls=https://apechain.calderachain.xyz/rest-aggregator
- --node.feed.input.url=wss://apechain.calderachain.xyz/feed
- --node.sequencer=false
- --node.staker.enable=false
- --parent-chain.connection.url=https://arb1.arbitrum.io/rpc
- --persistent.chain=/root/.arbitrum/apechain-mainnet
- --persistent.db-engine=pebble
- --ws.addr=0.0.0.0
- --ws.origins=*
- --ws.port=8545
restart: unless-stopped
stop_grace_period: 5m
networks:
- chains
volumes:
- ${APECHAIN_MAINNET_NITRO_PRUNED_PEBBLE_PATH_DATA:-apechain-mainnet-nitro-pruned-pebble-path}:/root/.arbitrum
- ./arb/apechain/arbitrum-one:/config
- /slowdisk:/slowdisk
logging: *logging-defaults
labels:
- prometheus-scrape.enabled=true
- prometheus-scrape.port=6070
- prometheus-scrape.path=/debug/metrics/prometheus
- traefik.enable=true
- traefik.http.middlewares.apechain-mainnet-nitro-pruned-pebble-path-stripprefix.stripprefix.prefixes=/apechain-mainnet
- traefik.http.services.apechain-mainnet-nitro-pruned-pebble-path.loadbalancer.server.port=8545
- ${NO_SSL:-traefik.http.routers.apechain-mainnet-nitro-pruned-pebble-path.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.apechain-mainnet-nitro-pruned-pebble-path.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.apechain-mainnet-nitro-pruned-pebble-path.rule=Host(`$DOMAIN`) && (Path(`/apechain-mainnet`) || Path(`/apechain-mainnet/`))}
- ${NO_SSL:+traefik.http.routers.apechain-mainnet-nitro-pruned-pebble-path.rule=Path(`/apechain-mainnet`) || Path(`/apechain-mainnet/`)}
- traefik.http.routers.apechain-mainnet-nitro-pruned-pebble-path.middlewares=apechain-mainnet-nitro-pruned-pebble-path-stripprefix, ipallowlist
volumes:
apechain-mainnet-nitro-pruned-pebble-path:
x-upstreams:
- id: $${ID}
labels:
provider: $${PROVIDER}
connection:
generic:
rpc:
url: $${RPC_URL}
ws:
frameSize: 20Mb
msgSize: 50Mb
url: $${WS_URL}
chain: apechain
method-groups:
enabled:
- debug
- filter
methods:
disabled:
# not compatible with path state scheme
- name: debug_traceBlockByHash
enabled:
- name: txpool_content # TODO: should be disabled for rollup nodes
# standard geth only
- name: debug_getRawBlock
- name: debug_getRawTransaction
- name: debug_getRawReceipts
- name: debug_getRawHeader
- name: debug_getBadBlocks
# non standard geth only slightly dangerous
- name: debug_intermediateRoots
- name: debug_dumpBlock
# standard geth and erigon
- name: debug_accountRange
- name: debug_getModifiedAccountsByNumber
- name: debug_getModifiedAccountsByHash
# non standard geth and erigon
- name: eth_getRawTransactionByHash
- name: eth_getRawTransactionByBlockHashAndIndex
...

View File

@@ -0,0 +1,141 @@
---
x-logging-defaults: &logging-defaults
driver: json-file
options:
max-size: "10m"
max-file: "3"
# Usage:
#
# mkdir rpc && cd rpc
#
# git init
# git remote add origin https://github.com/StakeSquid/ethereum-rpc-docker.git
# git fetch origin vibe
# git checkout origin/vibe
#
# docker run --rm alpine sh -c "printf '0x'; head -c32 /dev/urandom | xxd -p -c 64" > .jwtsecret
#
# env
# ...
# IP=$(curl ipinfo.io/ip)
# DOMAIN=${IP}.traefik.me
# COMPOSE_FILE=base.yml:rpc.yml:arb/nitro/arbitrum-nova-nitro-minimal-pebble-hash.yml
#
# docker compose up -d
#
# curl -X POST https://${IP}.traefik.me/arbitrum-nova-minimal \
# -H "Content-Type: application/json" \
# --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
services:
arbitrum-nova-minimal:
image: ${ARBITRUM_NITRO_IMAGE:-offchainlabs/nitro-node}:${ARBITRUM_NOVA_NITRO_VERSION:-v3.10.1-d7f07be}
sysctls:
# TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
net.ipv4.tcp_no_metrics_save: 1 # Disable metrics cache
net.ipv4.tcp_rmem: 4096 87380 16777216 # Increase TCP read buffers
net.ipv4.tcp_wmem: 4096 87380 16777216 # Increase TCP write buffers
net.core.somaxconn: 32768 # Higher connection queue
# Memory/Connection Management
# net.core.netdev_max_backlog: 50000 # Increase network buffer
net.ipv4.tcp_max_syn_backlog: 30000 # More SYN requests
net.ipv4.tcp_max_tw_buckets: 2000000 # Allow more TIME_WAIT sockets
ulimits:
nofile: 1048576 # Max open files (for RPC/WS connections)
user: root
expose:
- 8545
command:
- --chain.id=42170
- --execution.caching.archive=${ARBITRUM_NOVA_MINIMAL_ARCHIVE_DB:-false}
- --execution.caching.database-cache=${ARBITRUM_NOVA_NITRO_MINIMAL_PEBBLE_HASH_DATABASE_CACHE:-2048}
- --execution.caching.snapshot-cache=${ARBITRUM_NOVA_NITRO_MINIMAL_PEBBLE_HASH_SNAPSHOT_CACHE:-400}
- --execution.caching.trie-clean-cache=${ARBITRUM_NOVA_NITRO_MINIMAL_PEBBLE_HASH_TRIE_CLEAN_CACHE:-600}
- --execution.caching.trie-dirty-cache=${ARBITRUM_NOVA_NITRO_MINIMAL_PEBBLE_HASH_TRIE_DIRTY_CACHE:-1024}
- --execution.rpc.gas-cap=5500000000
- --execution.rpc.log-history=0
- --execution.sequencer.enable=false
- --http.addr=0.0.0.0
- --http.api=eth,net,web3,arb,txpool,debug
- --http.corsdomain=*
- --http.port=8545
- --http.vhosts=*
- --init.prune=minimal
- --metrics
- --metrics-server.addr=0.0.0.0
- --metrics-server.port=6070
- --node.batch-poster.enable=false
- --node.sequencer=false
- --node.staker.enable=false
- --parent-chain.blob-client.beacon-url=${ETHEREUM_MAINNET_BEACON_REST}
- --parent-chain.connection.url=${ETHEREUM_MAINNET_EXECUTION_RPC}
- --persistent.chain=/root/.arbitrum/arbitrum-nova-minimal
- --persistent.db-engine=pebble
- --ws.addr=0.0.0.0
- --ws.origins=*
- --ws.port=8545
restart: unless-stopped
stop_grace_period: 5m
networks:
- chains
volumes:
- ${ARBITRUM_NOVA_NITRO_MINIMAL_PEBBLE_HASH_DATA:-arbitrum-nova-nitro-minimal-pebble-hash}:/root/.arbitrum
- ./tmp/arbitrum-nova-minimal:/tmp
- /slowdisk:/slowdisk
logging: *logging-defaults
labels:
- prometheus-scrape.enabled=true
- prometheus-scrape.port=6070
- prometheus-scrape.path=/debug/metrics/prometheus
- traefik.enable=true
- traefik.http.middlewares.arbitrum-nova-nitro-minimal-pebble-hash-stripprefix.stripprefix.prefixes=/arbitrum-nova-minimal
- traefik.http.services.arbitrum-nova-nitro-minimal-pebble-hash.loadbalancer.server.port=8545
- ${NO_SSL:-traefik.http.routers.arbitrum-nova-nitro-minimal-pebble-hash.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.arbitrum-nova-nitro-minimal-pebble-hash.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.arbitrum-nova-nitro-minimal-pebble-hash.rule=Host(`$DOMAIN`) && (Path(`/arbitrum-nova-minimal`) || Path(`/arbitrum-nova-minimal/`))}
- ${NO_SSL:+traefik.http.routers.arbitrum-nova-nitro-minimal-pebble-hash.rule=Path(`/arbitrum-nova-minimal`) || Path(`/arbitrum-nova-minimal/`)}
- traefik.http.routers.arbitrum-nova-nitro-minimal-pebble-hash.middlewares=arbitrum-nova-nitro-minimal-pebble-hash-stripprefix, ipallowlist
volumes:
arbitrum-nova-nitro-minimal-pebble-hash:
x-upstreams:
- id: $${ID}
labels:
provider: $${PROVIDER}
connection:
generic:
rpc:
url: $${RPC_URL}
ws:
frameSize: 20Mb
msgSize: 50Mb
url: $${WS_URL}
chain: arbitrum-nova
method-groups:
enabled:
- debug
- filter
methods:
disabled:
enabled:
- name: txpool_content # TODO: should be disabled for rollup nodes
# standard geth only
- name: debug_getRawBlock
- name: debug_getRawTransaction
- name: debug_getRawReceipts
- name: debug_getRawHeader
- name: debug_getBadBlocks
# non standard geth only slightly dangerous
- name: debug_intermediateRoots
- name: debug_dumpBlock
# standard geth and erigon
- name: debug_accountRange
- name: debug_getModifiedAccountsByNumber
- name: debug_getModifiedAccountsByHash
# non standard geth and erigon
- name: eth_getRawTransactionByHash
- name: eth_getRawTransactionByBlockHashAndIndex
...

View File

@@ -0,0 +1,140 @@
---
x-logging-defaults: &logging-defaults
driver: json-file
options:
max-size: "10m"
max-file: "3"
# Usage:
#
# mkdir rpc && cd rpc
#
# git init
# git remote add origin https://github.com/StakeSquid/ethereum-rpc-docker.git
# git fetch origin vibe
# git checkout origin/vibe
#
# docker run --rm alpine sh -c "printf '0x'; head -c32 /dev/urandom | xxd -p -c 64" > .jwtsecret
#
# env
# ...
# IP=$(curl ipinfo.io/ip)
# DOMAIN=${IP}.traefik.me
# COMPOSE_FILE=base.yml:rpc.yml:arb/nitro/arbitrum-nova-nitro-minimal-pebble-hash.yml
#
# docker compose up -d
#
# curl -X POST https://${IP}.traefik.me/arbitrum-nova-minimal \
# -H "Content-Type: application/json" \
# --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
services:
arbitrum-nova-minimal:
image: ${ARBITRUM_NITRO_IMAGE:-offchainlabs/nitro-node}:${ARBITRUM_NOVA_NITRO_VERSION:-v3.10.1-d7f07be}
sysctls:
# TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
net.ipv4.tcp_no_metrics_save: 1 # Disable metrics cache
net.ipv4.tcp_rmem: 4096 87380 16777216 # Increase TCP read buffers
net.ipv4.tcp_wmem: 4096 87380 16777216 # Increase TCP write buffers
net.core.somaxconn: 32768 # Higher connection queue
# Memory/Connection Management
# net.core.netdev_max_backlog: 50000 # Increase network buffer
net.ipv4.tcp_max_syn_backlog: 30000 # More SYN requests
net.ipv4.tcp_max_tw_buckets: 2000000 # Allow more TIME_WAIT sockets
ulimits:
nofile: 1048576 # Max open files (for RPC/WS connections)
user: root
expose:
- 8545
command:
- --chain.id=42170
- --execution.caching.archive=${ARBITRUM_NOVA_MINIMAL_ARCHIVE_DB:-false}
- --execution.caching.database-cache=${ARBITRUM_NOVA_NITRO_MINIMAL_PEBBLE_HASH_DATABASE_CACHE:-2048}
- --execution.caching.snapshot-cache=${ARBITRUM_NOVA_NITRO_MINIMAL_PEBBLE_HASH_SNAPSHOT_CACHE:-400}
- --execution.caching.trie-clean-cache=${ARBITRUM_NOVA_NITRO_MINIMAL_PEBBLE_HASH_TRIE_CLEAN_CACHE:-600}
- --execution.caching.trie-dirty-cache=${ARBITRUM_NOVA_NITRO_MINIMAL_PEBBLE_HASH_TRIE_DIRTY_CACHE:-1024}
- --execution.rpc.gas-cap=5500000000
- --execution.rpc.log-history=0
- --execution.sequencer.enable=false
- --http.addr=0.0.0.0
- --http.api=eth,net,web3,arb,txpool,debug
- --http.corsdomain=*
- --http.port=8545
- --http.vhosts=*
- --metrics
- --metrics-server.addr=0.0.0.0
- --metrics-server.port=6070
- --node.batch-poster.enable=false
- --node.sequencer=false
- --node.staker.enable=false
- --parent-chain.blob-client.beacon-url=${ETHEREUM_MAINNET_BEACON_REST}
- --parent-chain.connection.url=${ETHEREUM_MAINNET_EXECUTION_RPC}
- --persistent.chain=/root/.arbitrum/arbitrum-nova-minimal
- --persistent.db-engine=pebble
- --ws.addr=0.0.0.0
- --ws.origins=*
- --ws.port=8545
restart: unless-stopped
stop_grace_period: 5m
networks:
- chains
volumes:
- ${ARBITRUM_NOVA_NITRO_MINIMAL_PEBBLE_HASH_DATA:-arbitrum-nova-nitro-minimal-pebble-hash}:/root/.arbitrum
- ./tmp/arbitrum-nova-minimal:/tmp
- /slowdisk:/slowdisk
logging: *logging-defaults
labels:
- prometheus-scrape.enabled=true
- prometheus-scrape.port=6070
- prometheus-scrape.path=/debug/metrics/prometheus
- traefik.enable=true
- traefik.http.middlewares.arbitrum-nova-nitro-minimal-pebble-hash-stripprefix.stripprefix.prefixes=/arbitrum-nova-minimal
- traefik.http.services.arbitrum-nova-nitro-minimal-pebble-hash.loadbalancer.server.port=8545
- ${NO_SSL:-traefik.http.routers.arbitrum-nova-nitro-minimal-pebble-hash.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.arbitrum-nova-nitro-minimal-pebble-hash.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.arbitrum-nova-nitro-minimal-pebble-hash.rule=Host(`$DOMAIN`) && (Path(`/arbitrum-nova-minimal`) || Path(`/arbitrum-nova-minimal/`))}
- ${NO_SSL:+traefik.http.routers.arbitrum-nova-nitro-minimal-pebble-hash.rule=Path(`/arbitrum-nova-minimal`) || Path(`/arbitrum-nova-minimal/`)}
- traefik.http.routers.arbitrum-nova-nitro-minimal-pebble-hash.middlewares=arbitrum-nova-nitro-minimal-pebble-hash-stripprefix, ipallowlist
volumes:
arbitrum-nova-nitro-minimal-pebble-hash:
x-upstreams:
- id: $${ID}
labels:
provider: $${PROVIDER}
connection:
generic:
rpc:
url: $${RPC_URL}
ws:
frameSize: 20Mb
msgSize: 50Mb
url: $${WS_URL}
chain: arbitrum-nova
method-groups:
enabled:
- debug
- filter
methods:
disabled:
enabled:
- name: txpool_content # TODO: should be disabled for rollup nodes
# standard geth only
- name: debug_getRawBlock
- name: debug_getRawTransaction
- name: debug_getRawReceipts
- name: debug_getRawHeader
- name: debug_getBadBlocks
# non standard geth only slightly dangerous
- name: debug_intermediateRoots
- name: debug_dumpBlock
# standard geth and erigon
- name: debug_accountRange
- name: debug_getModifiedAccountsByNumber
- name: debug_getModifiedAccountsByHash
# non standard geth and erigon
- name: eth_getRawTransactionByHash
- name: eth_getRawTransactionByBlockHashAndIndex
...

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
arbitrum-nova: arbitrum-nova:
image: ${ARBITRUM_NITRO_IMAGE:-offchainlabs/nitro-node}:${ARBITRUM_NOVA_NITRO_VERSION:-v3.9.5-66e42c4} image: ${ARBITRUM_NITRO_IMAGE:-offchainlabs/nitro-node}:${ARBITRUM_NOVA_NITRO_VERSION:-v3.10.1-d7f07be}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

View File

@@ -0,0 +1,141 @@
---
x-logging-defaults: &logging-defaults
driver: json-file
options:
max-size: "10m"
max-file: "3"
# Usage:
#
# mkdir rpc && cd rpc
#
# git init
# git remote add origin https://github.com/StakeSquid/ethereum-rpc-docker.git
# git fetch origin vibe
# git checkout origin/vibe
#
# docker run --rm alpine sh -c "printf '0x'; head -c32 /dev/urandom | xxd -p -c 64" > .jwtsecret
#
# env
# ...
# IP=$(curl ipinfo.io/ip)
# DOMAIN=${IP}.traefik.me
# COMPOSE_FILE=base.yml:rpc.yml:arb/nitro/arbitrum-one-nitro-minimal-pebble-hash.yml
#
# docker compose up -d
#
# curl -X POST https://${IP}.traefik.me/arbitrum-one-minimal \
# -H "Content-Type: application/json" \
# --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
services:
arbitrum-one-minimal:
image: ${ARBITRUM_NITRO_IMAGE:-offchainlabs/nitro-node}:${ARBITRUM_ONE_NITRO_VERSION:-v3.10.1-d7f07be}
sysctls:
# TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
net.ipv4.tcp_no_metrics_save: 1 # Disable metrics cache
net.ipv4.tcp_rmem: 4096 87380 16777216 # Increase TCP read buffers
net.ipv4.tcp_wmem: 4096 87380 16777216 # Increase TCP write buffers
net.core.somaxconn: 32768 # Higher connection queue
# Memory/Connection Management
# net.core.netdev_max_backlog: 50000 # Increase network buffer
net.ipv4.tcp_max_syn_backlog: 30000 # More SYN requests
net.ipv4.tcp_max_tw_buckets: 2000000 # Allow more TIME_WAIT sockets
ulimits:
nofile: 1048576 # Max open files (for RPC/WS connections)
user: root
expose:
- 8545
command:
- --chain.id=42161
- --execution.caching.archive=${ARBITRUM_ONE_MINIMAL_ARCHIVE_DB:-false}
- --execution.caching.database-cache=${ARBITRUM_ONE_NITRO_MINIMAL_PEBBLE_HASH_DATABASE_CACHE:-2048}
- --execution.caching.snapshot-cache=${ARBITRUM_ONE_NITRO_MINIMAL_PEBBLE_HASH_SNAPSHOT_CACHE:-400}
- --execution.caching.trie-clean-cache=${ARBITRUM_ONE_NITRO_MINIMAL_PEBBLE_HASH_TRIE_CLEAN_CACHE:-600}
- --execution.caching.trie-dirty-cache=${ARBITRUM_ONE_NITRO_MINIMAL_PEBBLE_HASH_TRIE_DIRTY_CACHE:-1024}
- --execution.rpc.gas-cap=5500000000
- --execution.rpc.log-history=0
- --execution.sequencer.enable=false
- --http.addr=0.0.0.0
- --http.api=eth,net,web3,arb,txpool,debug
- --http.corsdomain=*
- --http.port=8545
- --http.vhosts=*
- --init.prune=minimal
- --metrics
- --metrics-server.addr=0.0.0.0
- --metrics-server.port=6070
- --node.batch-poster.enable=false
- --node.sequencer=false
- --node.staker.enable=false
- --parent-chain.blob-client.beacon-url=${ETHEREUM_MAINNET_BEACON_REST}
- --parent-chain.connection.url=${ETHEREUM_MAINNET_EXECUTION_RPC}
- --persistent.chain=/root/.arbitrum/arbitrum-one-minimal
- --persistent.db-engine=pebble
- --ws.addr=0.0.0.0
- --ws.origins=*
- --ws.port=8545
restart: unless-stopped
stop_grace_period: 5m
networks:
- chains
volumes:
- ${ARBITRUM_ONE_NITRO_MINIMAL_PEBBLE_HASH_DATA:-arbitrum-one-nitro-minimal-pebble-hash}:/root/.arbitrum
- ./tmp/arbitrum-one-minimal:/tmp
- /slowdisk:/slowdisk
logging: *logging-defaults
labels:
- prometheus-scrape.enabled=true
- prometheus-scrape.port=6070
- prometheus-scrape.path=/debug/metrics/prometheus
- traefik.enable=true
- traefik.http.middlewares.arbitrum-one-nitro-minimal-pebble-hash-stripprefix.stripprefix.prefixes=/arbitrum-one-minimal
- traefik.http.services.arbitrum-one-nitro-minimal-pebble-hash.loadbalancer.server.port=8545
- ${NO_SSL:-traefik.http.routers.arbitrum-one-nitro-minimal-pebble-hash.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.arbitrum-one-nitro-minimal-pebble-hash.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.arbitrum-one-nitro-minimal-pebble-hash.rule=Host(`$DOMAIN`) && (Path(`/arbitrum-one-minimal`) || Path(`/arbitrum-one-minimal/`))}
- ${NO_SSL:+traefik.http.routers.arbitrum-one-nitro-minimal-pebble-hash.rule=Path(`/arbitrum-one-minimal`) || Path(`/arbitrum-one-minimal/`)}
- traefik.http.routers.arbitrum-one-nitro-minimal-pebble-hash.middlewares=arbitrum-one-nitro-minimal-pebble-hash-stripprefix, ipallowlist
volumes:
arbitrum-one-nitro-minimal-pebble-hash:
x-upstreams:
- id: $${ID}
labels:
provider: $${PROVIDER}
connection:
generic:
rpc:
url: $${RPC_URL}
ws:
frameSize: 20Mb
msgSize: 50Mb
url: $${WS_URL}
chain: arbitrum
method-groups:
enabled:
- debug
- filter
methods:
disabled:
enabled:
- name: txpool_content # TODO: should be disabled for rollup nodes
# standard geth only
- name: debug_getRawBlock
- name: debug_getRawTransaction
- name: debug_getRawReceipts
- name: debug_getRawHeader
- name: debug_getBadBlocks
# non standard geth only slightly dangerous
- name: debug_intermediateRoots
- name: debug_dumpBlock
# standard geth and erigon
- name: debug_accountRange
- name: debug_getModifiedAccountsByNumber
- name: debug_getModifiedAccountsByHash
# non standard geth and erigon
- name: eth_getRawTransactionByHash
- name: eth_getRawTransactionByBlockHashAndIndex
...

View File

@@ -0,0 +1,140 @@
---
x-logging-defaults: &logging-defaults
driver: json-file
options:
max-size: "10m"
max-file: "3"
# Usage:
#
# mkdir rpc && cd rpc
#
# git init
# git remote add origin https://github.com/StakeSquid/ethereum-rpc-docker.git
# git fetch origin vibe
# git checkout origin/vibe
#
# docker run --rm alpine sh -c "printf '0x'; head -c32 /dev/urandom | xxd -p -c 64" > .jwtsecret
#
# env
# ...
# IP=$(curl ipinfo.io/ip)
# DOMAIN=${IP}.traefik.me
# COMPOSE_FILE=base.yml:rpc.yml:arb/nitro/arbitrum-one-nitro-minimal-pebble-hash.yml
#
# docker compose up -d
#
# curl -X POST https://${IP}.traefik.me/arbitrum-one-minimal \
# -H "Content-Type: application/json" \
# --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
services:
arbitrum-one-minimal:
image: ${ARBITRUM_NITRO_IMAGE:-offchainlabs/nitro-node}:${ARBITRUM_ONE_NITRO_VERSION:-v3.10.1-d7f07be}
sysctls:
# TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
net.ipv4.tcp_no_metrics_save: 1 # Disable metrics cache
net.ipv4.tcp_rmem: 4096 87380 16777216 # Increase TCP read buffers
net.ipv4.tcp_wmem: 4096 87380 16777216 # Increase TCP write buffers
net.core.somaxconn: 32768 # Higher connection queue
# Memory/Connection Management
# net.core.netdev_max_backlog: 50000 # Increase network buffer
net.ipv4.tcp_max_syn_backlog: 30000 # More SYN requests
net.ipv4.tcp_max_tw_buckets: 2000000 # Allow more TIME_WAIT sockets
ulimits:
nofile: 1048576 # Max open files (for RPC/WS connections)
user: root
expose:
- 8545
command:
- --chain.id=42161
- --execution.caching.archive=${ARBITRUM_ONE_MINIMAL_ARCHIVE_DB:-false}
- --execution.caching.database-cache=${ARBITRUM_ONE_NITRO_MINIMAL_PEBBLE_HASH_DATABASE_CACHE:-2048}
- --execution.caching.snapshot-cache=${ARBITRUM_ONE_NITRO_MINIMAL_PEBBLE_HASH_SNAPSHOT_CACHE:-400}
- --execution.caching.trie-clean-cache=${ARBITRUM_ONE_NITRO_MINIMAL_PEBBLE_HASH_TRIE_CLEAN_CACHE:-600}
- --execution.caching.trie-dirty-cache=${ARBITRUM_ONE_NITRO_MINIMAL_PEBBLE_HASH_TRIE_DIRTY_CACHE:-1024}
- --execution.rpc.gas-cap=5500000000
- --execution.rpc.log-history=0
- --execution.sequencer.enable=false
- --http.addr=0.0.0.0
- --http.api=eth,net,web3,arb,txpool,debug
- --http.corsdomain=*
- --http.port=8545
- --http.vhosts=*
- --metrics
- --metrics-server.addr=0.0.0.0
- --metrics-server.port=6070
- --node.batch-poster.enable=false
- --node.sequencer=false
- --node.staker.enable=false
- --parent-chain.blob-client.beacon-url=${ETHEREUM_MAINNET_BEACON_REST}
- --parent-chain.connection.url=${ETHEREUM_MAINNET_EXECUTION_RPC}
- --persistent.chain=/root/.arbitrum/arbitrum-one-minimal
- --persistent.db-engine=pebble
- --ws.addr=0.0.0.0
- --ws.origins=*
- --ws.port=8545
restart: unless-stopped
stop_grace_period: 5m
networks:
- chains
volumes:
- ${ARBITRUM_ONE_NITRO_MINIMAL_PEBBLE_HASH_DATA:-arbitrum-one-nitro-minimal-pebble-hash}:/root/.arbitrum
- ./tmp/arbitrum-one-minimal:/tmp
- /slowdisk:/slowdisk
logging: *logging-defaults
labels:
- prometheus-scrape.enabled=true
- prometheus-scrape.port=6070
- prometheus-scrape.path=/debug/metrics/prometheus
- traefik.enable=true
- traefik.http.middlewares.arbitrum-one-nitro-minimal-pebble-hash-stripprefix.stripprefix.prefixes=/arbitrum-one-minimal
- traefik.http.services.arbitrum-one-nitro-minimal-pebble-hash.loadbalancer.server.port=8545
- ${NO_SSL:-traefik.http.routers.arbitrum-one-nitro-minimal-pebble-hash.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.arbitrum-one-nitro-minimal-pebble-hash.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.arbitrum-one-nitro-minimal-pebble-hash.rule=Host(`$DOMAIN`) && (Path(`/arbitrum-one-minimal`) || Path(`/arbitrum-one-minimal/`))}
- ${NO_SSL:+traefik.http.routers.arbitrum-one-nitro-minimal-pebble-hash.rule=Path(`/arbitrum-one-minimal`) || Path(`/arbitrum-one-minimal/`)}
- traefik.http.routers.arbitrum-one-nitro-minimal-pebble-hash.middlewares=arbitrum-one-nitro-minimal-pebble-hash-stripprefix, ipallowlist
volumes:
arbitrum-one-nitro-minimal-pebble-hash:
x-upstreams:
- id: $${ID}
labels:
provider: $${PROVIDER}
connection:
generic:
rpc:
url: $${RPC_URL}
ws:
frameSize: 20Mb
msgSize: 50Mb
url: $${WS_URL}
chain: arbitrum
method-groups:
enabled:
- debug
- filter
methods:
disabled:
enabled:
- name: txpool_content # TODO: should be disabled for rollup nodes
# standard geth only
- name: debug_getRawBlock
- name: debug_getRawTransaction
- name: debug_getRawReceipts
- name: debug_getRawHeader
- name: debug_getBadBlocks
# non standard geth only slightly dangerous
- name: debug_intermediateRoots
- name: debug_dumpBlock
# standard geth and erigon
- name: debug_accountRange
- name: debug_getModifiedAccountsByNumber
- name: debug_getModifiedAccountsByHash
# non standard geth and erigon
- name: eth_getRawTransactionByHash
- name: eth_getRawTransactionByBlockHashAndIndex
...

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
arbitrum-one: arbitrum-one:
image: ${ARBITRUM_NITRO_IMAGE:-offchainlabs/nitro-node}:${ARBITRUM_ONE_NITRO_VERSION:-v3.9.5-66e42c4} image: ${ARBITRUM_NITRO_IMAGE:-offchainlabs/nitro-node}:${ARBITRUM_ONE_NITRO_VERSION:-v3.10.1-d7f07be}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

View File

@@ -0,0 +1,141 @@
---
x-logging-defaults: &logging-defaults
driver: json-file
options:
max-size: "10m"
max-file: "3"
# Usage:
#
# mkdir rpc && cd rpc
#
# git init
# git remote add origin https://github.com/StakeSquid/ethereum-rpc-docker.git
# git fetch origin vibe
# git checkout origin/vibe
#
# docker run --rm alpine sh -c "printf '0x'; head -c32 /dev/urandom | xxd -p -c 64" > .jwtsecret
#
# env
# ...
# IP=$(curl ipinfo.io/ip)
# DOMAIN=${IP}.traefik.me
# COMPOSE_FILE=base.yml:rpc.yml:arb/nitro/arbitrum-sepolia-nitro-minimal-pebble-hash.yml
#
# docker compose up -d
#
# curl -X POST https://${IP}.traefik.me/arbitrum-sepolia-minimal \
# -H "Content-Type: application/json" \
# --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
services:
arbitrum-sepolia-minimal:
image: ${ARBITRUM_NITRO_IMAGE:-offchainlabs/nitro-node}:${ARBITRUM_SEPOLIA_NITRO_VERSION:-v3.10.1-d7f07be}
sysctls:
# TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
net.ipv4.tcp_no_metrics_save: 1 # Disable metrics cache
net.ipv4.tcp_rmem: 4096 87380 16777216 # Increase TCP read buffers
net.ipv4.tcp_wmem: 4096 87380 16777216 # Increase TCP write buffers
net.core.somaxconn: 32768 # Higher connection queue
# Memory/Connection Management
# net.core.netdev_max_backlog: 50000 # Increase network buffer
net.ipv4.tcp_max_syn_backlog: 30000 # More SYN requests
net.ipv4.tcp_max_tw_buckets: 2000000 # Allow more TIME_WAIT sockets
ulimits:
nofile: 1048576 # Max open files (for RPC/WS connections)
user: root
expose:
- 8545
command:
- --chain.id=421614
- --execution.caching.archive=${ARBITRUM_SEPOLIA_MINIMAL_ARCHIVE_DB:-false}
- --execution.caching.database-cache=${ARBITRUM_SEPOLIA_NITRO_MINIMAL_PEBBLE_HASH_DATABASE_CACHE:-2048}
- --execution.caching.snapshot-cache=${ARBITRUM_SEPOLIA_NITRO_MINIMAL_PEBBLE_HASH_SNAPSHOT_CACHE:-400}
- --execution.caching.trie-clean-cache=${ARBITRUM_SEPOLIA_NITRO_MINIMAL_PEBBLE_HASH_TRIE_CLEAN_CACHE:-600}
- --execution.caching.trie-dirty-cache=${ARBITRUM_SEPOLIA_NITRO_MINIMAL_PEBBLE_HASH_TRIE_DIRTY_CACHE:-1024}
- --execution.rpc.gas-cap=5500000000
- --execution.rpc.log-history=0
- --execution.sequencer.enable=false
- --http.addr=0.0.0.0
- --http.api=eth,net,web3,arb,txpool,debug
- --http.corsdomain=*
- --http.port=8545
- --http.vhosts=*
- --init.prune=minimal
- --metrics
- --metrics-server.addr=0.0.0.0
- --metrics-server.port=6070
- --node.batch-poster.enable=false
- --node.sequencer=false
- --node.staker.enable=false
- --parent-chain.blob-client.beacon-url=${ETHEREUM_SEPOLIA_BEACON_REST}
- --parent-chain.connection.url=${ETHEREUM_SEPOLIA_EXECUTION_RPC}
- --persistent.chain=/root/.arbitrum/arbitrum-sepolia-minimal
- --persistent.db-engine=pebble
- --ws.addr=0.0.0.0
- --ws.origins=*
- --ws.port=8545
restart: unless-stopped
stop_grace_period: 5m
networks:
- chains
volumes:
- ${ARBITRUM_SEPOLIA_NITRO_MINIMAL_PEBBLE_HASH_DATA:-arbitrum-sepolia-nitro-minimal-pebble-hash}:/root/.arbitrum
- ./tmp/arbitrum-sepolia-minimal:/tmp
- /slowdisk:/slowdisk
logging: *logging-defaults
labels:
- prometheus-scrape.enabled=true
- prometheus-scrape.port=6070
- prometheus-scrape.path=/debug/metrics/prometheus
- traefik.enable=true
- traefik.http.middlewares.arbitrum-sepolia-nitro-minimal-pebble-hash-stripprefix.stripprefix.prefixes=/arbitrum-sepolia-minimal
- traefik.http.services.arbitrum-sepolia-nitro-minimal-pebble-hash.loadbalancer.server.port=8545
- ${NO_SSL:-traefik.http.routers.arbitrum-sepolia-nitro-minimal-pebble-hash.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.arbitrum-sepolia-nitro-minimal-pebble-hash.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.arbitrum-sepolia-nitro-minimal-pebble-hash.rule=Host(`$DOMAIN`) && (Path(`/arbitrum-sepolia-minimal`) || Path(`/arbitrum-sepolia-minimal/`))}
- ${NO_SSL:+traefik.http.routers.arbitrum-sepolia-nitro-minimal-pebble-hash.rule=Path(`/arbitrum-sepolia-minimal`) || Path(`/arbitrum-sepolia-minimal/`)}
- traefik.http.routers.arbitrum-sepolia-nitro-minimal-pebble-hash.middlewares=arbitrum-sepolia-nitro-minimal-pebble-hash-stripprefix, ipallowlist
volumes:
arbitrum-sepolia-nitro-minimal-pebble-hash:
x-upstreams:
- id: $${ID}
labels:
provider: $${PROVIDER}
connection:
generic:
rpc:
url: $${RPC_URL}
ws:
frameSize: 20Mb
msgSize: 50Mb
url: $${WS_URL}
chain: arbitrum-sepolia
method-groups:
enabled:
- debug
- filter
methods:
disabled:
enabled:
- name: txpool_content # TODO: should be disabled for rollup nodes
# standard geth only
- name: debug_getRawBlock
- name: debug_getRawTransaction
- name: debug_getRawReceipts
- name: debug_getRawHeader
- name: debug_getBadBlocks
# non standard geth only slightly dangerous
- name: debug_intermediateRoots
- name: debug_dumpBlock
# standard geth and erigon
- name: debug_accountRange
- name: debug_getModifiedAccountsByNumber
- name: debug_getModifiedAccountsByHash
# non standard geth and erigon
- name: eth_getRawTransactionByHash
- name: eth_getRawTransactionByBlockHashAndIndex
...

View File

@@ -0,0 +1,140 @@
---
x-logging-defaults: &logging-defaults
driver: json-file
options:
max-size: "10m"
max-file: "3"
# Usage:
#
# mkdir rpc && cd rpc
#
# git init
# git remote add origin https://github.com/StakeSquid/ethereum-rpc-docker.git
# git fetch origin vibe
# git checkout origin/vibe
#
# docker run --rm alpine sh -c "printf '0x'; head -c32 /dev/urandom | xxd -p -c 64" > .jwtsecret
#
# env
# ...
# IP=$(curl ipinfo.io/ip)
# DOMAIN=${IP}.traefik.me
# COMPOSE_FILE=base.yml:rpc.yml:arb/nitro/arbitrum-sepolia-nitro-minimal-pebble-hash.yml
#
# docker compose up -d
#
# curl -X POST https://${IP}.traefik.me/arbitrum-sepolia-minimal \
# -H "Content-Type: application/json" \
# --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
services:
arbitrum-sepolia-minimal:
image: ${ARBITRUM_NITRO_IMAGE:-offchainlabs/nitro-node}:${ARBITRUM_SEPOLIA_NITRO_VERSION:-v3.10.1-d7f07be}
sysctls:
# TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
net.ipv4.tcp_no_metrics_save: 1 # Disable metrics cache
net.ipv4.tcp_rmem: 4096 87380 16777216 # Increase TCP read buffers
net.ipv4.tcp_wmem: 4096 87380 16777216 # Increase TCP write buffers
net.core.somaxconn: 32768 # Higher connection queue
# Memory/Connection Management
# net.core.netdev_max_backlog: 50000 # Increase network buffer
net.ipv4.tcp_max_syn_backlog: 30000 # More SYN requests
net.ipv4.tcp_max_tw_buckets: 2000000 # Allow more TIME_WAIT sockets
ulimits:
nofile: 1048576 # Max open files (for RPC/WS connections)
user: root
expose:
- 8545
command:
- --chain.id=421614
- --execution.caching.archive=${ARBITRUM_SEPOLIA_MINIMAL_ARCHIVE_DB:-false}
- --execution.caching.database-cache=${ARBITRUM_SEPOLIA_NITRO_MINIMAL_PEBBLE_HASH_DATABASE_CACHE:-2048}
- --execution.caching.snapshot-cache=${ARBITRUM_SEPOLIA_NITRO_MINIMAL_PEBBLE_HASH_SNAPSHOT_CACHE:-400}
- --execution.caching.trie-clean-cache=${ARBITRUM_SEPOLIA_NITRO_MINIMAL_PEBBLE_HASH_TRIE_CLEAN_CACHE:-600}
- --execution.caching.trie-dirty-cache=${ARBITRUM_SEPOLIA_NITRO_MINIMAL_PEBBLE_HASH_TRIE_DIRTY_CACHE:-1024}
- --execution.rpc.gas-cap=5500000000
- --execution.rpc.log-history=0
- --execution.sequencer.enable=false
- --http.addr=0.0.0.0
- --http.api=eth,net,web3,arb,txpool,debug
- --http.corsdomain=*
- --http.port=8545
- --http.vhosts=*
- --metrics
- --metrics-server.addr=0.0.0.0
- --metrics-server.port=6070
- --node.batch-poster.enable=false
- --node.sequencer=false
- --node.staker.enable=false
- --parent-chain.blob-client.beacon-url=${ETHEREUM_SEPOLIA_BEACON_REST}
- --parent-chain.connection.url=${ETHEREUM_SEPOLIA_EXECUTION_RPC}
- --persistent.chain=/root/.arbitrum/arbitrum-sepolia-minimal
- --persistent.db-engine=pebble
- --ws.addr=0.0.0.0
- --ws.origins=*
- --ws.port=8545
restart: unless-stopped
stop_grace_period: 5m
networks:
- chains
volumes:
- ${ARBITRUM_SEPOLIA_NITRO_MINIMAL_PEBBLE_HASH_DATA:-arbitrum-sepolia-nitro-minimal-pebble-hash}:/root/.arbitrum
- ./tmp/arbitrum-sepolia-minimal:/tmp
- /slowdisk:/slowdisk
logging: *logging-defaults
labels:
- prometheus-scrape.enabled=true
- prometheus-scrape.port=6070
- prometheus-scrape.path=/debug/metrics/prometheus
- traefik.enable=true
- traefik.http.middlewares.arbitrum-sepolia-nitro-minimal-pebble-hash-stripprefix.stripprefix.prefixes=/arbitrum-sepolia-minimal
- traefik.http.services.arbitrum-sepolia-nitro-minimal-pebble-hash.loadbalancer.server.port=8545
- ${NO_SSL:-traefik.http.routers.arbitrum-sepolia-nitro-minimal-pebble-hash.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.arbitrum-sepolia-nitro-minimal-pebble-hash.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.arbitrum-sepolia-nitro-minimal-pebble-hash.rule=Host(`$DOMAIN`) && (Path(`/arbitrum-sepolia-minimal`) || Path(`/arbitrum-sepolia-minimal/`))}
- ${NO_SSL:+traefik.http.routers.arbitrum-sepolia-nitro-minimal-pebble-hash.rule=Path(`/arbitrum-sepolia-minimal`) || Path(`/arbitrum-sepolia-minimal/`)}
- traefik.http.routers.arbitrum-sepolia-nitro-minimal-pebble-hash.middlewares=arbitrum-sepolia-nitro-minimal-pebble-hash-stripprefix, ipallowlist
volumes:
arbitrum-sepolia-nitro-minimal-pebble-hash:
x-upstreams:
- id: $${ID}
labels:
provider: $${PROVIDER}
connection:
generic:
rpc:
url: $${RPC_URL}
ws:
frameSize: 20Mb
msgSize: 50Mb
url: $${WS_URL}
chain: arbitrum-sepolia
method-groups:
enabled:
- debug
- filter
methods:
disabled:
enabled:
- name: txpool_content # TODO: should be disabled for rollup nodes
# standard geth only
- name: debug_getRawBlock
- name: debug_getRawTransaction
- name: debug_getRawReceipts
- name: debug_getRawHeader
- name: debug_getBadBlocks
# non standard geth only slightly dangerous
- name: debug_intermediateRoots
- name: debug_dumpBlock
# standard geth and erigon
- name: debug_accountRange
- name: debug_getModifiedAccountsByNumber
- name: debug_getModifiedAccountsByHash
# non standard geth and erigon
- name: eth_getRawTransactionByHash
- name: eth_getRawTransactionByBlockHashAndIndex
...

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
arbitrum-sepolia: arbitrum-sepolia:
image: ${ARBITRUM_NITRO_IMAGE:-offchainlabs/nitro-node}:${ARBITRUM_SEPOLIA_NITRO_VERSION:-v3.9.5-66e42c4} image: ${ARBITRUM_NITRO_IMAGE:-offchainlabs/nitro-node}:${ARBITRUM_SEPOLIA_NITRO_VERSION:-v3.10.1-d7f07be}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

View File

@@ -0,0 +1,198 @@
---
x-logging-defaults: &logging-defaults
driver: json-file
options:
max-size: "10m"
max-file: "3"
# Usage:
#
# mkdir rpc && cd rpc
#
# git init
# git remote add origin https://github.com/StakeSquid/ethereum-rpc-docker.git
# git fetch origin vibe
# git checkout origin/vibe
#
# docker run --rm alpine sh -c "printf '0x'; head -c32 /dev/urandom | xxd -p -c 64" > .jwtsecret
#
# env
# ...
# IP=$(curl ipinfo.io/ip)
# DOMAIN=${IP}.traefik.me
# COMPOSE_FILE=base.yml:rpc.yml:arc/arc/arc-testnet-arc-full.yml
#
# docker compose up -d
#
# curl -X POST https://${IP}.traefik.me/arc-testnet \
# -H "Content-Type: application/json" \
# --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
services:
arc-testnet-snapshots:
image: ${ARC_ARC_IMAGE:-docker.cloudsmith.io/circle/arc-network/arc-execution}:${ARC_TESTNET_ARC_VERSION:-0.7.2}
user: 0:0
entrypoint: [/usr/local/bin/arc-snapshots, download]
command:
- --chain=arc-testnet
- --consensus-path=/data/consensus
- --execution-path=/data/execution
restart: no
networks:
- chains
volumes:
- ${ARC_TESTNET_ARC_FULL_CONSENSUS_DATA:-arc-testnet-arc-full-consensus}:/data/consensus
- ${ARC_TESTNET_ARC_FULL_EXECUTION_DATA:-arc-testnet-arc-full-execution}:/data/execution
logging: *logging-defaults
arc-testnet-consensus-init:
image: ${ARC_CONSENSUS_IMAGE:-docker.cloudsmith.io/circle/arc-network/arc-consensus}:${ARC_TESTNET_CONSENSUS_VERSION:-0.7.2}
user: 0:0
entrypoint: [/usr/local/bin/arc-node-consensus, init]
command:
- --home=/data/consensus
restart: no
depends_on:
arc-testnet-snapshots:
condition: service_completed_successfully
networks:
- chains
volumes:
- ${ARC_TESTNET_ARC_FULL_CONSENSUS_DATA:-arc-testnet-arc-full-consensus}:/data/consensus
logging: *logging-defaults
arc-testnet-sockets-init:
image: debian:bookworm-slim
entrypoint: [/bin/sh, -c]
command: [rm -f /sockets/*.ipc && chown 999:999 /sockets]
restart: no
depends_on:
arc-testnet-consensus-init:
condition: service_completed_successfully
networks:
- chains
volumes:
- arc-testnet-arc-full-sockets:/sockets
logging: *logging-defaults
arc-testnet:
image: ${ARC_ARC_IMAGE:-docker.cloudsmith.io/circle/arc-network/arc-execution}:${ARC_TESTNET_ARC_VERSION:-0.7.2}
sysctls:
# TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
net.ipv4.tcp_no_metrics_save: 1 # Disable metrics cache
net.ipv4.tcp_rmem: 4096 87380 16777216 # Increase TCP read buffers
net.ipv4.tcp_wmem: 4096 87380 16777216 # Increase TCP write buffers
net.core.somaxconn: 32768 # Higher connection queue
# Memory/Connection Management
# net.core.netdev_max_backlog: 50000 # Increase network buffer
net.ipv4.tcp_max_syn_backlog: 30000 # More SYN requests
net.ipv4.tcp_max_tw_buckets: 2000000 # Allow more TIME_WAIT sockets
ulimits:
nofile: 1048576 # Max open files (for RPC/WS connections)
user: 0:0
expose:
- 8545
- 9001
entrypoint: [/usr/local/bin/arc-node-execution, node]
command:
- --auth-ipc
- --auth-ipc.path=/sockets/auth.ipc
- --chain=arc-testnet
- --datadir=/data/execution
- --disable-discovery
- --enable-arc-rpc
- --full
- --http
- --http.addr=0.0.0.0
- --http.api=eth,net,web3,txpool,trace,debug
- --http.port=8545
- --ipcpath=/sockets/reth.ipc
- --log.file.directory=/data/execution/logs
- --metrics=0.0.0.0:9001
- --rpc.forwarder=https://rpc.quicknode.testnet.arc.network/
restart: unless-stopped
stop_grace_period: 5m
depends_on:
arc-testnet-sockets-init:
condition: service_completed_successfully
networks:
- chains
volumes:
- ${ARC_TESTNET_ARC_FULL_EXECUTION_DATA:-arc-testnet-arc-full-execution}:/data/execution
- /slowdisk:/slowdisk
- arc-testnet-arc-full-sockets:/sockets
logging: *logging-defaults
labels:
- prometheus-scrape.enabled=true
- prometheus-scrape.port=9001
- prometheus-scrape.path=/metrics
- traefik.enable=true
- traefik.http.middlewares.arc-testnet-arc-full-stripprefix.stripprefix.prefixes=/arc-testnet
- traefik.http.services.arc-testnet-arc-full.loadbalancer.server.port=8545
- ${NO_SSL:-traefik.http.routers.arc-testnet-arc-full.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.arc-testnet-arc-full.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.arc-testnet-arc-full.rule=Host(`$DOMAIN`) && (Path(`/arc-testnet`) || Path(`/arc-testnet/`))}
- ${NO_SSL:+traefik.http.routers.arc-testnet-arc-full.rule=Path(`/arc-testnet`) || Path(`/arc-testnet/`)}
- traefik.http.routers.arc-testnet-arc-full.middlewares=arc-testnet-arc-full-stripprefix, ipallowlist
arc-testnet-node:
image: ${ARC_CONSENSUS_IMAGE:-docker.cloudsmith.io/circle/arc-network/arc-consensus}:${ARC_TESTNET_CONSENSUS_VERSION:-0.7.2}
user: 0:0
expose:
- 31000
- 29000
entrypoint: [/usr/local/bin/arc-node-consensus, start]
command:
- --eth-socket=/sockets/reth.ipc
- --execution-persistence-backpressure
- --execution-persistence-backpressure-threshold=50
- --execution-socket=/sockets/auth.ipc
- --follow
- --follow.endpoint=https://rpc.blockdaemon.testnet.arc.network,wss=rpc.blockdaemon.testnet.arc.network/websocket
- --follow.endpoint=https://rpc.drpc.testnet.arc.network,wss=rpc.drpc.testnet.arc.network
- --follow.endpoint=https://rpc.quicknode.testnet.arc.network,wss=rpc.quicknode.testnet.arc.network
- --full
- --home=/data/consensus
- --metrics=0.0.0.0:29000
- --rpc.addr=0.0.0.0:31000
restart: unless-stopped
stop_grace_period: 5m
depends_on:
arc-testnet-consensus-init:
condition: service_completed_successfully
arc-testnet:
condition: service_started
networks:
- chains
volumes:
- ${ARC_TESTNET_ARC_FULL_CONSENSUS_DATA:-arc-testnet-arc-full-consensus}:/data/consensus
- arc-testnet-arc-full-sockets:/sockets
logging: *logging-defaults
labels:
- prometheus-scrape.enabled=true
- prometheus-scrape.port=29000
volumes:
arc-testnet-arc-full-consensus:
arc-testnet-arc-full-execution:
arc-testnet-arc-full-sockets:
x-upstreams:
- id: $${ID}
labels:
provider: $${PROVIDER}
connection:
generic:
rpc:
url: $${RPC_URL}
chain: arc-testnet
method-groups:
enabled:
- debug
- filter
- trace
methods:
enabled:
- name: txpool_content
...

View File

@@ -0,0 +1,6 @@
{
"rpc-gas-cap": 2500000000,
"eth-rpc-gas-limit": 2500000000,
"offline-pruning-enabled": true,
"offline-pruning-data-directory": "/root/.avalanchego/offline-pruning"
}

View File

@@ -87,8 +87,8 @@ services:
- traefik.http.routers.avalanche-fuji-go-archive-leveldb.service=avalanche-fuji-go-archive-leveldb - traefik.http.routers.avalanche-fuji-go-archive-leveldb.service=avalanche-fuji-go-archive-leveldb
- ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-archive-leveldb-ws.entrypoints=websecure} - ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-archive-leveldb-ws.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-archive-leveldb-ws.tls.certresolver=myresolver} - ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-archive-leveldb-ws.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-archive-leveldb-ws.rule=Host(`$DOMAIN`) && (Path(`/avalanche-fuji-archive`) || Path(`/avalanche-fuji-archive/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-archive-leveldb-ws.rule=Host(`$DOMAIN`) && (Path(`/avalanche-fuji-archive`) || Path(`/avalanche-fuji-archive/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- ${NO_SSL:+traefik.http.routers.avalanche-fuji-go-archive-leveldb-ws.rule=(Path(`/avalanche-fuji-archive`) || Path(`/avalanche-fuji-archive/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:+traefik.http.routers.avalanche-fuji-go-archive-leveldb-ws.rule=(Path(`/avalanche-fuji-archive`) || Path(`/avalanche-fuji-archive/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- traefik.http.routers.avalanche-fuji-go-archive-leveldb-ws.middlewares=avalanche-fuji-go-archive-leveldb-stripprefix, avalanche-fuji-go-archive-leveldb-set-ws-path, ipallowlist - traefik.http.routers.avalanche-fuji-go-archive-leveldb-ws.middlewares=avalanche-fuji-go-archive-leveldb-stripprefix, avalanche-fuji-go-archive-leveldb-set-ws-path, ipallowlist
volumes: volumes:

View File

@@ -0,0 +1,118 @@
---
x-logging-defaults: &logging-defaults
driver: json-file
options:
max-size: "10m"
max-file: "3"
# Usage:
#
# mkdir rpc && cd rpc
#
# git init
# git remote add origin https://github.com/StakeSquid/ethereum-rpc-docker.git
# git fetch origin vibe
# git checkout origin/vibe
#
# docker run --rm alpine sh -c "printf '0x'; head -c32 /dev/urandom | xxd -p -c 64" > .jwtsecret
#
# env
# ...
# IP=$(curl ipinfo.io/ip)
# DOMAIN=${IP}.traefik.me
# COMPOSE_FILE=base.yml:rpc.yml:avalanche/go/avalanche-fuji-go-pruned-leveldb.yml
#
# docker compose up -d
#
# curl -X POST https://${IP}.traefik.me/avalanche-fuji \
# -H "Content-Type: application/json" \
# --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
services:
avalanche-fuji:
image: ${AVALANCHE_GO_IMAGE:-avaplatform/avalanchego}:${AVALANCHE_FUJI_GO_VERSION:-v1.14.2}
sysctls:
# TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
net.ipv4.tcp_no_metrics_save: 1 # Disable metrics cache
net.ipv4.tcp_rmem: 4096 87380 16777216 # Increase TCP read buffers
net.ipv4.tcp_wmem: 4096 87380 16777216 # Increase TCP write buffers
net.core.somaxconn: 32768 # Higher connection queue
# Memory/Connection Management
# net.core.netdev_max_backlog: 50000 # Increase network buffer
net.ipv4.tcp_max_syn_backlog: 30000 # More SYN requests
net.ipv4.tcp_max_tw_buckets: 2000000 # Allow more TIME_WAIT sockets
ulimits:
nofile: 1048576 # Max open files (for RPC/WS connections)
user: root
ports:
- 12059:12059
- 12059:12059/udp
expose:
- 9650
entrypoint: [/bin/sh, -c, mkdir -p /root/.avalanchego/offline-pruning && exec /avalanchego/build/avalanchego "$@", --]
command:
- --chain-config-dir=/config/prune
- --db-type=leveldb
- --http-allowed-hosts=*
- --http-host=
- --network-id=fuji
- --public-ip=${IP}
- --staking-port=12059
restart: unless-stopped
stop_grace_period: 5m
networks:
- chains
volumes:
- ${AVALANCHE_FUJI_GO_PRUNED_LEVELDB_DATA:-avalanche-fuji-go-pruned-leveldb}:/root/.avalanchego
- ./avalanche/fuji:/config
- /slowdisk:/slowdisk
logging: *logging-defaults
labels:
- prometheus-scrape.enabled=false
- traefik.enable=true
- traefik.http.middlewares.avalanche-fuji-go-pruned-leveldb-set-path.replacepath.path=/ext/bc/C/rpc
- traefik.http.middlewares.avalanche-fuji-go-pruned-leveldb-stripprefix.stripprefix.prefixes=/avalanche-fuji
- traefik.http.services.avalanche-fuji-go-pruned-leveldb.loadbalancer.server.port=9650
- ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-pruned-leveldb.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-pruned-leveldb.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-pruned-leveldb.rule=Host(`$DOMAIN`) && (Path(`/avalanche-fuji`) || Path(`/avalanche-fuji/`))}
- ${NO_SSL:+traefik.http.routers.avalanche-fuji-go-pruned-leveldb.rule=Path(`/avalanche-fuji`) || Path(`/avalanche-fuji/`)}
- traefik.http.routers.avalanche-fuji-go-pruned-leveldb.middlewares=avalanche-fuji-go-pruned-leveldb-stripprefix, avalanche-fuji-go-pruned-leveldb-set-path, ipallowlist
- traefik.http.routers.avalanche-fuji-go-pruned-leveldb.priority=50 # gets any request that is not GET with UPGRADE header
- traefik.http.routers.avalanche-fuji-go-pruned-leveldb-ws.priority=100 # answers GET requests first
- traefik.http.middlewares.avalanche-fuji-go-pruned-leveldb-set-ws-path.replacepath.path=/ext/bc/C/ws
- traefik.http.services.avalanche-fuji-go-pruned-leveldb-ws.loadbalancer.server.port=9650
- traefik.http.routers.avalanche-fuji-go-pruned-leveldb-ws.service=avalanche-fuji-go-pruned-leveldb-ws
- traefik.http.routers.avalanche-fuji-go-pruned-leveldb.service=avalanche-fuji-go-pruned-leveldb
- ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-pruned-leveldb-ws.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-pruned-leveldb-ws.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-pruned-leveldb-ws.rule=Host(`$DOMAIN`) && (Path(`/avalanche-fuji`) || Path(`/avalanche-fuji/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- ${NO_SSL:+traefik.http.routers.avalanche-fuji-go-pruned-leveldb-ws.rule=(Path(`/avalanche-fuji`) || Path(`/avalanche-fuji/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- traefik.http.routers.avalanche-fuji-go-pruned-leveldb-ws.middlewares=avalanche-fuji-go-pruned-leveldb-stripprefix, avalanche-fuji-go-pruned-leveldb-set-ws-path, ipallowlist
volumes:
avalanche-fuji-go-pruned-leveldb:
x-upstreams:
- id: $${ID}
labels:
provider: $${PROVIDER}
connection:
generic:
rpc:
url: $${RPC_URL}
ws:
frameSize: 20Mb
msgSize: 50Mb
url: $${WS_URL}
chain: avalanche
method-groups:
enabled:
- debug
- filter
methods:
disabled:
enabled:
- name: txpool_content # TODO: should be disabled for rollup nodes
...

View File

@@ -87,8 +87,8 @@ services:
- traefik.http.routers.avalanche-fuji-go-pruned-leveldb.service=avalanche-fuji-go-pruned-leveldb - traefik.http.routers.avalanche-fuji-go-pruned-leveldb.service=avalanche-fuji-go-pruned-leveldb
- ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-pruned-leveldb-ws.entrypoints=websecure} - ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-pruned-leveldb-ws.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-pruned-leveldb-ws.tls.certresolver=myresolver} - ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-pruned-leveldb-ws.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-pruned-leveldb-ws.rule=Host(`$DOMAIN`) && (Path(`/avalanche-fuji`) || Path(`/avalanche-fuji/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-pruned-leveldb-ws.rule=Host(`$DOMAIN`) && (Path(`/avalanche-fuji`) || Path(`/avalanche-fuji/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- ${NO_SSL:+traefik.http.routers.avalanche-fuji-go-pruned-leveldb-ws.rule=(Path(`/avalanche-fuji`) || Path(`/avalanche-fuji/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:+traefik.http.routers.avalanche-fuji-go-pruned-leveldb-ws.rule=(Path(`/avalanche-fuji`) || Path(`/avalanche-fuji/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- traefik.http.routers.avalanche-fuji-go-pruned-leveldb-ws.middlewares=avalanche-fuji-go-pruned-leveldb-stripprefix, avalanche-fuji-go-pruned-leveldb-set-ws-path, ipallowlist - traefik.http.routers.avalanche-fuji-go-pruned-leveldb-ws.middlewares=avalanche-fuji-go-pruned-leveldb-stripprefix, avalanche-fuji-go-pruned-leveldb-set-ws-path, ipallowlist
volumes: volumes:

View File

@@ -0,0 +1,118 @@
---
x-logging-defaults: &logging-defaults
driver: json-file
options:
max-size: "10m"
max-file: "3"
# Usage:
#
# mkdir rpc && cd rpc
#
# git init
# git remote add origin https://github.com/StakeSquid/ethereum-rpc-docker.git
# git fetch origin vibe
# git checkout origin/vibe
#
# docker run --rm alpine sh -c "printf '0x'; head -c32 /dev/urandom | xxd -p -c 64" > .jwtsecret
#
# env
# ...
# IP=$(curl ipinfo.io/ip)
# DOMAIN=${IP}.traefik.me
# COMPOSE_FILE=base.yml:rpc.yml:avalanche/go/avalanche-fuji-go-pruned-pebbledb.yml
#
# docker compose up -d
#
# curl -X POST https://${IP}.traefik.me/avalanche-fuji \
# -H "Content-Type: application/json" \
# --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
services:
avalanche-fuji:
image: ${AVALANCHE_GO_IMAGE:-avaplatform/avalanchego}:${AVALANCHE_FUJI_GO_VERSION:-v1.14.2}
sysctls:
# TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
net.ipv4.tcp_no_metrics_save: 1 # Disable metrics cache
net.ipv4.tcp_rmem: 4096 87380 16777216 # Increase TCP read buffers
net.ipv4.tcp_wmem: 4096 87380 16777216 # Increase TCP write buffers
net.core.somaxconn: 32768 # Higher connection queue
# Memory/Connection Management
# net.core.netdev_max_backlog: 50000 # Increase network buffer
net.ipv4.tcp_max_syn_backlog: 30000 # More SYN requests
net.ipv4.tcp_max_tw_buckets: 2000000 # Allow more TIME_WAIT sockets
ulimits:
nofile: 1048576 # Max open files (for RPC/WS connections)
user: root
ports:
- 10350:10350
- 10350:10350/udp
expose:
- 9650
entrypoint: [/bin/sh, -c, mkdir -p /root/.avalanchego/offline-pruning && exec /avalanchego/build/avalanchego "$@", --]
command:
- --chain-config-dir=/config/prune
- --db-type=pebbledb
- --http-allowed-hosts=*
- --http-host=
- --network-id=fuji
- --public-ip=${IP}
- --staking-port=10350
restart: unless-stopped
stop_grace_period: 5m
networks:
- chains
volumes:
- ${AVALANCHE_FUJI_GO_PRUNED_PEBBLEDB_DATA:-avalanche-fuji-go-pruned-pebbledb}:/root/.avalanchego
- ./avalanche/fuji:/config
- /slowdisk:/slowdisk
logging: *logging-defaults
labels:
- prometheus-scrape.enabled=false
- traefik.enable=true
- traefik.http.middlewares.avalanche-fuji-go-pruned-pebbledb-set-path.replacepath.path=/ext/bc/C/rpc
- traefik.http.middlewares.avalanche-fuji-go-pruned-pebbledb-stripprefix.stripprefix.prefixes=/avalanche-fuji
- traefik.http.services.avalanche-fuji-go-pruned-pebbledb.loadbalancer.server.port=9650
- ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-pruned-pebbledb.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-pruned-pebbledb.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-pruned-pebbledb.rule=Host(`$DOMAIN`) && (Path(`/avalanche-fuji`) || Path(`/avalanche-fuji/`))}
- ${NO_SSL:+traefik.http.routers.avalanche-fuji-go-pruned-pebbledb.rule=Path(`/avalanche-fuji`) || Path(`/avalanche-fuji/`)}
- traefik.http.routers.avalanche-fuji-go-pruned-pebbledb.middlewares=avalanche-fuji-go-pruned-pebbledb-stripprefix, avalanche-fuji-go-pruned-pebbledb-set-path, ipallowlist
- traefik.http.routers.avalanche-fuji-go-pruned-pebbledb.priority=50 # gets any request that is not GET with UPGRADE header
- traefik.http.routers.avalanche-fuji-go-pruned-pebbledb-ws.priority=100 # answers GET requests first
- traefik.http.middlewares.avalanche-fuji-go-pruned-pebbledb-set-ws-path.replacepath.path=/ext/bc/C/ws
- traefik.http.services.avalanche-fuji-go-pruned-pebbledb-ws.loadbalancer.server.port=9650
- traefik.http.routers.avalanche-fuji-go-pruned-pebbledb-ws.service=avalanche-fuji-go-pruned-pebbledb-ws
- traefik.http.routers.avalanche-fuji-go-pruned-pebbledb.service=avalanche-fuji-go-pruned-pebbledb
- ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-pruned-pebbledb-ws.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-pruned-pebbledb-ws.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-pruned-pebbledb-ws.rule=Host(`$DOMAIN`) && (Path(`/avalanche-fuji`) || Path(`/avalanche-fuji/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- ${NO_SSL:+traefik.http.routers.avalanche-fuji-go-pruned-pebbledb-ws.rule=(Path(`/avalanche-fuji`) || Path(`/avalanche-fuji/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- traefik.http.routers.avalanche-fuji-go-pruned-pebbledb-ws.middlewares=avalanche-fuji-go-pruned-pebbledb-stripprefix, avalanche-fuji-go-pruned-pebbledb-set-ws-path, ipallowlist
volumes:
avalanche-fuji-go-pruned-pebbledb:
x-upstreams:
- id: $${ID}
labels:
provider: $${PROVIDER}
connection:
generic:
rpc:
url: $${RPC_URL}
ws:
frameSize: 20Mb
msgSize: 50Mb
url: $${WS_URL}
chain: avalanche
method-groups:
enabled:
- debug
- filter
methods:
disabled:
enabled:
- name: txpool_content # TODO: should be disabled for rollup nodes
...

View File

@@ -87,8 +87,8 @@ services:
- traefik.http.routers.avalanche-fuji-go-pruned-pebbledb.service=avalanche-fuji-go-pruned-pebbledb - traefik.http.routers.avalanche-fuji-go-pruned-pebbledb.service=avalanche-fuji-go-pruned-pebbledb
- ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-pruned-pebbledb-ws.entrypoints=websecure} - ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-pruned-pebbledb-ws.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-pruned-pebbledb-ws.tls.certresolver=myresolver} - ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-pruned-pebbledb-ws.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-pruned-pebbledb-ws.rule=Host(`$DOMAIN`) && (Path(`/avalanche-fuji`) || Path(`/avalanche-fuji/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:-traefik.http.routers.avalanche-fuji-go-pruned-pebbledb-ws.rule=Host(`$DOMAIN`) && (Path(`/avalanche-fuji`) || Path(`/avalanche-fuji/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- ${NO_SSL:+traefik.http.routers.avalanche-fuji-go-pruned-pebbledb-ws.rule=(Path(`/avalanche-fuji`) || Path(`/avalanche-fuji/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:+traefik.http.routers.avalanche-fuji-go-pruned-pebbledb-ws.rule=(Path(`/avalanche-fuji`) || Path(`/avalanche-fuji/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- traefik.http.routers.avalanche-fuji-go-pruned-pebbledb-ws.middlewares=avalanche-fuji-go-pruned-pebbledb-stripprefix, avalanche-fuji-go-pruned-pebbledb-set-ws-path, ipallowlist - traefik.http.routers.avalanche-fuji-go-pruned-pebbledb-ws.middlewares=avalanche-fuji-go-pruned-pebbledb-stripprefix, avalanche-fuji-go-pruned-pebbledb-set-ws-path, ipallowlist
volumes: volumes:

View File

@@ -87,8 +87,8 @@ services:
- traefik.http.routers.avalanche-mainnet-go-archive-leveldb.service=avalanche-mainnet-go-archive-leveldb - traefik.http.routers.avalanche-mainnet-go-archive-leveldb.service=avalanche-mainnet-go-archive-leveldb
- ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-archive-leveldb-ws.entrypoints=websecure} - ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-archive-leveldb-ws.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-archive-leveldb-ws.tls.certresolver=myresolver} - ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-archive-leveldb-ws.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-archive-leveldb-ws.rule=Host(`$DOMAIN`) && (Path(`/avalanche-mainnet-archive`) || Path(`/avalanche-mainnet-archive/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-archive-leveldb-ws.rule=Host(`$DOMAIN`) && (Path(`/avalanche-mainnet-archive`) || Path(`/avalanche-mainnet-archive/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- ${NO_SSL:+traefik.http.routers.avalanche-mainnet-go-archive-leveldb-ws.rule=(Path(`/avalanche-mainnet-archive`) || Path(`/avalanche-mainnet-archive/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:+traefik.http.routers.avalanche-mainnet-go-archive-leveldb-ws.rule=(Path(`/avalanche-mainnet-archive`) || Path(`/avalanche-mainnet-archive/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- traefik.http.routers.avalanche-mainnet-go-archive-leveldb-ws.middlewares=avalanche-mainnet-go-archive-leveldb-stripprefix, avalanche-mainnet-go-archive-leveldb-set-ws-path, ipallowlist - traefik.http.routers.avalanche-mainnet-go-archive-leveldb-ws.middlewares=avalanche-mainnet-go-archive-leveldb-stripprefix, avalanche-mainnet-go-archive-leveldb-set-ws-path, ipallowlist
volumes: volumes:

View File

@@ -0,0 +1,118 @@
---
x-logging-defaults: &logging-defaults
driver: json-file
options:
max-size: "10m"
max-file: "3"
# Usage:
#
# mkdir rpc && cd rpc
#
# git init
# git remote add origin https://github.com/StakeSquid/ethereum-rpc-docker.git
# git fetch origin vibe
# git checkout origin/vibe
#
# docker run --rm alpine sh -c "printf '0x'; head -c32 /dev/urandom | xxd -p -c 64" > .jwtsecret
#
# env
# ...
# IP=$(curl ipinfo.io/ip)
# DOMAIN=${IP}.traefik.me
# COMPOSE_FILE=base.yml:rpc.yml:avalanche/go/avalanche-mainnet-go-pruned-leveldb.yml
#
# docker compose up -d
#
# curl -X POST https://${IP}.traefik.me/avalanche-mainnet \
# -H "Content-Type: application/json" \
# --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
services:
avalanche-mainnet:
image: ${AVALANCHE_GO_IMAGE:-avaplatform/avalanchego}:${AVALANCHE_MAINNET_GO_VERSION:-v1.14.2}
sysctls:
# TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
net.ipv4.tcp_no_metrics_save: 1 # Disable metrics cache
net.ipv4.tcp_rmem: 4096 87380 16777216 # Increase TCP read buffers
net.ipv4.tcp_wmem: 4096 87380 16777216 # Increase TCP write buffers
net.core.somaxconn: 32768 # Higher connection queue
# Memory/Connection Management
# net.core.netdev_max_backlog: 50000 # Increase network buffer
net.ipv4.tcp_max_syn_backlog: 30000 # More SYN requests
net.ipv4.tcp_max_tw_buckets: 2000000 # Allow more TIME_WAIT sockets
ulimits:
nofile: 1048576 # Max open files (for RPC/WS connections)
user: root
ports:
- 12757:12757
- 12757:12757/udp
expose:
- 9650
entrypoint: [/bin/sh, -c, mkdir -p /root/.avalanchego/offline-pruning && exec /avalanchego/build/avalanchego "$@", --]
command:
- --chain-config-dir=/config/prune
- --db-type=leveldb
- --http-allowed-hosts=*
- --http-host=
- --network-id=mainnet
- --public-ip=${IP}
- --staking-port=12757
restart: unless-stopped
stop_grace_period: 5m
networks:
- chains
volumes:
- ${AVALANCHE_MAINNET_GO_PRUNED_LEVELDB_DATA:-avalanche-mainnet-go-pruned-leveldb}:/root/.avalanchego
- ./avalanche/mainnet:/config
- /slowdisk:/slowdisk
logging: *logging-defaults
labels:
- prometheus-scrape.enabled=false
- traefik.enable=true
- traefik.http.middlewares.avalanche-mainnet-go-pruned-leveldb-set-path.replacepath.path=/ext/bc/C/rpc
- traefik.http.middlewares.avalanche-mainnet-go-pruned-leveldb-stripprefix.stripprefix.prefixes=/avalanche-mainnet
- traefik.http.services.avalanche-mainnet-go-pruned-leveldb.loadbalancer.server.port=9650
- ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-pruned-leveldb.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-pruned-leveldb.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-pruned-leveldb.rule=Host(`$DOMAIN`) && (Path(`/avalanche-mainnet`) || Path(`/avalanche-mainnet/`))}
- ${NO_SSL:+traefik.http.routers.avalanche-mainnet-go-pruned-leveldb.rule=Path(`/avalanche-mainnet`) || Path(`/avalanche-mainnet/`)}
- traefik.http.routers.avalanche-mainnet-go-pruned-leveldb.middlewares=avalanche-mainnet-go-pruned-leveldb-stripprefix, avalanche-mainnet-go-pruned-leveldb-set-path, ipallowlist
- traefik.http.routers.avalanche-mainnet-go-pruned-leveldb.priority=50 # gets any request that is not GET with UPGRADE header
- traefik.http.routers.avalanche-mainnet-go-pruned-leveldb-ws.priority=100 # answers GET requests first
- traefik.http.middlewares.avalanche-mainnet-go-pruned-leveldb-set-ws-path.replacepath.path=/ext/bc/C/ws
- traefik.http.services.avalanche-mainnet-go-pruned-leveldb-ws.loadbalancer.server.port=9650
- traefik.http.routers.avalanche-mainnet-go-pruned-leveldb-ws.service=avalanche-mainnet-go-pruned-leveldb-ws
- traefik.http.routers.avalanche-mainnet-go-pruned-leveldb.service=avalanche-mainnet-go-pruned-leveldb
- ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-pruned-leveldb-ws.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-pruned-leveldb-ws.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-pruned-leveldb-ws.rule=Host(`$DOMAIN`) && (Path(`/avalanche-mainnet`) || Path(`/avalanche-mainnet/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- ${NO_SSL:+traefik.http.routers.avalanche-mainnet-go-pruned-leveldb-ws.rule=(Path(`/avalanche-mainnet`) || Path(`/avalanche-mainnet/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- traefik.http.routers.avalanche-mainnet-go-pruned-leveldb-ws.middlewares=avalanche-mainnet-go-pruned-leveldb-stripprefix, avalanche-mainnet-go-pruned-leveldb-set-ws-path, ipallowlist
volumes:
avalanche-mainnet-go-pruned-leveldb:
x-upstreams:
- id: $${ID}
labels:
provider: $${PROVIDER}
connection:
generic:
rpc:
url: $${RPC_URL}
ws:
frameSize: 20Mb
msgSize: 50Mb
url: $${WS_URL}
chain: avalanche
method-groups:
enabled:
- debug
- filter
methods:
disabled:
enabled:
- name: txpool_content # TODO: should be disabled for rollup nodes
...

View File

@@ -87,8 +87,8 @@ services:
- traefik.http.routers.avalanche-mainnet-go-pruned-leveldb.service=avalanche-mainnet-go-pruned-leveldb - traefik.http.routers.avalanche-mainnet-go-pruned-leveldb.service=avalanche-mainnet-go-pruned-leveldb
- ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-pruned-leveldb-ws.entrypoints=websecure} - ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-pruned-leveldb-ws.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-pruned-leveldb-ws.tls.certresolver=myresolver} - ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-pruned-leveldb-ws.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-pruned-leveldb-ws.rule=Host(`$DOMAIN`) && (Path(`/avalanche-mainnet`) || Path(`/avalanche-mainnet/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-pruned-leveldb-ws.rule=Host(`$DOMAIN`) && (Path(`/avalanche-mainnet`) || Path(`/avalanche-mainnet/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- ${NO_SSL:+traefik.http.routers.avalanche-mainnet-go-pruned-leveldb-ws.rule=(Path(`/avalanche-mainnet`) || Path(`/avalanche-mainnet/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:+traefik.http.routers.avalanche-mainnet-go-pruned-leveldb-ws.rule=(Path(`/avalanche-mainnet`) || Path(`/avalanche-mainnet/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- traefik.http.routers.avalanche-mainnet-go-pruned-leveldb-ws.middlewares=avalanche-mainnet-go-pruned-leveldb-stripprefix, avalanche-mainnet-go-pruned-leveldb-set-ws-path, ipallowlist - traefik.http.routers.avalanche-mainnet-go-pruned-leveldb-ws.middlewares=avalanche-mainnet-go-pruned-leveldb-stripprefix, avalanche-mainnet-go-pruned-leveldb-set-ws-path, ipallowlist
volumes: volumes:

View File

@@ -0,0 +1,118 @@
---
x-logging-defaults: &logging-defaults
driver: json-file
options:
max-size: "10m"
max-file: "3"
# Usage:
#
# mkdir rpc && cd rpc
#
# git init
# git remote add origin https://github.com/StakeSquid/ethereum-rpc-docker.git
# git fetch origin vibe
# git checkout origin/vibe
#
# docker run --rm alpine sh -c "printf '0x'; head -c32 /dev/urandom | xxd -p -c 64" > .jwtsecret
#
# env
# ...
# IP=$(curl ipinfo.io/ip)
# DOMAIN=${IP}.traefik.me
# COMPOSE_FILE=base.yml:rpc.yml:avalanche/go/avalanche-mainnet-go-pruned-pebbledb.yml
#
# docker compose up -d
#
# curl -X POST https://${IP}.traefik.me/avalanche-mainnet \
# -H "Content-Type: application/json" \
# --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
services:
avalanche-mainnet:
image: ${AVALANCHE_GO_IMAGE:-avaplatform/avalanchego}:${AVALANCHE_MAINNET_GO_VERSION:-v1.14.2}
sysctls:
# TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
net.ipv4.tcp_no_metrics_save: 1 # Disable metrics cache
net.ipv4.tcp_rmem: 4096 87380 16777216 # Increase TCP read buffers
net.ipv4.tcp_wmem: 4096 87380 16777216 # Increase TCP write buffers
net.core.somaxconn: 32768 # Higher connection queue
# Memory/Connection Management
# net.core.netdev_max_backlog: 50000 # Increase network buffer
net.ipv4.tcp_max_syn_backlog: 30000 # More SYN requests
net.ipv4.tcp_max_tw_buckets: 2000000 # Allow more TIME_WAIT sockets
ulimits:
nofile: 1048576 # Max open files (for RPC/WS connections)
user: root
ports:
- 11929:11929
- 11929:11929/udp
expose:
- 9650
entrypoint: [/bin/sh, -c, mkdir -p /root/.avalanchego/offline-pruning && exec /avalanchego/build/avalanchego "$@", --]
command:
- --chain-config-dir=/config/prune
- --db-type=pebbledb
- --http-allowed-hosts=*
- --http-host=
- --network-id=mainnet
- --public-ip=${IP}
- --staking-port=11929
restart: unless-stopped
stop_grace_period: 5m
networks:
- chains
volumes:
- ${AVALANCHE_MAINNET_GO_PRUNED_PEBBLEDB_DATA:-avalanche-mainnet-go-pruned-pebbledb}:/root/.avalanchego
- ./avalanche/mainnet:/config
- /slowdisk:/slowdisk
logging: *logging-defaults
labels:
- prometheus-scrape.enabled=false
- traefik.enable=true
- traefik.http.middlewares.avalanche-mainnet-go-pruned-pebbledb-set-path.replacepath.path=/ext/bc/C/rpc
- traefik.http.middlewares.avalanche-mainnet-go-pruned-pebbledb-stripprefix.stripprefix.prefixes=/avalanche-mainnet
- traefik.http.services.avalanche-mainnet-go-pruned-pebbledb.loadbalancer.server.port=9650
- ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-pruned-pebbledb.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-pruned-pebbledb.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-pruned-pebbledb.rule=Host(`$DOMAIN`) && (Path(`/avalanche-mainnet`) || Path(`/avalanche-mainnet/`))}
- ${NO_SSL:+traefik.http.routers.avalanche-mainnet-go-pruned-pebbledb.rule=Path(`/avalanche-mainnet`) || Path(`/avalanche-mainnet/`)}
- traefik.http.routers.avalanche-mainnet-go-pruned-pebbledb.middlewares=avalanche-mainnet-go-pruned-pebbledb-stripprefix, avalanche-mainnet-go-pruned-pebbledb-set-path, ipallowlist
- traefik.http.routers.avalanche-mainnet-go-pruned-pebbledb.priority=50 # gets any request that is not GET with UPGRADE header
- traefik.http.routers.avalanche-mainnet-go-pruned-pebbledb-ws.priority=100 # answers GET requests first
- traefik.http.middlewares.avalanche-mainnet-go-pruned-pebbledb-set-ws-path.replacepath.path=/ext/bc/C/ws
- traefik.http.services.avalanche-mainnet-go-pruned-pebbledb-ws.loadbalancer.server.port=9650
- traefik.http.routers.avalanche-mainnet-go-pruned-pebbledb-ws.service=avalanche-mainnet-go-pruned-pebbledb-ws
- traefik.http.routers.avalanche-mainnet-go-pruned-pebbledb.service=avalanche-mainnet-go-pruned-pebbledb
- ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-pruned-pebbledb-ws.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-pruned-pebbledb-ws.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-pruned-pebbledb-ws.rule=Host(`$DOMAIN`) && (Path(`/avalanche-mainnet`) || Path(`/avalanche-mainnet/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- ${NO_SSL:+traefik.http.routers.avalanche-mainnet-go-pruned-pebbledb-ws.rule=(Path(`/avalanche-mainnet`) || Path(`/avalanche-mainnet/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- traefik.http.routers.avalanche-mainnet-go-pruned-pebbledb-ws.middlewares=avalanche-mainnet-go-pruned-pebbledb-stripprefix, avalanche-mainnet-go-pruned-pebbledb-set-ws-path, ipallowlist
volumes:
avalanche-mainnet-go-pruned-pebbledb:
x-upstreams:
- id: $${ID}
labels:
provider: $${PROVIDER}
connection:
generic:
rpc:
url: $${RPC_URL}
ws:
frameSize: 20Mb
msgSize: 50Mb
url: $${WS_URL}
chain: avalanche
method-groups:
enabled:
- debug
- filter
methods:
disabled:
enabled:
- name: txpool_content # TODO: should be disabled for rollup nodes
...

View File

@@ -87,8 +87,8 @@ services:
- traefik.http.routers.avalanche-mainnet-go-pruned-pebbledb.service=avalanche-mainnet-go-pruned-pebbledb - traefik.http.routers.avalanche-mainnet-go-pruned-pebbledb.service=avalanche-mainnet-go-pruned-pebbledb
- ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-pruned-pebbledb-ws.entrypoints=websecure} - ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-pruned-pebbledb-ws.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-pruned-pebbledb-ws.tls.certresolver=myresolver} - ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-pruned-pebbledb-ws.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-pruned-pebbledb-ws.rule=Host(`$DOMAIN`) && (Path(`/avalanche-mainnet`) || Path(`/avalanche-mainnet/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:-traefik.http.routers.avalanche-mainnet-go-pruned-pebbledb-ws.rule=Host(`$DOMAIN`) && (Path(`/avalanche-mainnet`) || Path(`/avalanche-mainnet/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- ${NO_SSL:+traefik.http.routers.avalanche-mainnet-go-pruned-pebbledb-ws.rule=(Path(`/avalanche-mainnet`) || Path(`/avalanche-mainnet/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:+traefik.http.routers.avalanche-mainnet-go-pruned-pebbledb-ws.rule=(Path(`/avalanche-mainnet`) || Path(`/avalanche-mainnet/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- traefik.http.routers.avalanche-mainnet-go-pruned-pebbledb-ws.middlewares=avalanche-mainnet-go-pruned-pebbledb-stripprefix, avalanche-mainnet-go-pruned-pebbledb-set-ws-path, ipallowlist - traefik.http.routers.avalanche-mainnet-go-pruned-pebbledb-ws.middlewares=avalanche-mainnet-go-pruned-pebbledb-stripprefix, avalanche-mainnet-go-pruned-pebbledb-set-ws-path, ipallowlist
volumes: volumes:

View File

@@ -0,0 +1,23 @@
{
"snowman-api-enabled": false,
"coreth-admin-api-enabled": false,
"net-api-enabled": true,
"rpc-gas-cap": 2500000000,
"rpc-tx-fee-cap": 100,
"eth-rpc-gas-limit": 2500000000,
"eth-api-enabled": true,
"personal-api-enabled": false,
"tx-pool-api-enabled": false,
"debug-api-enabled": false,
"web3-api-enabled": true,
"local-txs-enabled": false,
"pruning-enabled": true,
"api-max-duration": 0,
"api-max-blocks-per-request": 0,
"allow-unfinalized-queries": false,
"log-level": "info",
"state-sync-enabled": false,
"state-sync-skip-resume": true,
"offline-pruning-enabled": true,
"offline-pruning-data-directory": "/root/.avalanchego/offline-pruning"
}

View File

@@ -26,13 +26,13 @@ x-logging-defaults: &logging-defaults
# #
# docker compose up -d # docker compose up -d
# #
# curl -X POST https://${IP}.traefik.me/aztec-testnet \ # curl -X POST https://${IP}.traefik.me/aztec-testnet-pruned \
# -H "Content-Type: application/json" \ # -H "Content-Type: application/json" \
# --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' # --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
services: services:
aztec-testnet: aztec-testnet-pruned:
image: ${AZTEC_AZTEC_IMAGE:-aztecprotocol/aztec}:${AZTEC_TESTNET_AZTEC_VERSION:-3.0.2} image: ${AZTEC_AZTEC_IMAGE:-aztecprotocol/aztec}:${AZTEC_TESTNET_AZTEC_VERSION:-5.0.0-rc.1}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
@@ -51,10 +51,10 @@ services:
- 13009:13009 - 13009:13009
- 13009:13009/udp - 13009:13009/udp
expose: expose:
- 8080 - 8545
environment: environment:
AZTEC_ADMIN_PORT: '8880' AZTEC_ADMIN_PORT: '8880'
AZTEC_PORT: '8080' AZTEC_PORT: '8545'
DATA_DIRECTORY: /var/lib/data DATA_DIRECTORY: /var/lib/data
ETHEREUM_HOSTS: ${ETHEREUM_SEPOLIA_EXECUTION_RPC} ETHEREUM_HOSTS: ${ETHEREUM_SEPOLIA_EXECUTION_RPC}
L1_CONSENSUS_HOST_URLS: ${ETHEREUM_SEPOLIA_BEACON_REST} L1_CONSENSUS_HOST_URLS: ${ETHEREUM_SEPOLIA_BEACON_REST}
@@ -63,9 +63,8 @@ services:
P2P_PORT: '13009' P2P_PORT: '13009'
entrypoint: [node, --no-warnings, /usr/src/yarn-project/aztec/dest/bin/index.js, start] entrypoint: [node, --no-warnings, /usr/src/yarn-project/aztec/dest/bin/index.js, start]
command: command:
- --archiver
- --network=testnet
- --node - --node
- --network=testnet
restart: unless-stopped restart: unless-stopped
stop_grace_period: 5m stop_grace_period: 5m
networks: networks:
@@ -77,12 +76,12 @@ services:
labels: labels:
- prometheus-scrape.enabled=false - prometheus-scrape.enabled=false
- traefik.enable=true - traefik.enable=true
- traefik.http.middlewares.aztec-testnet-aztec-pruned-stripprefix.stripprefix.prefixes=/aztec-testnet - traefik.http.middlewares.aztec-testnet-aztec-pruned-stripprefix.stripprefix.prefixes=/aztec-testnet-pruned
- traefik.http.services.aztec-testnet-aztec-pruned.loadbalancer.server.port=8080 - traefik.http.services.aztec-testnet-aztec-pruned.loadbalancer.server.port=8545
- ${NO_SSL:-traefik.http.routers.aztec-testnet-aztec-pruned.entrypoints=websecure} - ${NO_SSL:-traefik.http.routers.aztec-testnet-aztec-pruned.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.aztec-testnet-aztec-pruned.tls.certresolver=myresolver} - ${NO_SSL:-traefik.http.routers.aztec-testnet-aztec-pruned.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.aztec-testnet-aztec-pruned.rule=Host(`$DOMAIN`) && (Path(`/aztec-testnet`) || Path(`/aztec-testnet/`))} - ${NO_SSL:-traefik.http.routers.aztec-testnet-aztec-pruned.rule=Host(`$DOMAIN`) && (Path(`/aztec-testnet-pruned`) || Path(`/aztec-testnet-pruned/`))}
- ${NO_SSL:+traefik.http.routers.aztec-testnet-aztec-pruned.rule=Path(`/aztec-testnet`) || Path(`/aztec-testnet/`)} - ${NO_SSL:+traefik.http.routers.aztec-testnet-aztec-pruned.rule=Path(`/aztec-testnet-pruned`) || Path(`/aztec-testnet-pruned/`)}
- traefik.http.routers.aztec-testnet-aztec-pruned.middlewares=aztec-testnet-aztec-pruned-stripprefix, ipallowlist - traefik.http.routers.aztec-testnet-aztec-pruned.middlewares=aztec-testnet-aztec-pruned-stripprefix, ipallowlist
volumes: volumes:

View File

@@ -36,15 +36,27 @@ generate_volume_metadata() {
# Check each static file path # Check each static file path
if [[ -f "$static_file_list" ]]; then if [[ -f "$static_file_list" ]]; then
while IFS= read -r path; do while IFS= read -r path; do
# Check if the path exists [[ -z "$path" ]] && continue
if [[ -e "$prefix/_data/$path" ]]; then # Match rule (see static-file-path-list.txt): an entry with NO slash is root-level
# Get the size # only (so `snapshots` won't catch postgres pg_logical/snapshots); an entry WITH a
size=$(du -sL "$prefix/_data/$path" 2>/dev/null | awk '{print $1}') # slash is a path-suffix, so any prefix matches (network-prefixed nitro freezers,
# Format size in human-readable format # nested l2geth geth/geth/...). Record the CONCRETE relative path so restore-volumes
size_formatted=$(echo "$(( size * 1024 ))" | numfmt --to=iec --suffix=B --format="%.2f") # can recreate the exact static-file -> /slowdisk symlink.
# Write to metadata file # Match real dirs AND symlinks: an already-OFFLOADED static dir is a symlink to
echo "$size_formatted $path" >> "$metadata_file" # /slowdisk, which find -type d alone would skip (then it would be dropped from the
# manifest and the next restore would not re-offload it).
local matches=() m rel
if [[ "$path" == */* ]]; then
while IFS= read -r m; do matches+=("$m"); done < <(find "$prefix/_data" \( -type d -o -type l \) -path "*/$path" 2>/dev/null)
else
m="$prefix/_data/$path"; { [ -d "$m" ] || [ -L "$m" ]; } && matches+=("$m")
fi fi
for m in "${matches[@]}"; do
rel="${m#"$prefix/_data/"}"
size=$(du -sL "$m" 2>/dev/null | awk '{print $1}')
size_formatted=$(echo "$(( ${size:-0} * 1024 ))" | numfmt --to=iec --suffix=B --format="%.2f")
echo "$size_formatted $rel" >> "$metadata_file"
done
done < "$static_file_list" done < "$static_file_list"
fi fi
} }

View File

@@ -112,7 +112,7 @@ services:
context: ./berachain context: ./berachain
dockerfile: beacon-kit.Dockerfile dockerfile: beacon-kit.Dockerfile
args: args:
BEACONKIT_VERSION: ${BERACHAIN_BEPOLIA_BEACON_KIT_VERSION:-v1.3.4} BEACONKIT_VERSION: ${BERACHAIN_BEPOLIA_BEACON_KIT_VERSION:-v1.4.0-rc3}
BEACONKIT_IMAGE: ${BERACHAIN_BEPOLIA_BEACON_KIT_IMAGE:-ghcr.io/berachain/beacon-kit} BEACONKIT_IMAGE: ${BERACHAIN_BEPOLIA_BEACON_KIT_IMAGE:-ghcr.io/berachain/beacon-kit}
ports: ports:
- 19888:19888 - 19888:19888

View File

@@ -112,7 +112,7 @@ services:
context: ./berachain context: ./berachain
dockerfile: beacon-kit.Dockerfile dockerfile: beacon-kit.Dockerfile
args: args:
BEACONKIT_VERSION: ${BERACHAIN_MAINNET_BEACON_KIT_VERSION:-v1.3.4} BEACONKIT_VERSION: ${BERACHAIN_MAINNET_BEACON_KIT_VERSION:-v1.4.0-rc3}
BEACONKIT_IMAGE: ${BERACHAIN_MAINNET_BEACON_KIT_IMAGE:-ghcr.io/berachain/beacon-kit} BEACONKIT_IMAGE: ${BERACHAIN_MAINNET_BEACON_KIT_IMAGE:-ghcr.io/berachain/beacon-kit}
ports: ports:
- 16562:16562 - 16562:16562

View File

@@ -151,7 +151,7 @@ services:
context: ./berachain context: ./berachain
dockerfile: beacon-kit.Dockerfile dockerfile: beacon-kit.Dockerfile
args: args:
BEACONKIT_VERSION: ${BERACHAIN_BARTIO_BEACON_KIT_VERSION:-v1.3.4} BEACONKIT_VERSION: ${BERACHAIN_BARTIO_BEACON_KIT_VERSION:-v1.4.0-rc3}
BEACONKIT_IMAGE: ${BERACHAIN_BARTIO_BEACON_KIT_IMAGE:-ghcr.io/berachain/beacon-kit} BEACONKIT_IMAGE: ${BERACHAIN_BARTIO_BEACON_KIT_IMAGE:-ghcr.io/berachain/beacon-kit}
ports: ports:
- 15527:15527 - 15527:15527

View File

@@ -152,7 +152,7 @@ services:
context: ./berachain context: ./berachain
dockerfile: beacon-kit.Dockerfile dockerfile: beacon-kit.Dockerfile
args: args:
BEACONKIT_VERSION: ${BERACHAIN_BARTIO_BEACON_KIT_VERSION:-v1.3.4} BEACONKIT_VERSION: ${BERACHAIN_BARTIO_BEACON_KIT_VERSION:-v1.4.0-rc3}
BEACONKIT_IMAGE: ${BERACHAIN_BARTIO_BEACON_KIT_IMAGE:-ghcr.io/berachain/beacon-kit} BEACONKIT_IMAGE: ${BERACHAIN_BARTIO_BEACON_KIT_IMAGE:-ghcr.io/berachain/beacon-kit}
ports: ports:
- 19467:19467 - 19467:19467

View File

@@ -152,7 +152,7 @@ services:
context: ./berachain context: ./berachain
dockerfile: beacon-kit.Dockerfile dockerfile: beacon-kit.Dockerfile
args: args:
BEACONKIT_VERSION: ${BERACHAIN_BEPOLIA_BEACON_KIT_VERSION:-v1.3.4} BEACONKIT_VERSION: ${BERACHAIN_BEPOLIA_BEACON_KIT_VERSION:-v1.4.0-rc3}
BEACONKIT_IMAGE: ${BERACHAIN_BEPOLIA_BEACON_KIT_IMAGE:-ghcr.io/berachain/beacon-kit} BEACONKIT_IMAGE: ${BERACHAIN_BEPOLIA_BEACON_KIT_IMAGE:-ghcr.io/berachain/beacon-kit}
ports: ports:
- 16347:16347 - 16347:16347

View File

@@ -153,7 +153,7 @@ services:
context: ./berachain context: ./berachain
dockerfile: beacon-kit.Dockerfile dockerfile: beacon-kit.Dockerfile
args: args:
BEACONKIT_VERSION: ${BERACHAIN_BEPOLIA_BEACON_KIT_VERSION:-v1.3.4} BEACONKIT_VERSION: ${BERACHAIN_BEPOLIA_BEACON_KIT_VERSION:-v1.4.0-rc3}
BEACONKIT_IMAGE: ${BERACHAIN_BEPOLIA_BEACON_KIT_IMAGE:-ghcr.io/berachain/beacon-kit} BEACONKIT_IMAGE: ${BERACHAIN_BEPOLIA_BEACON_KIT_IMAGE:-ghcr.io/berachain/beacon-kit}
ports: ports:
- 17274:17274 - 17274:17274

View File

@@ -152,7 +152,7 @@ services:
context: ./berachain context: ./berachain
dockerfile: beacon-kit.Dockerfile dockerfile: beacon-kit.Dockerfile
args: args:
BEACONKIT_VERSION: ${BERACHAIN_MAINNET_BEACON_KIT_VERSION:-v1.3.4} BEACONKIT_VERSION: ${BERACHAIN_MAINNET_BEACON_KIT_VERSION:-v1.4.0-rc3}
BEACONKIT_IMAGE: ${BERACHAIN_MAINNET_BEACON_KIT_IMAGE:-ghcr.io/berachain/beacon-kit} BEACONKIT_IMAGE: ${BERACHAIN_MAINNET_BEACON_KIT_IMAGE:-ghcr.io/berachain/beacon-kit}
ports: ports:
- 17881:17881 - 17881:17881

View File

@@ -153,7 +153,7 @@ services:
context: ./berachain context: ./berachain
dockerfile: beacon-kit.Dockerfile dockerfile: beacon-kit.Dockerfile
args: args:
BEACONKIT_VERSION: ${BERACHAIN_MAINNET_BEACON_KIT_VERSION:-v1.3.4} BEACONKIT_VERSION: ${BERACHAIN_MAINNET_BEACON_KIT_VERSION:-v1.4.0-rc3}
BEACONKIT_IMAGE: ${BERACHAIN_MAINNET_BEACON_KIT_IMAGE:-ghcr.io/berachain/beacon-kit} BEACONKIT_IMAGE: ${BERACHAIN_MAINNET_BEACON_KIT_IMAGE:-ghcr.io/berachain/beacon-kit}
ports: ports:
- 15900:15900 - 15900:15900

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
bitcoin-cash-mainnet: bitcoin-cash-mainnet:
image: ${BITCOIN_CASH_BITCOIND_IMAGE:-bitcoinabc/bitcoin-abc}:${BITCOIN_CASH_MAINNET_BITCOIND_VERSION:-0.33.4} image: ${BITCOIN_CASH_BITCOIND_IMAGE:-bitcoinabc/bitcoin-abc}:${BITCOIN_CASH_MAINNET_BITCOIND_VERSION:-0.33.6}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
bitcoin-cash-testnet: bitcoin-cash-testnet:
image: ${BITCOIN_CASH_BITCOIND_IMAGE:-bitcoinabc/bitcoin-abc}:${BITCOIN_CASH_TESTNET_BITCOIND_VERSION:-0.33.4} image: ${BITCOIN_CASH_BITCOIND_IMAGE:-bitcoinabc/bitcoin-abc}:${BITCOIN_CASH_TESTNET_BITCOIND_VERSION:-0.33.6}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

View File

@@ -74,7 +74,7 @@ services:
- --metrics.port=6060 - --metrics.port=6060
- --nat=extip:${IP} - --nat=extip:${IP}
- --port=12759 - --port=12759
- --rpc.gascap=0 - --rpc.gascap=600000000
- --rpc.txfeecap=0 - --rpc.txfeecap=0
- --state.scheme=path - --state.scheme=path
- --syncmode=snap - --syncmode=snap

View File

@@ -80,7 +80,7 @@ services:
- --metrics.port=6060 - --metrics.port=6060
- --nat=extip:${IP} - --nat=extip:${IP}
- --port=12853 - --port=12853
- --rpc.gascap=0 - --rpc.gascap=600000000
- --rpc.txfeecap=0 - --rpc.txfeecap=0
- --state.scheme=hash - --state.scheme=hash
- --syncmode=full - --syncmode=full
@@ -135,6 +135,10 @@ x-upstreams:
- filter - filter
methods: methods:
disabled: disabled:
# minimal bsc lacks the state to serve eth_getProof; the drpc gateway
# probes it and marks the whole upstream unavailable on "header not
# found" (especially while catching up after a restart).
- name: eth_getProof
enabled: enabled:
- name: txpool_content # TODO: should be disabled for rollup nodes - name: txpool_content # TODO: should be disabled for rollup nodes
# standard geth only # standard geth only

View File

@@ -80,7 +80,7 @@ services:
- --metrics.port=6060 - --metrics.port=6060
- --nat=extip:${IP} - --nat=extip:${IP}
- --port=14596 - --port=14596
- --rpc.gascap=0 - --rpc.gascap=600000000
- --rpc.txfeecap=0 - --rpc.txfeecap=0
- --state.scheme=path - --state.scheme=path
- --syncmode=snap - --syncmode=snap
@@ -137,6 +137,10 @@ x-upstreams:
disabled: disabled:
# not compatible with path state scheme # not compatible with path state scheme
- name: debug_traceBlockByHash - name: debug_traceBlockByHash
# minimal bsc lacks the state to serve eth_getProof; the drpc gateway
# probes it and marks the whole upstream unavailable on "header not
# found" (especially while catching up after a restart).
- name: eth_getProof
enabled: enabled:
- name: txpool_content # TODO: should be disabled for rollup nodes - name: txpool_content # TODO: should be disabled for rollup nodes
# standard geth only # standard geth only

View File

@@ -75,7 +75,7 @@ services:
- --metrics.port=6060 - --metrics.port=6060
- --nat=extip:${IP} - --nat=extip:${IP}
- --port=12037 - --port=12037
- --rpc.gascap=0 - --rpc.gascap=600000000
- --rpc.txfeecap=0 - --rpc.txfeecap=0
- --state.scheme=path - --state.scheme=path
- --syncmode=full - --syncmode=full

View File

@@ -74,7 +74,7 @@ services:
- --metrics.port=6060 - --metrics.port=6060
- --nat=extip:${IP} - --nat=extip:${IP}
- --port=12037 - --port=12037
- --rpc.gascap=0 - --rpc.gascap=600000000
- --rpc.txfeecap=0 - --rpc.txfeecap=0
- --state.scheme=path - --state.scheme=path
- --syncmode=snap - --syncmode=snap

View File

@@ -130,6 +130,10 @@ x-upstreams:
methods: methods:
disabled: disabled:
- name: eth_getLogs # this returns result [] on ethereum mainnet when it shouldn't so it's probably buggy on al networks - name: eth_getLogs # this returns result [] on ethereum mainnet when it shouldn't so it's probably buggy on al networks
# minimal bsc lacks the state to serve eth_getProof; the drpc gateway
# probes it and marks the whole upstream unavailable on "header not
# found" (especially while catching up after a restart).
- name: eth_getProof
enabled: enabled:
- name: txpool_content # TODO: should be disabled for rollup nodes - name: txpool_content # TODO: should be disabled for rollup nodes
# standard geth and erigon # standard geth and erigon

View File

@@ -130,6 +130,10 @@ x-upstreams:
methods: methods:
disabled: disabled:
- name: eth_getLogs # this returns result [] on ethereum mainnet when it shouldn't so it's probably buggy on al networks - name: eth_getLogs # this returns result [] on ethereum mainnet when it shouldn't so it's probably buggy on al networks
# minimal bsc lacks the state to serve eth_getProof; the drpc gateway
# probes it and marks the whole upstream unavailable on "header not
# found" (especially while catching up after a restart).
- name: eth_getProof
enabled: enabled:
- name: txpool_content # TODO: should be disabled for rollup nodes - name: txpool_content # TODO: should be disabled for rollup nodes
# standard geth and erigon # standard geth and erigon

View File

@@ -18,6 +18,7 @@ services:
- "prometheus-scrape.enabled=true" - "prometheus-scrape.enabled=true"
- "prometheus-scrape.port=8080" - "prometheus-scrape.port=8080"
- "prometheus-scrape.job_name=cadvisor" - "prometheus-scrape.job_name=cadvisor"
- "prometheus-scrape.metrics_path=/metrics"
- "org.label-schema.group=monitoring" - "org.label-schema.group=monitoring"
networks: networks:
- monitoring - monitoring

View File

@@ -10,15 +10,19 @@ fi
RPC_URL=$1 RPC_URL=$1
shift shift
# Check for --starknet / --aztec flag # Check for --starknet / --aztec / --cosmos flag
is_starknet=false is_starknet=false
is_aztec=false is_aztec=false
is_cosmos=false
if [ "$1" == "--starknet" ]; then if [ "$1" == "--starknet" ]; then
is_starknet=true is_starknet=true
shift shift
elif [ "$1" == "--aztec" ]; then elif [ "$1" == "--aztec" ]; then
is_aztec=true is_aztec=true
shift shift
elif [ "$1" == "--cosmos" ]; then
is_cosmos=true
shift
fi fi
REF="" REF=""
@@ -33,6 +37,28 @@ ref=${REF% }
timeout=3 # seconds timeout=3 # seconds
# CometBFT / cosmos (gaiad and the cosmos batch): no EVM RPC. Use the chain's own
# sync_info from the CometBFT /status method — catching_up=false means caught up to head.
# Short-circuits here; the EVM/starknet/aztec block-comparison path below is not used.
if $is_cosmos; then
status=$(curl -L --ipv4 -m $timeout -s -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","id":1,"method":"status"}' "$RPC_URL")
if [ $? -ne 0 ] || [ -z "$status" ]; then echo "timeout"; exit 1; fi
catching_up=$(echo "$status" | jq -r '.result.sync_info.catching_up // .sync_info.catching_up' 2>/dev/null)
node_height=$(echo "$status" | jq -r '.result.sync_info.latest_block_height // .sync_info.latest_block_height' 2>/dev/null)
if [ -z "$node_height" ] || [ "$node_height" = "null" ]; then echo "error"; exit 1; fi
if [ "$catching_up" = "true" ]; then echo "syncing"; exit 1; fi
# catching_up=false => synced. If a reference endpoint is given, sanity-check head gap.
if [ -n "$ref" ]; then
ref_status=$($BASEPATH/multicurl.sh -L --ipv4 -m $timeout -s -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","id":1,"method":"status"}' $ref)
ref_height=$(echo "$ref_status" | jq -r '.result.sync_info.latest_block_height // .sync_info.latest_block_height' 2>/dev/null)
if [ -n "$ref_height" ] && [ "$ref_height" != "null" ] && [ "$ref_height" -gt 0 ] 2>/dev/null; then
gap=$(( ref_height - node_height ))
if [ "$gap" -gt 100 ]; then echo "behind ($gap)"; exit 1; fi
fi
fi
echo "online"; exit 0
fi
response_file=$(mktemp) response_file=$(mktemp)
# Use appropriate RPC method based on chain type # Use appropriate RPC method based on chain type
@@ -78,9 +104,51 @@ if [ $? -eq 0 ]; then
rm "$response_file" rm "$response_file"
if [ -n "$ref" ]; then if [ -n "$ref" ]; then
MAX_RETRIES=3
attempt=1
while [ $attempt -le $MAX_RETRIES ]; do
# Re-fetch local latest block for retries > 1
if [ $attempt -gt 1 ]; then
sleep 3
# Re-query local latest block and update variables
response_file=$(mktemp)
http_status_code=$(curl -L --ipv4 -m $timeout -s -X POST -w "%{http_code}" -o "$response_file" -H "Content-Type: application/json" --data "$rpc_method" $RPC_URL)
if [ $? -eq 0 ] && [[ $http_status_code -eq 200 ]]; then
response=$(cat "$response_file")
if $is_starknet; then
latest_block_timestamp_decimal=$(echo "$response" | jq -r '.result.timestamp')
latest_block_number=$(echo "$response" | jq -r '.result.block_number')
latest_block_hash=$(echo "$response" | jq -r '.result.block_hash')
elif $is_aztec; then
latest_block_number=$(echo "$response" | jq -r '.result.header.globalVariables.blockNumber')
latest_block_timestamp_decimal=$(echo "$response" | jq -r '.result.header.globalVariables.timestamp')
latest_block_hash=$(echo "$response" | jq -r '.result.blockHash')
if [ "$latest_block_number" = "null" ] || [ "$latest_block_timestamp_decimal" = "null" ] || [ -z "$latest_block_timestamp_decimal" ]; then
echo "error"
exit 1
fi
else
latest_block_timestamp=$(echo "$response" | jq -r '.result.timestamp')
latest_block_timestamp_decimal=$((16#${latest_block_timestamp#0x}))
latest_block_number=$(echo "$response" | jq -r '.result.number')
latest_block_hash=$(echo "$response" | jq -r '.result.hash')
fi
current_time=$(date +%s)
time_difference=$((current_time - latest_block_timestamp_decimal))
rm "$response_file"
else
rm "$response_file"
echo "error"
exit 1
fi
fi
response_file2=$(mktemp) response_file2=$(mktemp)
if [ $attempt -eq 1 ]; then
sleep 3 # to give the reference node more time to import the block if it is very current sleep 3 # to give the reference node more time to import the block if it is very current
fi
if $is_starknet; then if $is_starknet; then
# Starknet uses block_id object with block_number # Starknet uses block_id object with block_number
@@ -163,12 +231,12 @@ if [ $? -eq 0 ]; then
response3=$(cat "$response_file3") response3=$(cat "$response_file3")
if $is_starknet; then if $is_starknet; then
latest_block_timestamp_decimal3=$(echo "$response3" | jq -r '.result.timestamp') ref_num=$(echo "$response3" | jq -r '.result.block_number // empty')
elif $is_aztec; then elif $is_aztec; then
latest_block_timestamp_decimal3=$(echo "$response3" | jq -r '.result.header.globalVariables.timestamp') ref_num=$(echo "$response3" | jq -r '.result.header.globalVariables.blockNumber // empty')
else else
latest_block_timestamp3=$(echo "$response3" | jq -r '.result.timestamp') ref_num_hex=$(echo "$response3" | jq -r '.result.number // empty')
latest_block_timestamp_decimal3=$((16#${latest_block_timestamp3#0x})) ref_num=$([ -n "$ref_num_hex" ] && printf '%d' "$ref_num_hex" 2>/dev/null)
fi fi
# echo "refer: $latest_block_timestamp_decimal3" # echo "refer: $latest_block_timestamp_decimal3"
@@ -179,25 +247,35 @@ if [ $? -eq 0 ]; then
response4=$(cat "$response_file4") response4=$(cat "$response_file4")
if $is_starknet; then if $is_starknet; then
latest_block_timestamp_decimal4=$(echo "$response4" | jq -r '.result.timestamp') local_num=$(echo "$response4" | jq -r '.result.block_number // empty')
elif $is_aztec; then elif $is_aztec; then
latest_block_timestamp_decimal4=$(echo "$response4" | jq -r '.result.header.globalVariables.timestamp') local_num=$(echo "$response4" | jq -r '.result.header.globalVariables.blockNumber // empty')
else else
latest_block_timestamp4=$(echo "$response4" | jq -r '.result.timestamp') local_num_hex=$(echo "$response4" | jq -r '.result.number // empty')
latest_block_timestamp_decimal4=$((16#${latest_block_timestamp4#0x})) local_num=$([ -n "$local_num_hex" ] && printf '%d' "$local_num_hex" 2>/dev/null)
fi fi
#echo "local: $latest_block_timestamp_decimal4" #echo "local: $latest_block_timestamp_decimal4"
rm "$response_file4" rm "$response_file4"
time_difference3=$(echo "scale=6; (${latest_block_timestamp_decimal3} - ${request_time3}) - (${latest_block_timestamp_decimal4} - ${request_time4})" | bc) # Lag in BLOCKS between the reference head and the local head
# (positive => local behind). Compare against dRPC's own per-chain
#echo "diff after network latency: $time_difference3 s" # thresholds (LAGGING_LAG / SYNCING_LAG from chains.yaml via
# sync-status.sh) so our status matches the dRPC gateway's view.
if (( $(echo "$time_difference3 < 2" | bc -l) )); then # dRPC uses the two thresholds inconsistently (sometimes
# lagging<syncing, sometimes the reverse), so treat the smaller as
# the online boundary and the larger as the syncing/drop boundary.
if [ -z "$ref_num" ] || [ -z "$local_num" ]; then
echo "error"
exit 1
fi
lag=$(( ref_num - local_num ))
lo=${LAGGING_LAG:-2}; hi=${SYNCING_LAG:-6}
if [ "$lo" -gt "$hi" ]; then tmp=$lo; lo=$hi; hi=$tmp; fi
if [ "$lag" -le "$lo" ]; then
echo "online" echo "online"
exit 0 exit 0
elif (( $(echo "$time_difference3 < 5" | bc -l) )); then elif [ "$lag" -le "$hi" ]; then
echo "lagging" echo "lagging"
exit 0 exit 0
else else
@@ -212,14 +290,23 @@ if [ $? -eq 0 ]; then
fi fi
fi fi
else else
# Hash mismatch - retry if we have attempts left
if [ $attempt -lt $MAX_RETRIES ]; then
rm "$response_file2"
attempt=$((attempt + 1))
continue
else
rm "$response_file2"
echo "forked" echo "forked"
exit 1 exit 1
fi fi
fi
else else
echo "unverified ($http_status_code2)" echo "unverified ($http_status_code2)"
exit 1 exit 1
fi fi
fi fi
done
echo "unverified ($curl_code)" echo "unverified ($curl_code)"
exit 0 exit 0

View File

@@ -1,21 +1,260 @@
#!/bin/bash #!/bin/bash
# Retain the N newest backups per volume key and move excess to trash.
#
# Usage:
# ./cleanup-backups.sh [--dry-run]
#
# Environment:
# BACKUP_DIR=/backup Backup root directory
# TRASH_DIR=/backup/trash Where removed backups are staged
# KEEP_COUNT=3 Backups to keep per volume key
# UPLOADING_MAX_AGE_HOURS=72 Trash uploading-* only when older than this
# EXCLUDE_DIRS=graveyard:quarantained:trash Colon-separated subdirs to skip
# Directory containing the backup files set -euo pipefail
backup_dir="/backup"
# Get a list of all backup files BASEPATH="$(cd "$(dirname "$0")" && pwd)"
backup_files=$(find "$backup_dir" -type f -name 'rpc_*-*.tar.zst') BACKUP_DIR="${BACKUP_DIR:-/backup}"
TRASH_DIR="${TRASH_DIR:-$BACKUP_DIR/trash}"
KEEP_COUNT="${KEEP_COUNT:-3}"
UPLOADING_MAX_AGE_HOURS="${UPLOADING_MAX_AGE_HOURS:-72}"
EXCLUDE_DIRS="${EXCLUDE_DIRS:-graveyard:quarantained:trash}"
# Iterate through each backup file DRY_RUN=false
for file in $backup_files; do if [[ "${1:-}" == "--dry-run" ]]; then
# Extract volume name from the file name DRY_RUN=true
volume_name=$(basename "$file" | cut -d '-' -f 1-3) elif [[ -n "${1:-}" ]]; then
echo "Usage: $0 [--dry-run]" >&2
exit 1
fi
# Get the latest backup file for this volume name BACKUP_PATTERN='^(rpc_.+)-([0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{2})-([0-9]+)G\.tar\.zst$'
latest_backup=$(find "$backup_dir" -type f -name "$volume_name-*" -printf "%T@ %p\n" | sort -n | tail -1 | cut -d ' ' -f 2)
# Keep only the latest backup file for this volume name log() {
if [[ "$file" != "$latest_backup" ]]; then echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >&2
rm "$file" }
bytes_trashed=0
add_trashed_bytes() {
local file=$1
if [[ -f "$file" ]]; then
local size
size=$(stat -c%s "$file" 2>/dev/null || echo 0)
bytes_trashed=$((bytes_trashed + size))
fi fi
done }
trash_file() {
local file=$1
local reason=$2
if [[ ! -f "$file" ]]; then
return 0
fi
local dest="$TRASH_DIR/$(basename "$file")"
if [[ -e "$dest" ]]; then
log "Error: trash destination already exists, skipping: $dest"
return 1
fi
if $DRY_RUN; then
log "DRY-RUN would trash ($reason): $file -> $dest"
return 0
fi
mv -- "$file" "$dest"
log "Trashed ($reason): $file -> $dest"
}
is_excluded_path() {
local path=$1
local rel="${path#"$BACKUP_DIR"/}"
if [[ "$rel" == broken_* ]] || [[ "$rel" == deprecated-* ]]; then
return 0
fi
local dir
IFS=':' read -ra excluded_dirs <<< "$EXCLUDE_DIRS"
for dir in "${excluded_dirs[@]}"; do
if [[ -n "$dir" && ( "$rel" == "$dir" || "$rel" == "$dir"/* ) ]]; then
return 0
fi
done
return 1
}
parse_volume_key() {
local basename=$1
if [[ "$basename" =~ $BACKUP_PATTERN ]]; then
echo "${BASH_REMATCH[1]}"
return 0
fi
return 1
}
metadata_for_archive() {
local archive=$1
echo "${archive%.tar.zst}.txt"
}
file_has_open_handles() {
local file=$1
if command -v lsof >/dev/null 2>&1; then
if lsof -- "$file" >/dev/null 2>&1; then
return 0
fi
fi
if command -v fuser >/dev/null 2>&1; then
if fuser -- "$file" >/dev/null 2>&1; then
return 0
fi
fi
return 1
}
cleanup_stale_uploads() {
local upload_file
local age_seconds=$((UPLOADING_MAX_AGE_HOURS * 3600))
local now
now=$(date +%s)
while IFS= read -r -d '' upload_file; do
if is_excluded_path "$upload_file"; then
continue
fi
local mtime age
mtime=$(stat -c %Y "$upload_file")
age=$((now - mtime))
if (( age < age_seconds )); then
log "Keeping in-progress upload ($(($age / 3600))h old): $upload_file"
continue
fi
if file_has_open_handles "$upload_file"; then
log "Keeping upload with open handles ($(($age / 3600))h old): $upload_file"
continue
fi
add_trashed_bytes "$upload_file"
trash_file "$upload_file" "stale upload older than ${UPLOADING_MAX_AGE_HOURS}h"
done < <(find "$BACKUP_DIR" -maxdepth 1 -type f -name 'uploading-*' -print0 2>/dev/null)
}
cleanup_volume_backups() {
declare -A volume_files=()
local file basename volume_key
while IFS= read -r -d '' file; do
if is_excluded_path "$file"; then
continue
fi
basename=$(basename "$file")
if ! volume_key=$(parse_volume_key "$basename"); then
log "Skipping unrecognized backup filename: $file"
continue
fi
volume_files["$volume_key"]+="$file"$'\n'
done < <(find "$BACKUP_DIR" -maxdepth 1 -type f -name 'rpc_*-*.tar.zst' -print0 2>/dev/null)
local volume trashed=0 kept=0
for volume in "${!volume_files[@]}"; do
mapfile -t files < <(printf '%s' "${volume_files[$volume]}" | sed '/^$/d' | sort)
local total=${#files[@]}
if (( total <= KEEP_COUNT )); then
kept=$((kept + total))
continue
fi
local delete_count=$((total - KEEP_COUNT))
local i
for ((i = 0; i < delete_count; i++)); do
local archive="${files[$i]}"
local metadata
metadata=$(metadata_for_archive "$archive")
add_trashed_bytes "$archive"
trash_file "$archive" "keeping ${KEEP_COUNT}/${total} for $volume"
trashed=$((trashed + 1))
if [[ -f "$metadata" ]]; then
add_trashed_bytes "$metadata"
trash_file "$metadata" "orphaned metadata for $volume"
fi
done
kept=$((kept + KEEP_COUNT))
done
echo "$trashed $kept"
}
cleanup_orphan_metadata() {
local metadata archive basename
local orphans=0
while IFS= read -r -d '' metadata; do
if is_excluded_path "$metadata"; then
continue
fi
basename=$(basename "$metadata")
if [[ ! "$basename" =~ ^rpc_.+\.txt$ ]]; then
continue
fi
archive="${metadata%.txt}.tar.zst"
if [[ -f "$archive" ]]; then
continue
fi
if [[ -f "$TRASH_DIR/$(basename "$archive")" ]]; then
add_trashed_bytes "$metadata"
trash_file "$metadata" "metadata for archived-in-trash backup"
orphans=$((orphans + 1))
continue
fi
add_trashed_bytes "$metadata"
trash_file "$metadata" "orphaned metadata without archive"
orphans=$((orphans + 1))
done < <(find "$BACKUP_DIR" -maxdepth 1 -type f -name 'rpc_*.txt' -print0 2>/dev/null)
echo "$orphans"
}
main() {
if [[ ! -d "$BACKUP_DIR" ]]; then
log "Error: backup directory does not exist: $BACKUP_DIR"
exit 1
fi
if ! $DRY_RUN; then
mkdir -p "$TRASH_DIR"
fi
log "Starting backup cleanup in $BACKUP_DIR (trash_dir=$TRASH_DIR, keep_count=$KEEP_COUNT, uploading_max_age=${UPLOADING_MAX_AGE_HOURS}h, dry_run=$DRY_RUN)"
cleanup_stale_uploads
local trashed kept orphan_metadata
read -r trashed kept < <(cleanup_volume_backups)
read -r orphan_metadata < <(cleanup_orphan_metadata)
local trashed_human
trashed_human=$(numfmt --to=iec-i --suffix=B "$bytes_trashed" 2>/dev/null || echo "${bytes_trashed}B")
log "Cleanup complete: trashed=$trashed kept=$kept orphan_metadata=$orphan_metadata staged≈$trashed_human"
}
main "$@"

View File

@@ -1,3 +1,8 @@
#!/bin/bash
# List (default) or, with --remove-from-disk, delete the docker volumes that are NOT
# referenced by the current COMPOSE_FILE. Removal also frees the static-file data that was
# offloaded to /slowdisk behind the volume's symlinks (delete_slowdisk_targets_for_key),
# so nothing leaks on /slowdisk.
BASEPATH="$(dirname "$0")" BASEPATH="$(dirname "$0")"
source $BASEPATH/.env source $BASEPATH/.env
source $BASEPATH/volume-utils.sh source $BASEPATH/volume-utils.sh
@@ -9,7 +14,7 @@ used_volumes=()
for part in "${parts[@]}"; do for part in "${parts[@]}"; do
volumes=$(get_volume_keys "$BASEPATH/$part") volumes=$(get_volume_keys "$BASEPATH/$part")
# Convert volumes to an array # Prefix each compose volume key with rpc_ to match docker's volume names.
prefix="rpc_" prefix="rpc_"
IFS=$'\n' read -r -d '' -a volumes_array <<< "$(printf "%s\n" "${volumes[@]}" | sed "/^$/! s/^/$prefix/")" IFS=$'\n' read -r -d '' -a volumes_array <<< "$(printf "%s\n" "${volumes[@]}" | sed "/^$/! s/^/$prefix/")"
@@ -18,19 +23,27 @@ done
on_disk=($(docker volume ls --format '{{.Name}}' | grep '^rpc_')) on_disk=($(docker volume ls --format '{{.Name}}' | grep '^rpc_'))
unused_volumes=() # A volume counts as "used" only on an EXACT name match. The previous substring test
# ([[ "${used_volumes[@]}" =~ "$element" ]]) could mis-classify a volume whose name is a
# substring of another (e.g. ...-pruned vs ...-pruned-trace) and wrongly purge a live one.
is_used() {
local v=$1 u
for u in "${used_volumes[@]}"; do
[[ "$u" == "$v" ]] && return 0
done
return 1
}
unused_volumes=()
for element in "${on_disk[@]}"; do for element in "${on_disk[@]}"; do
# Check if the element exists in array2 is_used "$element" || unused_volumes+=("$element")
if [[ ! "${used_volumes[@]}" =~ "$element" ]]; then
# If not, add it to the difference array
unused_volumes+=("$element")
fi
done done
if [ "$1" = "--remove-from-disk" ]; then if [ "$1" = "--remove-from-disk" ]; then
# Iterate over volumes in the difference array and remove them from disk # Remove each unused volume AND the /slowdisk static data behind its symlinks.
for volume in "${unused_volumes[@]}"; do for volume in "${unused_volumes[@]}"; do
echo "removing unused volume: $volume"
delete_slowdisk_targets_for_key "${volume#rpc_}"
docker volume rm "$volume" docker volume rm "$volume"
done done
else else

View File

@@ -2,6 +2,23 @@
# Script to clone node volumes from backup location to a remote server # Script to clone node volumes from backup location to a remote server
# Uses the same transfer method as clone-node.sh but streams zstd archives directly from backup location # Uses the same transfer method as clone-node.sh but streams zstd archives directly from backup location
#
# Usage: ./clone-backup.sh <config> <dest_host> [--no-slowdisk]
# --no-slowdisk : do NOT offload static files to /slowdisk (no symlinks);
# extract everything onto the local disk instead. Required to
# proceed when /slowdisk is too small for the static files.
# Pull the --no-slowdisk flag out of the args so the positional <config>/<dest>
# parsing below is unaffected regardless of where the flag is placed.
NO_SLOWDISK=false
_args=()
for _a in "$@"; do
case "$_a" in
--no-slowdisk) NO_SLOWDISK=true ;;
*) _args+=("$_a") ;;
esac
done
set -- "${_args[@]}"
if [[ -n $2 ]]; then if [[ -n $2 ]]; then
DEST_HOST="$2.stakesquid.eu" DEST_HOST="$2.stakesquid.eu"
@@ -108,7 +125,7 @@ release_port() {
# Check if SLOWDISK mode is enabled on target # Check if SLOWDISK mode is enabled on target
check_slowdisk_enabled() { check_slowdisk_enabled() {
$SSH_CMD "$DEST_HOST" "grep -q '^SLOWDISK=true' /root/rpc/.env 2>/dev/null" $SSH_CMD "$DEST_HOST" "grep -qi '^SLOWDISK=true' /root/rpc/.env 2>/dev/null"
return $? return $?
} }
@@ -159,6 +176,40 @@ parse_metadata() {
printf '%s\n' "${static_paths[@]}" printf '%s\n' "${static_paths[@]}"
} }
# Decide whether to offload this volume's static files to /slowdisk.
# return 0 -> use /slowdisk (caller should create symlinks + extract)
# return 1 -> skip /slowdisk (extract static files onto local disk)
# Aborts the whole script if /slowdisk is too small and --no-slowdisk was not
# given, to avoid overfilling /slowdisk with a partially-extracted snapshot.
decide_slowdisk() {
local key=$1
local static_size_kb=$2
# Explicit override: never offload, never create symlinks.
if [[ "$NO_SLOWDISK" == "true" ]]; then
echo " --no-slowdisk: skipping /slowdisk offload for '$key' (static files -> local disk)"
return 1
fi
# How much room is actually on /slowdisk right now?
local slowdisk_available
slowdisk_available=$($SSH_CMD "$DEST_HOST" "df -BK /slowdisk 2>/dev/null | tail -1 | awk '{print \$4}' | sed 's/K//'")
if [[ -z "$slowdisk_available" ]] || [[ "$slowdisk_available" -lt "$static_size_kb" ]]; then
{
echo ""
echo "WARNING: /slowdisk on $DEST_HOST is too small for the static files of '$key'."
echo " available: $(( ${slowdisk_available:-0} / 1024 ))MB, needed: $(( static_size_kb / 1024 ))MB"
echo " Aborting to avoid overfilling /slowdisk with a partial snapshot."
echo " Re-run with --no-slowdisk to extract static files onto the local disk"
echo " instead (no /slowdisk offload, no symlinks created)."
} >&2
exit 1
fi
return 0
}
# Setup slowdisk directory structure with symlinks # Setup slowdisk directory structure with symlinks
setup_slowdisk_structure() { setup_slowdisk_structure() {
local key=$1 local key=$1
@@ -255,7 +306,7 @@ transfer_backup() {
local backup_basename=$(basename "$backup_file" .tar.zst) local backup_basename=$(basename "$backup_file" .tar.zst)
local metadata_file="$backup_dir/${backup_basename}.txt" local metadata_file="$backup_dir/${backup_basename}.txt"
local use_slowdisk=false local use_slowdisk=false
local tar_extract_opts="-xf - -C /" local tar_extract_opts="-xf - -C / --keep-directory-symlink"
if [[ -f "$metadata_file" ]] && check_slowdisk_enabled; then if [[ -f "$metadata_file" ]] && check_slowdisk_enabled; then
echo "Metadata file found and SLOWDISK mode enabled" echo "Metadata file found and SLOWDISK mode enabled"
@@ -267,16 +318,22 @@ transfer_backup() {
local static_paths=($(echo "$metadata_output" | tail -n +2)) local static_paths=($(echo "$metadata_output" | tail -n +2))
if [[ ${#static_paths[@]} -gt 0 ]] && [[ -n "$static_size_kb" ]]; then if [[ ${#static_paths[@]} -gt 0 ]] && [[ -n "$static_size_kb" ]]; then
# Check /slowdisk capacity (aborts if too small without --no-slowdisk).
if decide_slowdisk "$key" "$static_size_kb"; then
# Setup slowdisk structure on remote # Setup slowdisk structure on remote
if setup_slowdisk_structure "$key" "$static_size_kb" "${static_paths[@]}"; then if setup_slowdisk_structure "$key" "$static_size_kb" "${static_paths[@]}"; then
use_slowdisk=true use_slowdisk=true
# Use --skip-old-files to avoid overwriting existing symlinks/directories # Use --skip-old-files to avoid overwriting existing symlinks/directories
# But we still want to extract files into symlinked directories # and --keep-directory-symlink so tar extracts THROUGH the pre-created dir symlinks
tar_extract_opts="-xf - -C / --skip-old-files" # instead of trying to mkdir over them (which fails with 'Cannot mkdir: File exists')
tar_extract_opts="-xf - -C / --skip-old-files --keep-directory-symlink"
echo "SLOWDISK structure ready, will extract respecting symlinks" echo "SLOWDISK structure ready, will extract respecting symlinks"
else else
echo "Warning: Failed to setup SLOWDISK structure, falling back to normal extraction" echo "Warning: Failed to setup SLOWDISK structure, falling back to normal extraction"
fi fi
fi
# decide_slowdisk returned 1 (--no-slowdisk): leave tar_extract_opts at
# the default so static files are extracted onto the local disk.
else else
echo "Warning: Could not parse metadata file, falling back to normal extraction" echo "Warning: Could not parse metadata file, falling back to normal extraction"
fi fi
@@ -438,7 +495,7 @@ transfer_backup_ssh() {
# Check for metadata file and SLOWDISK mode (same logic as transfer_backup) # Check for metadata file and SLOWDISK mode (same logic as transfer_backup)
local backup_basename=$(basename "$backup_file" .tar.zst) local backup_basename=$(basename "$backup_file" .tar.zst)
local metadata_file="$backup_dir/${backup_basename}.txt" local metadata_file="$backup_dir/${backup_basename}.txt"
local tar_extract_opts="-xf - -C /" local tar_extract_opts="-xf - -C / --keep-directory-symlink"
if [[ -f "$metadata_file" ]] && check_slowdisk_enabled; then if [[ -f "$metadata_file" ]] && check_slowdisk_enabled; then
echo "Metadata file found and SLOWDISK mode enabled" echo "Metadata file found and SLOWDISK mode enabled"
@@ -452,7 +509,9 @@ transfer_backup_ssh() {
if [[ ${#static_paths[@]} -gt 0 ]] && [[ -n "$static_size_kb" ]]; then if [[ ${#static_paths[@]} -gt 0 ]] && [[ -n "$static_size_kb" ]]; then
# Setup slowdisk structure on remote # Setup slowdisk structure on remote
if setup_slowdisk_structure "$key" "$static_size_kb" "${static_paths[@]}"; then if setup_slowdisk_structure "$key" "$static_size_kb" "${static_paths[@]}"; then
tar_extract_opts="-xf - -C / --skip-old-files" # and --keep-directory-symlink so tar extracts THROUGH the pre-created dir symlinks
# instead of trying to mkdir over them (which fails with 'Cannot mkdir: File exists')
tar_extract_opts="-xf - -C / --skip-old-files --keep-directory-symlink"
echo "SLOWDISK structure ready, will extract respecting symlinks" echo "SLOWDISK structure ready, will extract respecting symlinks"
else else
echo "Warning: Failed to setup SLOWDISK structure, falling back to normal extraction" echo "Warning: Failed to setup SLOWDISK structure, falling back to normal extraction"
@@ -482,6 +541,15 @@ main() {
# Set up cleanup trap # Set up cleanup trap
trap cleanup_all_ports EXIT INT TERM trap cleanup_all_ports EXIT INT TERM
# RETH GUARD: reth refuses to start when its static_files directory is a symlink.
# Match restore-volumes.sh: skip the whole /slowdisk static-file symlink offload
# for reth nodes and extract everything onto the primary disk.
if [[ "$1" == *reth* ]]; then
echo "WARNING: $1 contains 'reth' — static-file symlink offload disabled (reth broke whole-dir symlinks)"
echo " All volumes will be extracted onto the primary disk (equivalent to --no-slowdisk)"
NO_SLOWDISK=true
fi
setup_ssh_multiplex setup_ssh_multiplex
# Check if backup directory exists # Check if backup directory exists

View File

@@ -5,6 +5,21 @@
BASEPATH="$(dirname "$0")" BASEPATH="$(dirname "$0")"
source "$BASEPATH/volume-utils.sh" source "$BASEPATH/volume-utils.sh"
# Usage: ./clone-node.sh <node_path> <dest_host> [--no-slowdisk]
# --no-slowdisk : do NOT offload static files to /slowdisk on the target (no
# symlinks); extract everything to the local disk. Required to
# proceed when the target's /slowdisk is too small. Strip it
# out before the positional <node>/<dest> parsing below.
NO_SLOWDISK=false
_args=()
for _a in "$@"; do
case "$_a" in
--no-slowdisk) NO_SLOWDISK=true ;;
*) _args+=("$_a") ;;
esac
done
set -- "${_args[@]}"
if [[ -n $2 ]]; then if [[ -n $2 ]]; then
DEST_HOST="$2.stakesquid.eu" DEST_HOST="$2.stakesquid.eu"
echo "Setting up optimized transfer to $DEST_HOST" echo "Setting up optimized transfer to $DEST_HOST"
@@ -104,7 +119,7 @@ release_port() {
# Check if SLOWDISK mode is enabled on target # Check if SLOWDISK mode is enabled on target
check_slowdisk_enabled() { check_slowdisk_enabled() {
$SSH_CMD "$DEST_HOST" "grep -q '^SLOWDISK=true' /root/rpc/.env 2>/dev/null" $SSH_CMD "$DEST_HOST" "grep -qi '^SLOWDISK=true' /root/rpc/.env 2>/dev/null"
return $? return $?
} }
@@ -141,6 +156,36 @@ detect_static_files() {
printf '%s\n' "${static_paths[@]}" printf '%s\n' "${static_paths[@]}"
} }
# Decide whether to offload this volume's static files to the target's /slowdisk.
# return 0 -> use /slowdisk (caller sets up symlinks + extracts through them)
# return 1 -> skip /slowdisk (extract static files onto local disk)
# Aborts the whole clone if /slowdisk is too small and --no-slowdisk was not
# given, to avoid overfilling /slowdisk with a partially-extracted volume.
decide_slowdisk() {
local key=$1
local static_size_kb=$2
if [[ "$NO_SLOWDISK" == "true" ]]; then
echo " --no-slowdisk: skipping /slowdisk offload for '$key' (static files -> local disk)"
return 1
fi
local slowdisk_available
slowdisk_available=$($SSH_CMD "$DEST_HOST" "df -BK /slowdisk 2>/dev/null | tail -1 | awk '{print \$4}' | sed 's/K//'")
if [[ -z "$slowdisk_available" ]] || [[ "$slowdisk_available" -lt "$static_size_kb" ]]; then
{
echo ""
echo "WARNING: /slowdisk on $DEST_HOST is too small for the static files of '$key'."
echo " available: $(( ${slowdisk_available:-0} / 1024 ))MB, needed: $(( static_size_kb / 1024 ))MB"
echo " Aborting to avoid overfilling /slowdisk with a partial volume."
echo " Re-run with --no-slowdisk to clone without /slowdisk offload (static files on local disk)."
} >&2
exit 1
fi
return 0
}
# Setup slowdisk directory structure with symlinks # Setup slowdisk directory structure with symlinks
setup_slowdisk_structure() { setup_slowdisk_structure() {
local key=$1 local key=$1
@@ -231,7 +276,7 @@ transfer_volume() {
fi fi
local folder_size=$(du -sb "$source_folder" 2>/dev/null | awk '{print $1}') local folder_size=$(du -sb "$source_folder" 2>/dev/null | awk '{print $1}')
local tar_extract_opts="-xf - -C /" local tar_extract_opts="-xf - -C / --keep-directory-symlink"
local use_slowdisk=false local use_slowdisk=false
# Check for SLOWDISK mode and detect static files # Check for SLOWDISK mode and detect static files
@@ -245,17 +290,23 @@ transfer_volume() {
if [[ ${#static_paths[@]} -gt 0 ]] && [[ -n "$static_size_kb" ]]; then if [[ ${#static_paths[@]} -gt 0 ]] && [[ -n "$static_size_kb" ]]; then
echo "Found ${#static_paths[@]} static paths (total: $((static_size_kb / 1024))MB)" echo "Found ${#static_paths[@]} static paths (total: $((static_size_kb / 1024))MB)"
# Check /slowdisk capacity (aborts if too small without --no-slowdisk).
if decide_slowdisk "$key" "$static_size_kb"; then
echo "Setting up SLOWDISK structure on target..." echo "Setting up SLOWDISK structure on target..."
# Setup slowdisk structure on remote # Setup slowdisk structure on remote
if setup_slowdisk_structure "$key" "$static_size_kb" "${static_paths[@]}"; then if setup_slowdisk_structure "$key" "$static_size_kb" "${static_paths[@]}"; then
use_slowdisk=true use_slowdisk=true
# Use --skip-old-files to avoid overwriting existing symlinks/directories # Use --skip-old-files to avoid overwriting existing symlinks/directories
tar_extract_opts="-xf - -C / --skip-old-files" # and --keep-directory-symlink so tar extracts THROUGH the pre-created dir symlinks
# instead of trying to mkdir over them (which fails with 'Cannot mkdir: File exists')
tar_extract_opts="-xf - -C / --skip-old-files --keep-directory-symlink"
echo "SLOWDISK structure ready, will extract respecting symlinks" echo "SLOWDISK structure ready, will extract respecting symlinks"
else else
echo "Warning: Failed to setup SLOWDISK structure, falling back to normal extraction" echo "Warning: Failed to setup SLOWDISK structure, falling back to normal extraction"
fi fi
fi
# decide_slowdisk returned 1 (--no-slowdisk): leave tar_extract_opts
# at the default so static files extract onto the local disk.
else else
echo "No static files detected, using normal extraction" echo "No static files detected, using normal extraction"
fi fi
@@ -408,7 +459,7 @@ transfer_volume_ssh() {
fi fi
local folder_size=$(du -sb "$source_folder" 2>/dev/null | awk '{print $1}') local folder_size=$(du -sb "$source_folder" 2>/dev/null | awk '{print $1}')
local tar_extract_opts="-xf - -C /" local tar_extract_opts="-xf - -C / --keep-directory-symlink"
# Check for SLOWDISK mode and detect static files (same logic as transfer_volume) # Check for SLOWDISK mode and detect static files (same logic as transfer_volume)
if check_slowdisk_enabled; then if check_slowdisk_enabled; then
@@ -421,15 +472,21 @@ transfer_volume_ssh() {
if [[ ${#static_paths[@]} -gt 0 ]] && [[ -n "$static_size_kb" ]]; then if [[ ${#static_paths[@]} -gt 0 ]] && [[ -n "$static_size_kb" ]]; then
echo "Found ${#static_paths[@]} static paths (total: $((static_size_kb / 1024))MB)" echo "Found ${#static_paths[@]} static paths (total: $((static_size_kb / 1024))MB)"
# Check /slowdisk capacity (aborts if too small without --no-slowdisk).
if decide_slowdisk "$key" "$static_size_kb"; then
echo "Setting up SLOWDISK structure on target..." echo "Setting up SLOWDISK structure on target..."
# Setup slowdisk structure on remote # Setup slowdisk structure on remote
if setup_slowdisk_structure "$key" "$static_size_kb" "${static_paths[@]}"; then if setup_slowdisk_structure "$key" "$static_size_kb" "${static_paths[@]}"; then
tar_extract_opts="-xf - -C / --skip-old-files" # and --keep-directory-symlink so tar extracts THROUGH the pre-created dir symlinks
# instead of trying to mkdir over them (which fails with 'Cannot mkdir: File exists')
tar_extract_opts="-xf - -C / --skip-old-files --keep-directory-symlink"
echo "SLOWDISK structure ready, will extract respecting symlinks" echo "SLOWDISK structure ready, will extract respecting symlinks"
else else
echo "Warning: Failed to setup SLOWDISK structure, falling back to normal extraction" echo "Warning: Failed to setup SLOWDISK structure, falling back to normal extraction"
fi fi
fi
# decide_slowdisk returned 1 (--no-slowdisk): leave tar_extract_opts
# at the default so static files extract onto the local disk.
else else
echo "No static files detected, using normal extraction" echo "No static files detected, using normal extraction"
fi fi
@@ -460,6 +517,15 @@ main() {
# Set up cleanup trap # Set up cleanup trap
trap cleanup_all_ports EXIT INT TERM trap cleanup_all_ports EXIT INT TERM
# RETH GUARD: reth refuses to start when its static_files directory is a symlink.
# Match restore-volumes.sh: skip the whole /slowdisk static-file symlink offload
# for reth nodes and extract everything onto the primary disk.
if [[ "$1" == *reth* ]]; then
echo "WARNING: $1 contains 'reth' — static-file symlink offload disabled (reth broke whole-dir symlinks)"
echo " All volumes will be extracted onto the primary disk (equivalent to --no-slowdisk)"
NO_SLOWDISK=true
fi
setup_ssh_multiplex setup_ssh_multiplex
# the following sysctls are critical for high-latency networks # the following sysctls are critical for high-latency networks

View File

@@ -196,6 +196,40 @@
"alephzero-sepolia-nitro-pruned-pebble-path" "alephzero-sepolia-nitro-pruned-pebble-path"
] ]
}, },
{
"chain": "mainnet",
"client": "nitro",
"compose_file": "arb/nitro/apechain-mainnet-nitro-archive-pebble-hash",
"features": [
"hash",
"pebble"
],
"network": "apechain",
"node": null,
"relay": null,
"stack": "arb",
"type": "archive",
"volumes": [
"apechain-mainnet-nitro-archive-pebble-hash"
]
},
{
"chain": "mainnet",
"client": "nitro",
"compose_file": "arb/nitro/apechain-mainnet-nitro-pruned-pebble-path",
"features": [
"path",
"pebble"
],
"network": "apechain",
"node": null,
"relay": null,
"stack": "arb",
"type": "pruned",
"volumes": [
"apechain-mainnet-nitro-pruned-pebble-path"
]
},
{ {
"chain": "nova", "chain": "nova",
"client": "nitro", "client": "nitro",
@@ -230,6 +264,23 @@
"arbitrum-nova-nitro-archive-pebble-path" "arbitrum-nova-nitro-archive-pebble-path"
] ]
}, },
{
"chain": "nova",
"client": "nitro",
"compose_file": "arb/nitro/arbitrum-nova-nitro-minimal-pebble-hash",
"features": [
"hash",
"pebble"
],
"network": "arbitrum",
"node": null,
"relay": null,
"stack": "arb",
"type": "minimal",
"volumes": [
"arbitrum-nova-nitro-minimal-pebble-hash"
]
},
{ {
"chain": "nova", "chain": "nova",
"client": "nitro", "client": "nitro",
@@ -317,6 +368,23 @@
"arbitrum-one-nitro-archive-pebble-path" "arbitrum-one-nitro-archive-pebble-path"
] ]
}, },
{
"chain": "one",
"client": "nitro",
"compose_file": "arb/nitro/arbitrum-one-nitro-minimal-pebble-hash",
"features": [
"hash",
"pebble"
],
"network": "arbitrum",
"node": null,
"relay": null,
"stack": "arb",
"type": "minimal",
"volumes": [
"arbitrum-one-nitro-minimal-pebble-hash"
]
},
{ {
"chain": "one", "chain": "one",
"client": "nitro", "client": "nitro",
@@ -369,6 +437,23 @@
"arbitrum-sepolia-nitro-archive-pebble-hash" "arbitrum-sepolia-nitro-archive-pebble-hash"
] ]
}, },
{
"chain": "sepolia",
"client": "nitro",
"compose_file": "arb/nitro/arbitrum-sepolia-nitro-minimal-pebble-hash",
"features": [
"hash",
"pebble"
],
"network": "arbitrum",
"node": null,
"relay": null,
"stack": "arb",
"type": "minimal",
"volumes": [
"arbitrum-sepolia-nitro-minimal-pebble-hash"
]
},
{ {
"chain": "sepolia", "chain": "sepolia",
"client": "nitro", "client": "nitro",
@@ -791,6 +876,22 @@
"arbitrum-sepolia-nitro-erigon-pruned-trace" "arbitrum-sepolia-nitro-erigon-pruned-trace"
] ]
}, },
{
"chain": "testnet",
"client": "arc",
"compose_file": "arc/arc/arc-testnet-arc-full",
"features": [],
"network": "arc",
"node": "malachite",
"relay": null,
"stack": null,
"type": "full",
"volumes": [
"arc-testnet-arc-full-consensus",
"arc-testnet-arc-full-execution",
"arc-testnet-arc-full-sockets"
]
},
{ {
"chain": "fuji", "chain": "fuji",
"client": "go", "client": "go",
@@ -1640,6 +1741,35 @@
"core-pigeon-core-pruned-pebble-path" "core-pigeon-core-pruned-pebble-path"
] ]
}, },
{
"chain": "mainnet",
"client": "gaiad",
"compose_file": "cosmos/gaiad/cosmos-mainnet-gaiad-pruned",
"features": [],
"network": "cosmos",
"node": null,
"relay": null,
"stack": null,
"type": "pruned",
"volumes": [
"cosmos-mainnet-gaiad-pruned"
]
},
{
"chain": "mainnet",
"client": "cronos",
"compose_file": "cronos/cronos/cronos-mainnet-cronos-pruned",
"features": [],
"network": "cronos",
"node": "config",
"relay": null,
"stack": null,
"type": "pruned",
"volumes": [
"cronos-mainnet-cronos-pruned",
"cronos-mainnet-cronos-pruned_config"
]
},
{ {
"chain": "zkevm-mainnet", "chain": "zkevm-mainnet",
"client": "external-node", "client": "external-node",
@@ -3511,6 +3641,25 @@
"metis-andromeda-sepolia-l2geth-archive-leveldb-hash_dtl" "metis-andromeda-sepolia-l2geth-archive-leveldb-hash_dtl"
] ]
}, },
{
"chain": "mainnet",
"client": "l2geth",
"compose_file": "morph/l2geth/morph-mainnet-l2geth-archive-leveldb-hash-mpt",
"features": [
"hash",
"leveldb",
"mpt"
],
"network": "morph",
"node": "morph",
"relay": null,
"stack": null,
"type": "archive",
"volumes": [
"morph-mainnet-l2geth-archive-leveldb-hash-mpt",
"morph-mainnet-l2geth-archive-leveldb-hash-mpt_morph"
]
},
{ {
"chain": "mainnet", "chain": "mainnet",
"client": "erigon", "client": "erigon",
@@ -4531,6 +4680,23 @@
"celo-sepolia-op-geth-pruned-pebble-path_eigenda-proxy" "celo-sepolia-op-geth-pruned-pebble-path_eigenda-proxy"
] ]
}, },
{
"chain": "mainnet",
"client": "geth",
"compose_file": "op/geth/doma-mainnet-op-geth-pruned-pebble-path",
"features": [
"path",
"pebble"
],
"network": "doma",
"node": "node",
"relay": "op-alt",
"stack": "op",
"type": "pruned",
"volumes": [
"doma-mainnet-op-geth-pruned-pebble-path"
]
},
{ {
"chain": "mainnet", "chain": "mainnet",
"client": "geth", "client": "geth",
@@ -6126,6 +6292,198 @@
"base-sepolia-op-reth-pruned-trace" "base-sepolia-op-reth-pruned-trace"
] ]
}, },
{
"chain": "sepolia",
"client": "reth",
"compose_file": "op/reth/bob-sepolia-op-reth-archive-trace",
"features": [
"trace"
],
"network": "bob",
"node": "node",
"relay": null,
"stack": "op",
"type": "archive",
"volumes": [
"bob-sepolia-op-reth-archive-trace"
]
},
{
"chain": "sepolia",
"client": "reth",
"compose_file": "op/reth/bob-sepolia-op-reth-minimal-trace",
"features": [
"trace"
],
"network": "bob",
"node": "node",
"relay": null,
"stack": "op",
"type": "minimal",
"volumes": [
"bob-sepolia-op-reth-minimal-trace"
]
},
{
"chain": "sepolia",
"client": "reth",
"compose_file": "op/reth/bob-sepolia-op-reth-pruned-trace",
"features": [
"trace"
],
"network": "bob",
"node": "node",
"relay": null,
"stack": "op",
"type": "pruned",
"volumes": [
"bob-sepolia-op-reth-pruned-trace"
]
},
{
"chain": "mainnet",
"client": "reth",
"compose_file": "op/reth/boba-mainnet-op-reth-pruned-trace",
"features": [
"trace"
],
"network": "boba",
"node": "node",
"relay": null,
"stack": "op",
"type": "pruned",
"volumes": [
"boba-mainnet-op-reth-pruned-trace"
]
},
{
"chain": "testnet",
"client": "reth",
"compose_file": "op/reth/doma-testnet-op-reth-pruned-trace",
"features": [
"trace"
],
"network": "doma",
"node": "node",
"relay": "op-alt",
"stack": "op",
"type": "pruned",
"volumes": [
"doma-testnet-op-reth-pruned-trace"
]
},
{
"chain": "mainnet",
"client": "reth",
"compose_file": "op/reth/hashkeychain-mainnet-op-reth-pruned-trace",
"features": [
"trace"
],
"network": "hashkeychain",
"node": "node",
"relay": null,
"stack": "op",
"type": "pruned",
"volumes": [
"hashkeychain-mainnet-op-reth-pruned-trace"
]
},
{
"chain": "testnet",
"client": "reth",
"compose_file": "op/reth/hashkeychain-testnet-op-reth-pruned-trace",
"features": [
"trace"
],
"network": "hashkeychain",
"node": "node",
"relay": null,
"stack": "op",
"type": "pruned",
"volumes": [
"hashkeychain-testnet-op-reth-pruned-trace"
]
},
{
"chain": "sepolia",
"client": "reth",
"compose_file": "op/reth/ink-sepolia-op-reth-archive-trace",
"features": [
"trace"
],
"network": "ink",
"node": "node",
"relay": null,
"stack": "op",
"type": "archive",
"volumes": [
"ink-sepolia-op-reth-archive-trace"
]
},
{
"chain": "sepolia",
"client": "reth",
"compose_file": "op/reth/ink-sepolia-op-reth-minimal-trace",
"features": [
"trace"
],
"network": "ink",
"node": "node",
"relay": null,
"stack": "op",
"type": "minimal",
"volumes": [
"ink-sepolia-op-reth-minimal-trace"
]
},
{
"chain": "sepolia",
"client": "reth",
"compose_file": "op/reth/ink-sepolia-op-reth-pruned-trace",
"features": [
"trace"
],
"network": "ink",
"node": "node",
"relay": null,
"stack": "op",
"type": "pruned",
"volumes": [
"ink-sepolia-op-reth-pruned-trace"
]
},
{
"chain": "mainnet",
"client": "reth",
"compose_file": "op/reth/katana-mainnet-op-reth-archive-trace",
"features": [
"trace"
],
"network": "katana",
"node": "node",
"relay": null,
"stack": "op",
"type": "archive",
"volumes": [
"katana-mainnet-op-reth-archive-trace"
]
},
{
"chain": "mainnet",
"client": "reth",
"compose_file": "op/reth/katana-mainnet-op-reth-pruned-trace",
"features": [
"trace"
],
"network": "katana",
"node": "node",
"relay": null,
"stack": "op",
"type": "pruned",
"volumes": [
"katana-mainnet-op-reth-pruned-trace"
]
},
{ {
"chain": "mainnet", "chain": "mainnet",
"client": "reth", "client": "reth",
@@ -6254,6 +6612,57 @@
"op-sepolia-op-reth-pruned-trace" "op-sepolia-op-reth-pruned-trace"
] ]
}, },
{
"chain": "mainnet",
"client": "reth",
"compose_file": "op/reth/ronin-mainnet-op-reth-archive-trace",
"features": [
"trace"
],
"network": "ronin",
"node": "node",
"relay": "eigenda-proxy",
"stack": "op",
"type": "archive",
"volumes": [
"ronin-mainnet-op-reth-archive-trace",
"ronin-mainnet-op-reth-archive-trace_eigenda-proxy"
]
},
{
"chain": "saigon",
"client": "reth",
"compose_file": "op/reth/ronin-saigon-op-reth-archive-trace",
"features": [
"trace"
],
"network": "ronin",
"node": "node",
"relay": "eigenda-proxy",
"stack": "op",
"type": "archive",
"volumes": [
"ronin-saigon-op-reth-archive-trace",
"ronin-saigon-op-reth-archive-trace_eigenda-proxy"
]
},
{
"chain": "saigon",
"client": "reth",
"compose_file": "op/reth/ronin-saigon-op-reth-pruned-trace",
"features": [
"trace"
],
"network": "ronin",
"node": "node",
"relay": "eigenda-proxy",
"stack": "op",
"type": "pruned",
"volumes": [
"ronin-saigon-op-reth-pruned-trace",
"ronin-saigon-op-reth-pruned-trace_eigenda-proxy"
]
},
{ {
"chain": "mainnet", "chain": "mainnet",
"client": "reth", "client": "reth",
@@ -6318,6 +6727,102 @@
"soneium-minato-sepolia-op-reth-pruned-trace" "soneium-minato-sepolia-op-reth-pruned-trace"
] ]
}, },
{
"chain": "sepolia",
"client": "reth",
"compose_file": "op/reth/superseed-sepolia-op-reth-pruned-trace",
"features": [
"trace"
],
"network": "superseed",
"node": "node",
"relay": null,
"stack": "op",
"type": "pruned",
"volumes": [
"superseed-sepolia-op-reth-pruned-trace"
]
},
{
"chain": "mainnet",
"client": "reth",
"compose_file": "op/reth/unichain-mainnet-op-reth-pruned-trace",
"features": [
"trace"
],
"network": "unichain",
"node": "node",
"relay": null,
"stack": "op",
"type": "pruned",
"volumes": [
"unichain-mainnet-op-reth-pruned-trace"
]
},
{
"chain": "sepolia",
"client": "reth",
"compose_file": "op/reth/unichain-sepolia-op-reth-pruned-trace",
"features": [
"trace"
],
"network": "unichain",
"node": "node",
"relay": null,
"stack": "op",
"type": "pruned",
"volumes": [
"unichain-sepolia-op-reth-pruned-trace"
]
},
{
"chain": "sepolia",
"client": "reth",
"compose_file": "op/reth/worldchain-sepolia-op-reth-archive-trace",
"features": [
"trace"
],
"network": "worldchain",
"node": "node",
"relay": null,
"stack": "op",
"type": "archive",
"volumes": [
"worldchain-sepolia-op-reth-archive-trace"
]
},
{
"chain": "sepolia",
"client": "reth",
"compose_file": "op/reth/worldchain-sepolia-op-reth-minimal-trace",
"features": [
"trace"
],
"network": "worldchain",
"node": "node",
"relay": null,
"stack": "op",
"type": "minimal",
"volumes": [
"worldchain-sepolia-op-reth-minimal-trace"
]
},
{
"chain": "sepolia",
"client": "reth",
"compose_file": "op/reth/worldchain-sepolia-op-reth-pruned-trace",
"features": [
"trace"
],
"network": "worldchain",
"node": "node",
"relay": null,
"stack": "op",
"type": "pruned",
"volumes": [
"worldchain-sepolia-op-reth-pruned-trace"
]
},
{ {
"chain": "mainnet", "chain": "mainnet",
"client": "reth", "client": "reth",
@@ -6334,22 +6839,6 @@
"xlayer-mainnet-op-reth-archive-trace" "xlayer-mainnet-op-reth-archive-trace"
] ]
}, },
{
"chain": "mainnet",
"client": "reth",
"compose_file": "op/reth/xlayer-mainnet-op-reth-pruned-trace",
"features": [
"trace"
],
"network": "xlayer",
"node": "node",
"relay": null,
"stack": "op",
"type": "pruned",
"volumes": [
"xlayer-mainnet-op-reth-pruned-trace"
]
},
{ {
"chain": "testnet", "chain": "testnet",
"client": "reth", "client": "reth",
@@ -6366,22 +6855,6 @@
"xlayer-testnet-op-reth-archive-trace" "xlayer-testnet-op-reth-archive-trace"
] ]
}, },
{
"chain": "testnet",
"client": "reth",
"compose_file": "op/reth/xlayer-testnet-op-reth-pruned-trace",
"features": [
"trace"
],
"network": "xlayer",
"node": "node",
"relay": null,
"stack": "op",
"type": "pruned",
"volumes": [
"xlayer-testnet-op-reth-pruned-trace"
]
},
{ {
"chain": "amoy", "chain": "amoy",
"client": "bor", "client": "bor",
@@ -6874,6 +7347,42 @@
"sei-testnet-sei-pruned" "sei-testnet-sei-pruned"
] ]
}, },
{
"chain": "mainnet",
"client": "bor",
"compose_file": "shibarium/bor/shibarium-mainnet-bor-archive-pebble-path",
"features": [
"path",
"pebble"
],
"network": "shibarium",
"node": "heimdall",
"relay": null,
"stack": null,
"type": "archive",
"volumes": [
"shibarium-mainnet-bor-archive-pebble-path",
"shibarium-mainnet-heimdall"
]
},
{
"chain": "mainnet",
"client": "bor",
"compose_file": "shibarium/bor/shibarium-mainnet-bor-pruned-pebble-path",
"features": [
"path",
"pebble"
],
"network": "shibarium",
"node": "heimdall",
"relay": null,
"stack": null,
"type": "pruned",
"volumes": [
"shibarium-mainnet-bor-pruned-pebble-path",
"shibarium-mainnet-heimdall"
]
},
{ {
"chain": "mainnet", "chain": "mainnet",
"client": "agave", "client": "agave",

View File

@@ -70,7 +70,7 @@ services:
- --maxpeers=50 - --maxpeers=50
- --nat=extip:${IP} - --nat=extip:${IP}
- --port=12384 - --port=12384
- --rpc.gascap=0 - --rpc.gascap=600000000
- --rpc.txfeecap=0 - --rpc.txfeecap=0
- --state.scheme=path - --state.scheme=path
- --syncmode=snap - --syncmode=snap

View File

@@ -70,7 +70,7 @@ services:
- --maxpeers=50 - --maxpeers=50
- --nat=extip:${IP} - --nat=extip:${IP}
- --port=14234 - --port=14234
- --rpc.gascap=0 - --rpc.gascap=600000000
- --rpc.txfeecap=0 - --rpc.txfeecap=0
- --state.scheme=hash - --state.scheme=hash
- --syncmode=full - --syncmode=full

View File

@@ -70,7 +70,7 @@ services:
- --maxpeers=50 - --maxpeers=50
- --nat=extip:${IP} - --nat=extip:${IP}
- --port=11169 - --port=11169
- --rpc.gascap=0 - --rpc.gascap=600000000
- --rpc.txfeecap=0 - --rpc.txfeecap=0
- --state.scheme=hash - --state.scheme=hash
- --syncmode=full - --syncmode=full

View File

@@ -70,7 +70,7 @@ services:
- --nat=extip:${IP} - --nat=extip:${IP}
- --pigeon - --pigeon
- --port=14478 - --port=14478
- --rpc.gascap=0 - --rpc.gascap=600000000
- --rpc.txfeecap=0 - --rpc.txfeecap=0
- --state.scheme=path - --state.scheme=path
- --syncmode=snap - --syncmode=snap

View File

@@ -0,0 +1,11 @@
ARG CL_IMAGE
ARG CL_VERSION
FROM ${CL_IMAGE}:${CL_VERSION}
# Layer the shared CometBFT bootstrap lib + the chain init.sh onto the upstream
# cosmos binary image (alpine-based, has sh+apk; runs nonroot by default — the compose
# sets user: root so init.sh can apk-add curl and write the /root home).
USER root
COPY ./scripts/cometbft-common.sh /usr/local/bin/cometbft-common.sh
COPY ./scripts/init.sh /usr/local/bin/init.sh
RUN chmod +x /usr/local/bin/init.sh /usr/local/bin/cometbft-common.sh
ENTRYPOINT ["init.sh"]

View File

@@ -0,0 +1,127 @@
---
x-logging-defaults: &logging-defaults
driver: json-file
options:
max-size: "10m"
max-file: "3"
# Usage:
#
# mkdir rpc && cd rpc
#
# git init
# git remote add origin https://github.com/StakeSquid/ethereum-rpc-docker.git
# git fetch origin vibe
# git checkout origin/vibe
#
# docker run --rm alpine sh -c "printf '0x'; head -c32 /dev/urandom | xxd -p -c 64" > .jwtsecret
#
# env
# ...
# IP=$(curl ipinfo.io/ip)
# DOMAIN=${IP}.traefik.me
# COMPOSE_FILE=base.yml:rpc.yml:cosmos/gaiad/cosmos-mainnet-gaiad-pruned.yml
#
# docker compose up -d
#
# curl -X POST https://${IP}.traefik.me/cosmos-mainnet-pruned \
# -H "Content-Type: application/json" \
# --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
services:
cosmos-mainnet-pruned:
build:
context: ./cosmos
dockerfile: cometbft.Dockerfile
args:
CL_IMAGE: ${COSMOS_GAIAD_IMAGE:-ghcr.io/cosmos/gaia}
CL_VERSION: ${COSMOS_MAINNET_GAIAD_VERSION:-v27.4.0}
sysctls:
# TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
net.ipv4.tcp_no_metrics_save: 1 # Disable metrics cache
net.ipv4.tcp_rmem: 4096 87380 16777216 # Increase TCP read buffers
net.ipv4.tcp_wmem: 4096 87380 16777216 # Increase TCP write buffers
net.core.somaxconn: 32768 # Higher connection queue
# Memory/Connection Management
# net.core.netdev_max_backlog: 50000 # Increase network buffer
net.ipv4.tcp_max_syn_backlog: 30000 # More SYN requests
net.ipv4.tcp_max_tw_buckets: 2000000 # Allow more TIME_WAIT sockets
ulimits:
nofile: 1048576 # Max open files (for RPC/WS connections)
user: root
ports:
- 12554:12554
- 12554:12554/udp
expose:
- 26657
- 26660
- 9090
- 1317
environment:
- CHAIN_ID=cosmoshub-4
- GENESIS_URL=https://github.com/cosmos/mainnet/raw/master/genesis/genesis.cosmoshub-4.json.gz
- IP=${IP}
- MIN_GAS=0.005uatom
- MONIKER=d${DOMAIN:-local}
- P2P_PORT=12554
- PERSISTENT_PEERS=a7f14a48cd97c0eae7833849ccdf4e9418622c56@65.108.128.201:14956,37dfe1ec33e9f88f378a61a32462d57d2baa5e74@65.108.99.140:26656,f86d297a28da1a2b186583daf0e229c2b1449414@144.76.217.227:26656,66ca3161c5532da890815e40826ddbbbe2cb7f6c@176.9.101.44:26656
- STATESYNC_RPC=https://cosmos-rpc.polkachu.com:443
- WASM_SNAPSHOT_URL=https://snapshots.polkachu.com/wasm/cosmos/cosmos_wasmonly.tar.lz4
restart: unless-stopped
stop_grace_period: 5m
networks:
- chains
volumes:
- ${COSMOS_MAINNET_GAIAD_PRUNED_DATA:-cosmos-mainnet-gaiad-pruned}:/root/.gaia
- /slowdisk:/slowdisk
logging: *logging-defaults
labels:
- prometheus-scrape.enabled=true
- prometheus-scrape.port=26660
- prometheus-scrape.path=/metrics
- traefik.enable=true
- traefik.http.middlewares.cosmos-mainnet-gaiad-pruned-stripprefix.stripprefix.prefixes=/cosmos-mainnet-pruned
- traefik.http.services.cosmos-mainnet-gaiad-pruned.loadbalancer.server.port=26657
- ${NO_SSL:-traefik.http.routers.cosmos-mainnet-gaiad-pruned.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.cosmos-mainnet-gaiad-pruned.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.cosmos-mainnet-gaiad-pruned.rule=Host(`$DOMAIN`) && (Path(`/cosmos-mainnet-pruned`) || Path(`/cosmos-mainnet-pruned/`))}
- ${NO_SSL:+traefik.http.routers.cosmos-mainnet-gaiad-pruned.rule=Path(`/cosmos-mainnet-pruned`) || Path(`/cosmos-mainnet-pruned/`)}
- traefik.http.routers.cosmos-mainnet-gaiad-pruned.middlewares=cosmos-mainnet-gaiad-pruned-stripprefix, ipallowlist
- traefik.http.routers.cosmos-mainnet-gaiad-pruned.priority=50 # gets any request that is not GET with UPGRADE header
- traefik.http.routers.cosmos-mainnet-gaiad-pruned-ws.priority=100 # answers GET requests first
- traefik.http.middlewares.cosmos-mainnet-gaiad-pruned-set-ws-path.replacepath.path=/websocket
- traefik.http.services.cosmos-mainnet-gaiad-pruned-ws.loadbalancer.server.port=26657
- traefik.http.routers.cosmos-mainnet-gaiad-pruned-ws.service=cosmos-mainnet-gaiad-pruned-ws
- traefik.http.routers.cosmos-mainnet-gaiad-pruned.service=cosmos-mainnet-gaiad-pruned
- ${NO_SSL:-traefik.http.routers.cosmos-mainnet-gaiad-pruned-ws.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.cosmos-mainnet-gaiad-pruned-ws.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.cosmos-mainnet-gaiad-pruned-ws.rule=Host(`$DOMAIN`) && (Path(`/cosmos-mainnet-pruned`) || Path(`/cosmos-mainnet-pruned/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- ${NO_SSL:+traefik.http.routers.cosmos-mainnet-gaiad-pruned-ws.rule=(Path(`/cosmos-mainnet-pruned`) || Path(`/cosmos-mainnet-pruned/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- traefik.http.routers.cosmos-mainnet-gaiad-pruned-ws.middlewares=cosmos-mainnet-gaiad-pruned-stripprefix, cosmos-mainnet-gaiad-pruned-set-ws-path, ipallowlist
volumes:
cosmos-mainnet-gaiad-pruned:
x-upstreams:
- id: $${ID}
labels:
provider: $${PROVIDER}
connection:
generic:
rpc:
url: $${RPC_URL}
ws:
frameSize: 20Mb
msgSize: 50Mb
url: $${WS_URL}
chain: cosmos-hub
method-groups:
enabled:
- debug
- filter
methods:
disabled:
enabled:
- name: txpool_content # TODO: should be disabled for rollup nodes
...

View File

@@ -0,0 +1,223 @@
#!/bin/sh
# cometbft-common.sh — reusable CometBFT-node bootstrap helpers (family C).
#
# Source this from a chain-specific init.sh. It encapsulates the operations every
# CometBFT-consensus node needs (init, fetch config artifacts, patch config.toml /
# app.toml, seed priv_validator_state), extracted verbatim from the proven berachain
# beacon-kit entrypoint so callers inherit known-good behavior.
#
# Each function takes explicit arguments (paths/values) — it is binary-agnostic. The
# caller owns the binary name, the `<binary> init` invocation, the artifact URLs, and
# the final `exec <binary> start ...`. EL-driven chains (beacon-kit, morph) also call
# the JWT / engine-dial helpers; pure-consensus chains (gaiad) skip them.
#
# Conventions: POSIX sh (alpine). Config dir is conventionally $HOME_DIR/config.
# Used by: morph-node, gaiad (cosmos batch), and any future family-C chain.
# beacon-kit (berachain) keeps its own bespoke init.sh on purpose — do not retrofit it.
set -e
ct_log() { echo "[cometbft-init] $*"; }
# Ensure curl exists (alpine base images often omit it). Idempotent.
ct_require_curl() {
if ! command -v curl >/dev/null 2>&1; then
ct_log "installing curl"
apk add --no-cache curl
fi
}
# ct_fetch URL DEST [required]
# Download URL -> DEST. If the 3rd arg is "required", a failure is fatal;
# otherwise a missing/failed fetch is logged and skipped (returns 0).
ct_fetch() {
_url="$1"; _dest="$2"; _req="${3:-optional}"
[ -n "$_url" ] || { [ "$_req" = required ] && { ct_log "FATAL: empty URL for $_dest"; exit 1; }; return 0; }
if curl -fsSL "$_url" -o "$_dest"; then
ct_log "fetched $_url -> $_dest"
else
if [ "$_req" = required ]; then
ct_log "FATAL: failed to fetch required $_url"; exit 1
fi
ct_log "skip: could not fetch optional $_url"
fi
}
# ct_patch_p2p CONFIG_TOML IP P2P_PORT
# Bind p2p to 0.0.0.0:PORT and advertise IP:PORT (only within the [p2p] section).
ct_patch_p2p() {
_cfg="$1"; _ip="$2"; _port="$3"
[ -f "$_cfg" ] || { ct_log "patch_p2p: $_cfg missing, skipping"; return 0; }
_laddr="tcp:\\/\\/0\\.0\\.0\\.0\\:${_port}"
sed -i "/^\[p2p\]/,/^\[/{s|^laddr = .*|laddr = \"$_laddr\"|}" "$_cfg"
sed -i "/^\[p2p\]/,/^\[/{s|^external_address = .*|external_address = \"${_ip}:${_port}\"|}" "$_cfg"
}
# ct_merge_seeds CONFIG_TOML CONFIGURED_SEEDS [SEEDS_URL]
# Merge operator-configured seeds with an optional official seed list (1 entry per
# line, first line skipped like the berachain cl-seeds.txt header), dedupe, write.
ct_merge_seeds() {
_cfg="$1"; _seeds="$2"; _url="$3"
[ -f "$_cfg" ] || return 0
if [ -n "$_url" ]; then
_official=$(curl -f -s "$_url" | tail -n +2 | tr '\n' ',' | sed 's/,$//' || true)
if [ -n "$_official" ]; then
ct_log "merging official seeds from $_url"
_seeds=$(echo "${_seeds},${_official}" | tr ',' '\n' | sed '/^$/d' | sort -u | paste -sd,)
else
ct_log "no official seeds fetched from $_url (continuing with configured)"
fi
fi
if [ -n "$_seeds" ]; then
sed -i "s/^seeds = \".*\"/seeds = \"${_seeds}\"/" "$_cfg"
fi
}
# ct_set_persistent_peers CONFIG_TOML PEERS
# Handles both cometbft-classic `persistent_peers` (underscore) and forks that use
# `persistent-peers` (hyphen, e.g. sei) — patches whichever key is present.
ct_set_persistent_peers() {
_cfg="$1"; _peers="$2"
[ -f "$_cfg" ] || return 0
[ -n "$_peers" ] || return 0
sed -i "s/^persistent_peers = \".*\"/persistent_peers = \"${_peers}\"/" "$_cfg"
sed -i "s/^persistent-peers = \".*\"/persistent-peers = \"${_peers}\"/" "$_cfg"
return 0
}
# ct_set_moniker CONFIG_TOML MONIKER
ct_set_moniker() {
_cfg="$1"; _mon="$2"
[ -f "$_cfg" ] || return 0
[ -n "$_mon" ] && sed -i "s/^moniker = \".*\"/moniker = \"$_mon\"/" "$_cfg"
return 0
}
# ct_set_addrbook CONFIG_DIR ADDRBOOK_URL
# Optional: cosmos chains often seed an addrbook.json for faster peer discovery.
ct_set_addrbook() {
_dir="$1"; _url="$2"
[ -n "$_url" ] || return 0
ct_fetch "$_url" "$_dir/addrbook.json" optional
}
# ct_write_jwt CONFIG_DIR [JWT_SRC]
# EL-driven chains: copy the shared engine JWT (default /jwtsecret) into the config
# dir as jwt.hex so the CL can authenticate to the EL engine API.
ct_write_jwt() {
_dir="$1"; _src="${2:-/jwtsecret}"
[ -f "$_src" ] || { ct_log "write_jwt: $_src missing, skipping"; return 0; }
cat "$_src" > "$_dir/jwt.hex"
}
# ct_set_rpc_dial_url APP_TOML AUTH_RPC
# beacon-kit / app.toml-style EL engine endpoint (e.g. http://<el>:8551).
ct_set_rpc_dial_url() {
_app="$1"; _rpc="$2"
[ -f "$_app" ] || return 0
[ -n "$_rpc" ] && sed -i "s|^rpc-dial-url = \".*\"|rpc-dial-url = \"$_rpc\"|" "$_app"
return 0
}
# ct_seed_priv_validator_state HOME_DIR
# Ensure data/priv_validator_state.json exists (cometbft refuses to start without it
# when one is present in config/). Mirrors the berachain init.sh behavior.
ct_seed_priv_validator_state() {
_home="$1"
if [ -e "$_home/config/priv_validator_state.json" ] && [ ! -e "$_home/data/priv_validator_state.json" ]; then
mkdir -p "$_home/data"
cp "$_home/config/priv_validator_state.json" "$_home/data/priv_validator_state.json"
fi
return 0
}
# ct_apk PKG...
# Install alpine packages idempotently (most cosmos init scripts need curl, some jq).
ct_apk() {
apk add --no-cache "$@"
}
# ct_localize_home CONFIG_DIR
# Rewrite `~/` to `/root/` in config.toml + app.toml. Cosmos `init` writes home-relative
# paths; the container runs as root with a static home, so make paths absolute.
ct_localize_home() {
_dir="$1"
[ -f "$_dir/config.toml" ] && sed -i 's|~/|/root/|g' "$_dir/config.toml"
[ -f "$_dir/app.toml" ] && sed -i 's|~/|/root/|g' "$_dir/app.toml"
return 0
}
# ct_set_min_gas_prices APP_TOML PRICE
# Cosmos chains reject txs (and sometimes refuse to start) with an empty
# minimum-gas-prices. PRICE e.g. "0.01usei", "0.0025uatom", "0.01hqq".
ct_set_min_gas_prices() {
_app="$1"; _price="$2"
[ -f "$_app" ] || return 0
[ -n "$_price" ] || return 0
sed -i "s/minimum-gas-prices = \"\"/minimum-gas-prices = \"${_price}\"/g" "$_app"
return 0
}
# ct_configure_statesync CONFIG_TOML RPC_SERVERS [TRUST_OFFSET]
# Enable cometbft state-sync so a fresh node bootstraps near chainhead instead of
# replaying from genesis — the single biggest lever for "can't keep it at chainhead"
# chains. RPC_SERVERS = comma list of trusted RPC endpoints (>=2 recommended; a single
# endpoint is duplicated). TRUST_OFFSET = blocks below head to trust (default 2000).
# Requires jq + curl. No-op (logged) if head height can't be fetched.
ct_configure_statesync() {
_cfg="$1"; _rpc="$2"; _offset="${3:-2000}"
[ -f "$_cfg" ] || return 0
# NEVER re-arm statesync on a node that already has application state (a restored
# snapshot or a prior sync). Re-statesyncing over it leaves a broken/partial datadir and,
# for wasm chains, drops the wasm files -> startup panic. _cfg is $HOME/config/config.toml,
# so application state lives at $HOME/data/application.db.
_home=$(dirname "$(dirname "$_cfg")")
if [ -e "$_home/data/application.db" ]; then
ct_log "statesync: existing data dir, skipping"
return 0
fi
[ -n "$_rpc" ] || { ct_log "statesync: no RPC servers given, skipping"; return 0; }
_primary=$(echo "$_rpc" | cut -d, -f1)
_latest=$(curl -s "$_primary/block" | jq -r '.result.block.header.height // .block.header.height' 2>/dev/null || true)
if [ -z "$_latest" ] || [ "$_latest" = null ]; then
ct_log "statesync: could not read head height from $_primary, skipping"; return 0
fi
_trust_h=$((_latest - _offset))
_trust_hash=$(curl -s "$_primary/block?height=$_trust_h" | jq -r '.result.block_id.hash // .block_id.hash' 2>/dev/null || true)
[ -n "$_trust_hash" ] && [ "$_trust_hash" != null ] || { ct_log "statesync: no trust hash, skipping"; return 0; }
# second server defaults to the first (cometbft wants >=2 for light-client cross-check)
echo "$_rpc" | grep -q ',' || _rpc="$_rpc,$_rpc"
ct_log "statesync: enable trust_height=$_trust_h trust_hash=$_trust_hash"
# Patch ONLY the [statesync] section. CometBFT config.toml uses underscore keys
# (rpc_servers/trust_height/trust_hash); tolerate hyphen variants with [_-].
sed -i.bak -E "/^\[statesync\]/,/^\[/{
s|^([[:space:]]*enable[[:space:]]*=[[:space:]]*).*|\1true|
s|^([[:space:]]*rpc[_-]servers[[:space:]]*=[[:space:]]*).*|\1\"$_rpc\"|
s|^([[:space:]]*trust[_-]height[[:space:]]*=[[:space:]]*).*|\1$_trust_h|
s|^([[:space:]]*trust[_-]hash[[:space:]]*=[[:space:]]*).*|\1\"$_trust_hash\"|
}" "$_cfg"
return 0
}
# ct_ensure_wasm HOME_DIR WASM_SNAPSHOT_URL
# CosmWasm + IBC 08-wasm bytecode are FILES on disk that state-sync does NOT restore, so
# a state-synced wasm chain panics at startup ("wasmlckeeper failed initialize pinned codes
# / Error opening Wasm file"). Seed them from a wasm-only snapshot (e.g. polkachu
# cosmos_wasmonly.tar.lz4) when the wasm dir is missing/empty. No-op if URL unset or wasm
# already present. Best-effort (logs on failure); the fully robust path for wasm chains is a
# FULL snapshot restore. Requires lz4 + tar (installed here).
ct_ensure_wasm() {
_home="$1"; _url="$2"
[ -n "$_url" ] || return 0
if [ -d "$_home/wasm" ] && [ -n "$(ls -A "$_home/wasm" 2>/dev/null)" ]; then
return 0 # wasm already present
fi
ct_log "wasm: empty, fetching snapshot $_url"
ct_apk lz4 tar
if curl -sL "$_url" | lz4 -dc | tar -xf - -C "$_home"; then
ct_log "wasm: extracted into $_home"
else
ct_log "WARN wasm: fetch/extract failed ($_url)"
fi
return 0
}

44
cosmos/scripts/init.sh Normal file
View File

@@ -0,0 +1,44 @@
#!/bin/sh
# cosmos-hub (gaiad) entrypoint — family C, pure CometBFT (no EL). Thin: sources the
# shared cometbft-common.sh and orchestrates init + statesync bootstrap + start.
# Genesis replay across ~25 gaia governance upgrades is impractical, so we statesync
# near head with the current binary. Serves CometBFT RPC :26657 (the dshackle upstream).
set -e
. /usr/local/bin/cometbft-common.sh
HOME_DIR="/root/.gaia"
CONFIG_DIR="$HOME_DIR/config"
CHAIN_ID="${CHAIN_ID:-cosmoshub-4}"
GENESIS_URL="${GENESIS_URL:-https://github.com/cosmos/mainnet/raw/master/genesis/genesis.cosmoshub-4.json.gz}"
STATESYNC_RPC="${STATESYNC_RPC:-https://cosmos-rpc.polkachu.com:443}"
MIN_GAS="${MIN_GAS:-0.005uatom}"
MONIKER="${MONIKER:-rpc-node}"
ct_apk curl jq
if gaiad init "$MONIKER" --chain-id "$CHAIN_ID" --home "$HOME_DIR" >/dev/null 2>&1; then
ct_log "fresh init; fetching genesis"
ct_fetch "$GENESIS_URL" "$CONFIG_DIR/genesis.json.gz" required
if gzip -t "$CONFIG_DIR/genesis.json.gz" 2>/dev/null; then
gunzip -f "$CONFIG_DIR/genesis.json.gz"
else
mv "$CONFIG_DIR/genesis.json.gz" "$CONFIG_DIR/genesis.json" # served plain, not gzipped
fi
ct_localize_home "$CONFIG_DIR"
ct_set_min_gas_prices "$CONFIG_DIR/app.toml" "$MIN_GAS"
else
ct_log "already initialized, continuing"
fi
# Serve RPC on all interfaces (dshackle/traefik upstream); default is 127.0.0.1.
sed -i '/^\[rpc\]/,/^\[/{s|^laddr = .*|laddr = "tcp://0.0.0.0:26657"|}' "$CONFIG_DIR/config.toml"
ct_patch_p2p "$CONFIG_DIR/config.toml" "$IP" "${P2P_PORT:-26656}"
ct_merge_seeds "$CONFIG_DIR/config.toml" "$SEEDS"
ct_set_persistent_peers "$CONFIG_DIR/config.toml" "$PERSISTENT_PEERS"
ct_set_moniker "$CONFIG_DIR/config.toml" "$MONIKER"
ct_configure_statesync "$CONFIG_DIR/config.toml" "$STATESYNC_RPC" # internally skips if data/application.db exists
ct_ensure_wasm "$HOME_DIR" "$WASM_SNAPSHOT_URL" # seeds CosmWasm/IBC-08 wasm if missing (statesync omits them)
ct_seed_priv_validator_state "$HOME_DIR"
exec gaiad start --home "$HOME_DIR" --minimum-gas-prices "$MIN_GAS" "$@"

View File

@@ -33,7 +33,7 @@ x-logging-defaults: &logging-defaults
services: services:
cronos-zkevm-mainnet-archive: cronos-zkevm-mainnet-archive:
image: ${CRONOS_ZKEVM_EXTERNAL_NODE_IMAGE:-ghcr.io/cronos-labs/external-node}:${CRONOS_ZKEVM_MAINNET_EXTERNAL_NODE_VERSION:-v29.14.0} image: ${CRONOS_ZKEVM_EXTERNAL_NODE_IMAGE:-ghcr.io/cronos-labs/external-node}:${CRONOS_ZKEVM_MAINNET_EXTERNAL_NODE_VERSION:-v31.0.0}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
@@ -102,8 +102,8 @@ services:
- traefik.http.routers.cronos-zkevm-mainnet-external-node-archive.service=cronos-zkevm-mainnet-external-node-archive - traefik.http.routers.cronos-zkevm-mainnet-external-node-archive.service=cronos-zkevm-mainnet-external-node-archive
- ${NO_SSL:-traefik.http.routers.cronos-zkevm-mainnet-external-node-archive-ws.entrypoints=websecure} - ${NO_SSL:-traefik.http.routers.cronos-zkevm-mainnet-external-node-archive-ws.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.cronos-zkevm-mainnet-external-node-archive-ws.tls.certresolver=myresolver} - ${NO_SSL:-traefik.http.routers.cronos-zkevm-mainnet-external-node-archive-ws.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.cronos-zkevm-mainnet-external-node-archive-ws.rule=Host(`$DOMAIN`) && (Path(`/cronos-zkevm-mainnet-archive`) || Path(`/cronos-zkevm-mainnet-archive/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:-traefik.http.routers.cronos-zkevm-mainnet-external-node-archive-ws.rule=Host(`$DOMAIN`) && (Path(`/cronos-zkevm-mainnet-archive`) || Path(`/cronos-zkevm-mainnet-archive/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- ${NO_SSL:+traefik.http.routers.cronos-zkevm-mainnet-external-node-archive-ws.rule=(Path(`/cronos-zkevm-mainnet-archive`) || Path(`/cronos-zkevm-mainnet-archive/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:+traefik.http.routers.cronos-zkevm-mainnet-external-node-archive-ws.rule=(Path(`/cronos-zkevm-mainnet-archive`) || Path(`/cronos-zkevm-mainnet-archive/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- traefik.http.routers.cronos-zkevm-mainnet-external-node-archive-ws.middlewares=cronos-zkevm-mainnet-external-node-archive-stripprefix, ipallowlist - traefik.http.routers.cronos-zkevm-mainnet-external-node-archive-ws.middlewares=cronos-zkevm-mainnet-external-node-archive-stripprefix, ipallowlist
cronos-zkevm-mainnet-archive-db: cronos-zkevm-mainnet-archive-db:

View File

@@ -33,7 +33,7 @@ x-logging-defaults: &logging-defaults
services: services:
cronos-zkevm-mainnet: cronos-zkevm-mainnet:
image: ${CRONOS_ZKEVM_EXTERNAL_NODE_IMAGE:-ghcr.io/cronos-labs/external-node}:${CRONOS_ZKEVM_MAINNET_EXTERNAL_NODE_VERSION:-v29.14.0} image: ${CRONOS_ZKEVM_EXTERNAL_NODE_IMAGE:-ghcr.io/cronos-labs/external-node}:${CRONOS_ZKEVM_MAINNET_EXTERNAL_NODE_VERSION:-v31.0.0}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
@@ -102,8 +102,8 @@ services:
- traefik.http.routers.cronos-zkevm-mainnet-external-node-pruned.service=cronos-zkevm-mainnet-external-node-pruned - traefik.http.routers.cronos-zkevm-mainnet-external-node-pruned.service=cronos-zkevm-mainnet-external-node-pruned
- ${NO_SSL:-traefik.http.routers.cronos-zkevm-mainnet-external-node-pruned-ws.entrypoints=websecure} - ${NO_SSL:-traefik.http.routers.cronos-zkevm-mainnet-external-node-pruned-ws.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.cronos-zkevm-mainnet-external-node-pruned-ws.tls.certresolver=myresolver} - ${NO_SSL:-traefik.http.routers.cronos-zkevm-mainnet-external-node-pruned-ws.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.cronos-zkevm-mainnet-external-node-pruned-ws.rule=Host(`$DOMAIN`) && (Path(`/cronos-zkevm-mainnet`) || Path(`/cronos-zkevm-mainnet/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:-traefik.http.routers.cronos-zkevm-mainnet-external-node-pruned-ws.rule=Host(`$DOMAIN`) && (Path(`/cronos-zkevm-mainnet`) || Path(`/cronos-zkevm-mainnet/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- ${NO_SSL:+traefik.http.routers.cronos-zkevm-mainnet-external-node-pruned-ws.rule=(Path(`/cronos-zkevm-mainnet`) || Path(`/cronos-zkevm-mainnet/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:+traefik.http.routers.cronos-zkevm-mainnet-external-node-pruned-ws.rule=(Path(`/cronos-zkevm-mainnet`) || Path(`/cronos-zkevm-mainnet/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- traefik.http.routers.cronos-zkevm-mainnet-external-node-pruned-ws.middlewares=cronos-zkevm-mainnet-external-node-pruned-stripprefix, ipallowlist - traefik.http.routers.cronos-zkevm-mainnet-external-node-pruned-ws.middlewares=cronos-zkevm-mainnet-external-node-pruned-stripprefix, ipallowlist
cronos-zkevm-mainnet-db: cronos-zkevm-mainnet-db:

View File

@@ -33,7 +33,7 @@ x-logging-defaults: &logging-defaults
services: services:
cronos-zkevm-testnet-archive: cronos-zkevm-testnet-archive:
image: ${CRONOS_ZKEVM_EXTERNAL_NODE_IMAGE:-ghcr.io/cronos-labs/external-node}:${CRONOS_ZKEVM_TESTNET_EXTERNAL_NODE_VERSION:-v29.14.0} image: ${CRONOS_ZKEVM_EXTERNAL_NODE_IMAGE:-ghcr.io/cronos-labs/external-node}:${CRONOS_ZKEVM_TESTNET_EXTERNAL_NODE_VERSION:-v31.0.0}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
@@ -102,8 +102,8 @@ services:
- traefik.http.routers.cronos-zkevm-testnet-external-node-archive.service=cronos-zkevm-testnet-external-node-archive - traefik.http.routers.cronos-zkevm-testnet-external-node-archive.service=cronos-zkevm-testnet-external-node-archive
- ${NO_SSL:-traefik.http.routers.cronos-zkevm-testnet-external-node-archive-ws.entrypoints=websecure} - ${NO_SSL:-traefik.http.routers.cronos-zkevm-testnet-external-node-archive-ws.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.cronos-zkevm-testnet-external-node-archive-ws.tls.certresolver=myresolver} - ${NO_SSL:-traefik.http.routers.cronos-zkevm-testnet-external-node-archive-ws.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.cronos-zkevm-testnet-external-node-archive-ws.rule=Host(`$DOMAIN`) && (Path(`/cronos-zkevm-testnet-archive`) || Path(`/cronos-zkevm-testnet-archive/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:-traefik.http.routers.cronos-zkevm-testnet-external-node-archive-ws.rule=Host(`$DOMAIN`) && (Path(`/cronos-zkevm-testnet-archive`) || Path(`/cronos-zkevm-testnet-archive/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- ${NO_SSL:+traefik.http.routers.cronos-zkevm-testnet-external-node-archive-ws.rule=(Path(`/cronos-zkevm-testnet-archive`) || Path(`/cronos-zkevm-testnet-archive/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:+traefik.http.routers.cronos-zkevm-testnet-external-node-archive-ws.rule=(Path(`/cronos-zkevm-testnet-archive`) || Path(`/cronos-zkevm-testnet-archive/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- traefik.http.routers.cronos-zkevm-testnet-external-node-archive-ws.middlewares=cronos-zkevm-testnet-external-node-archive-stripprefix, ipallowlist - traefik.http.routers.cronos-zkevm-testnet-external-node-archive-ws.middlewares=cronos-zkevm-testnet-external-node-archive-stripprefix, ipallowlist
cronos-zkevm-testnet-archive-db: cronos-zkevm-testnet-archive-db:

View File

@@ -33,7 +33,7 @@ x-logging-defaults: &logging-defaults
services: services:
cronos-zkevm-testnet: cronos-zkevm-testnet:
image: ${CRONOS_ZKEVM_EXTERNAL_NODE_IMAGE:-ghcr.io/cronos-labs/external-node}:${CRONOS_ZKEVM_TESTNET_EXTERNAL_NODE_VERSION:-v29.14.0} image: ${CRONOS_ZKEVM_EXTERNAL_NODE_IMAGE:-ghcr.io/cronos-labs/external-node}:${CRONOS_ZKEVM_TESTNET_EXTERNAL_NODE_VERSION:-v31.0.0}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
@@ -102,8 +102,8 @@ services:
- traefik.http.routers.cronos-zkevm-testnet-external-node-pruned.service=cronos-zkevm-testnet-external-node-pruned - traefik.http.routers.cronos-zkevm-testnet-external-node-pruned.service=cronos-zkevm-testnet-external-node-pruned
- ${NO_SSL:-traefik.http.routers.cronos-zkevm-testnet-external-node-pruned-ws.entrypoints=websecure} - ${NO_SSL:-traefik.http.routers.cronos-zkevm-testnet-external-node-pruned-ws.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.cronos-zkevm-testnet-external-node-pruned-ws.tls.certresolver=myresolver} - ${NO_SSL:-traefik.http.routers.cronos-zkevm-testnet-external-node-pruned-ws.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.cronos-zkevm-testnet-external-node-pruned-ws.rule=Host(`$DOMAIN`) && (Path(`/cronos-zkevm-testnet`) || Path(`/cronos-zkevm-testnet/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:-traefik.http.routers.cronos-zkevm-testnet-external-node-pruned-ws.rule=Host(`$DOMAIN`) && (Path(`/cronos-zkevm-testnet`) || Path(`/cronos-zkevm-testnet/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- ${NO_SSL:+traefik.http.routers.cronos-zkevm-testnet-external-node-pruned-ws.rule=(Path(`/cronos-zkevm-testnet`) || Path(`/cronos-zkevm-testnet/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:+traefik.http.routers.cronos-zkevm-testnet-external-node-pruned-ws.rule=(Path(`/cronos-zkevm-testnet`) || Path(`/cronos-zkevm-testnet/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- traefik.http.routers.cronos-zkevm-testnet-external-node-pruned-ws.middlewares=cronos-zkevm-testnet-external-node-pruned-stripprefix, ipallowlist - traefik.http.routers.cronos-zkevm-testnet-external-node-pruned-ws.middlewares=cronos-zkevm-testnet-external-node-pruned-stripprefix, ipallowlist
cronos-zkevm-testnet-db: cronos-zkevm-testnet-db:

View File

@@ -0,0 +1,11 @@
ARG CRONOS_CRONOS_IMAGE
ARG CRONOS_CRONOS_VERSION
FROM ${CRONOS_CRONOS_IMAGE}:${CRONOS_CRONOS_VERSION}
# Layer the shared CometBFT bootstrap lib + the chain init.sh onto the upstream
# cronos binary image (alpine-based, has sh+apk; runs nonroot by default — the compose
# sets user: root so init.sh can apk-add curl and write the /root home).
USER root
COPY ./scripts/cometbft-common.sh /usr/local/bin/cometbft-common.sh
COPY ./scripts/init.sh /usr/local/bin/init.sh
RUN chmod +x /usr/local/bin/init.sh /usr/local/bin/cometbft-common.sh
ENTRYPOINT ["init.sh"]

View File

@@ -0,0 +1,125 @@
---
x-logging-defaults: &logging-defaults
driver: json-file
options:
max-size: "10m"
max-file: "3"
# Usage:
#
# mkdir rpc && cd rpc
#
# git init
# git remote add origin https://github.com/StakeSquid/ethereum-rpc-docker.git
# git fetch origin vibe
# git checkout origin/vibe
#
# docker run --rm alpine sh -c "printf '0x'; head -c32 /dev/urandom | xxd -p -c 64" > .jwtsecret
#
# env
# ...
# IP=$(curl ipinfo.io/ip)
# DOMAIN=${IP}.traefik.me
# COMPOSE_FILE=base.yml:rpc.yml:cronos/cronos/cronos-mainnet-cronos-pruned.yml
#
# docker compose up -d
#
# curl -X POST https://${IP}.traefik.me/cronos-mainnet \
# -H "Content-Type: application/json" \
# --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
services:
cronos-mainnet:
build:
context: ./cronos
dockerfile: cometbft.Dockerfile
args:
CRONOS_CRONOS_VERSION: ${CRONOS_MAINNET_CRONOS_VERSION:-v1.7.7}
CRONOS_CRONOS_IMAGE: ${CRONOS_MAINNET_CRONOS_IMAGE:-ghcr.io/crypto-org-chain/cronos}
sysctls:
# TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
net.ipv4.tcp_no_metrics_save: 1 # Disable metrics cache
net.ipv4.tcp_rmem: 4096 87380 16777216 # Increase TCP read buffers
net.ipv4.tcp_wmem: 4096 87380 16777216 # Increase TCP write buffers
net.core.somaxconn: 32768 # Higher connection queue
# Memory/Connection Management
# net.core.netdev_max_backlog: 50000 # Increase network buffer
net.ipv4.tcp_max_syn_backlog: 30000 # More SYN requests
net.ipv4.tcp_max_tw_buckets: 2000000 # Allow more TIME_WAIT sockets
ulimits:
nofile: 1048576 # Max open files (for RPC/WS connections)
user: root
ports:
- 10521:10521
- 10521:10521/udp
expose:
- 8545
- 8546
- 6066
- 26657
environment:
- API=eth,txpool,net,debug,web3
- CHAINID=cronosmainnet_25-1
- CHAINNAME=mainnet
- IP=${IP}
- MONIKER=d${DOMAIN:-local}
- P2P_PORT=10521
restart: unless-stopped
stop_grace_period: 5m
networks:
- chains
volumes:
- ${CRONOS_MAINNET_CRONOS_PRUNED_DATA:-cronos-mainnet-cronos-pruned}:/root/.cronos/data
- /slowdisk:/slowdisk
- cronos-mainnet-cronos-pruned_config:/root/.cronos/config
logging: *logging-defaults
labels:
- prometheus-scrape.enabled=true
- prometheus-scrape.port=6066
- prometheus-scrape.path=/metrics
- traefik.enable=true
- traefik.http.middlewares.cronos-mainnet-cronos-pruned-stripprefix.stripprefix.prefixes=/cronos-mainnet
- traefik.http.services.cronos-mainnet-cronos-pruned.loadbalancer.server.port=8545
- ${NO_SSL:-traefik.http.routers.cronos-mainnet-cronos-pruned.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.cronos-mainnet-cronos-pruned.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.cronos-mainnet-cronos-pruned.rule=Host(`$DOMAIN`) && (Path(`/cronos-mainnet`) || Path(`/cronos-mainnet/`))}
- ${NO_SSL:+traefik.http.routers.cronos-mainnet-cronos-pruned.rule=Path(`/cronos-mainnet`) || Path(`/cronos-mainnet/`)}
- traefik.http.routers.cronos-mainnet-cronos-pruned.middlewares=cronos-mainnet-cronos-pruned-stripprefix, ipallowlist
- traefik.http.routers.cronos-mainnet-cronos-pruned.priority=50 # gets any request that is not GET with UPGRADE header
- traefik.http.routers.cronos-mainnet-cronos-pruned-ws.priority=100 # answers GET requests first
- traefik.http.services.cronos-mainnet-cronos-pruned-ws.loadbalancer.server.port=8546
- traefik.http.routers.cronos-mainnet-cronos-pruned-ws.service=cronos-mainnet-cronos-pruned-ws
- traefik.http.routers.cronos-mainnet-cronos-pruned.service=cronos-mainnet-cronos-pruned
- ${NO_SSL:-traefik.http.routers.cronos-mainnet-cronos-pruned-ws.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.cronos-mainnet-cronos-pruned-ws.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.cronos-mainnet-cronos-pruned-ws.rule=Host(`$DOMAIN`) && (Path(`/cronos-mainnet`) || Path(`/cronos-mainnet/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- ${NO_SSL:+traefik.http.routers.cronos-mainnet-cronos-pruned-ws.rule=(Path(`/cronos-mainnet`) || Path(`/cronos-mainnet/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- traefik.http.routers.cronos-mainnet-cronos-pruned-ws.middlewares=cronos-mainnet-cronos-pruned-stripprefix, ipallowlist
volumes:
cronos-mainnet-cronos-pruned:
cronos-mainnet-cronos-pruned_config:
x-upstreams:
- id: $${ID}
labels:
provider: $${PROVIDER}
connection:
generic:
rpc:
url: $${RPC_URL}
ws:
frameSize: 20Mb
msgSize: 50Mb
url: $${WS_URL}
chain: cronos
method-groups:
enabled:
- debug
- filter
methods:
disabled:
enabled:
- name: txpool_content # TODO: should be disabled for rollup nodes
...

View File

@@ -0,0 +1,223 @@
#!/bin/sh
# cometbft-common.sh — reusable CometBFT-node bootstrap helpers (family C).
#
# Source this from a chain-specific init.sh. It encapsulates the operations every
# CometBFT-consensus node needs (init, fetch config artifacts, patch config.toml /
# app.toml, seed priv_validator_state), extracted verbatim from the proven berachain
# beacon-kit entrypoint so callers inherit known-good behavior.
#
# Each function takes explicit arguments (paths/values) — it is binary-agnostic. The
# caller owns the binary name, the `<binary> init` invocation, the artifact URLs, and
# the final `exec <binary> start ...`. EL-driven chains (beacon-kit, morph) also call
# the JWT / engine-dial helpers; pure-consensus chains (gaiad) skip them.
#
# Conventions: POSIX sh (alpine). Config dir is conventionally $HOME_DIR/config.
# Used by: morph-node, gaiad (cosmos batch), and any future family-C chain.
# beacon-kit (berachain) keeps its own bespoke init.sh on purpose — do not retrofit it.
set -e
ct_log() { echo "[cometbft-init] $*"; }
# Ensure curl exists (alpine base images often omit it). Idempotent.
ct_require_curl() {
if ! command -v curl >/dev/null 2>&1; then
ct_log "installing curl"
apk add --no-cache curl
fi
}
# ct_fetch URL DEST [required]
# Download URL -> DEST. If the 3rd arg is "required", a failure is fatal;
# otherwise a missing/failed fetch is logged and skipped (returns 0).
ct_fetch() {
_url="$1"; _dest="$2"; _req="${3:-optional}"
[ -n "$_url" ] || { [ "$_req" = required ] && { ct_log "FATAL: empty URL for $_dest"; exit 1; }; return 0; }
if curl -fsSL "$_url" -o "$_dest"; then
ct_log "fetched $_url -> $_dest"
else
if [ "$_req" = required ]; then
ct_log "FATAL: failed to fetch required $_url"; exit 1
fi
ct_log "skip: could not fetch optional $_url"
fi
}
# ct_patch_p2p CONFIG_TOML IP P2P_PORT
# Bind p2p to 0.0.0.0:PORT and advertise IP:PORT (only within the [p2p] section).
ct_patch_p2p() {
_cfg="$1"; _ip="$2"; _port="$3"
[ -f "$_cfg" ] || { ct_log "patch_p2p: $_cfg missing, skipping"; return 0; }
_laddr="tcp:\\/\\/0\\.0\\.0\\.0\\:${_port}"
sed -i "/^\[p2p\]/,/^\[/{s|^laddr = .*|laddr = \"$_laddr\"|}" "$_cfg"
sed -i "/^\[p2p\]/,/^\[/{s|^external_address = .*|external_address = \"${_ip}:${_port}\"|}" "$_cfg"
}
# ct_merge_seeds CONFIG_TOML CONFIGURED_SEEDS [SEEDS_URL]
# Merge operator-configured seeds with an optional official seed list (1 entry per
# line, first line skipped like the berachain cl-seeds.txt header), dedupe, write.
ct_merge_seeds() {
_cfg="$1"; _seeds="$2"; _url="$3"
[ -f "$_cfg" ] || return 0
if [ -n "$_url" ]; then
_official=$(curl -f -s "$_url" | tail -n +2 | tr '\n' ',' | sed 's/,$//' || true)
if [ -n "$_official" ]; then
ct_log "merging official seeds from $_url"
_seeds=$(echo "${_seeds},${_official}" | tr ',' '\n' | sed '/^$/d' | sort -u | paste -sd,)
else
ct_log "no official seeds fetched from $_url (continuing with configured)"
fi
fi
if [ -n "$_seeds" ]; then
sed -i "s/^seeds = \".*\"/seeds = \"${_seeds}\"/" "$_cfg"
fi
}
# ct_set_persistent_peers CONFIG_TOML PEERS
# Handles both cometbft-classic `persistent_peers` (underscore) and forks that use
# `persistent-peers` (hyphen, e.g. sei) — patches whichever key is present.
ct_set_persistent_peers() {
_cfg="$1"; _peers="$2"
[ -f "$_cfg" ] || return 0
[ -n "$_peers" ] || return 0
sed -i "s/^persistent_peers = \".*\"/persistent_peers = \"${_peers}\"/" "$_cfg"
sed -i "s/^persistent-peers = \".*\"/persistent-peers = \"${_peers}\"/" "$_cfg"
return 0
}
# ct_set_moniker CONFIG_TOML MONIKER
ct_set_moniker() {
_cfg="$1"; _mon="$2"
[ -f "$_cfg" ] || return 0
[ -n "$_mon" ] && sed -i "s/^moniker = \".*\"/moniker = \"$_mon\"/" "$_cfg"
return 0
}
# ct_set_addrbook CONFIG_DIR ADDRBOOK_URL
# Optional: cosmos chains often seed an addrbook.json for faster peer discovery.
ct_set_addrbook() {
_dir="$1"; _url="$2"
[ -n "$_url" ] || return 0
ct_fetch "$_url" "$_dir/addrbook.json" optional
}
# ct_write_jwt CONFIG_DIR [JWT_SRC]
# EL-driven chains: copy the shared engine JWT (default /jwtsecret) into the config
# dir as jwt.hex so the CL can authenticate to the EL engine API.
ct_write_jwt() {
_dir="$1"; _src="${2:-/jwtsecret}"
[ -f "$_src" ] || { ct_log "write_jwt: $_src missing, skipping"; return 0; }
cat "$_src" > "$_dir/jwt.hex"
}
# ct_set_rpc_dial_url APP_TOML AUTH_RPC
# beacon-kit / app.toml-style EL engine endpoint (e.g. http://<el>:8551).
ct_set_rpc_dial_url() {
_app="$1"; _rpc="$2"
[ -f "$_app" ] || return 0
[ -n "$_rpc" ] && sed -i "s|^rpc-dial-url = \".*\"|rpc-dial-url = \"$_rpc\"|" "$_app"
return 0
}
# ct_seed_priv_validator_state HOME_DIR
# Ensure data/priv_validator_state.json exists (cometbft refuses to start without it
# when one is present in config/). Mirrors the berachain init.sh behavior.
ct_seed_priv_validator_state() {
_home="$1"
if [ -e "$_home/config/priv_validator_state.json" ] && [ ! -e "$_home/data/priv_validator_state.json" ]; then
mkdir -p "$_home/data"
cp "$_home/config/priv_validator_state.json" "$_home/data/priv_validator_state.json"
fi
return 0
}
# ct_apk PKG...
# Install alpine packages idempotently (most cosmos init scripts need curl, some jq).
ct_apk() {
apk add --no-cache "$@"
}
# ct_localize_home CONFIG_DIR
# Rewrite `~/` to `/root/` in config.toml + app.toml. Cosmos `init` writes home-relative
# paths; the container runs as root with a static home, so make paths absolute.
ct_localize_home() {
_dir="$1"
[ -f "$_dir/config.toml" ] && sed -i 's|~/|/root/|g' "$_dir/config.toml"
[ -f "$_dir/app.toml" ] && sed -i 's|~/|/root/|g' "$_dir/app.toml"
return 0
}
# ct_set_min_gas_prices APP_TOML PRICE
# Cosmos chains reject txs (and sometimes refuse to start) with an empty
# minimum-gas-prices. PRICE e.g. "0.01usei", "0.0025uatom", "0.01hqq".
ct_set_min_gas_prices() {
_app="$1"; _price="$2"
[ -f "$_app" ] || return 0
[ -n "$_price" ] || return 0
sed -i "s/minimum-gas-prices = \"\"/minimum-gas-prices = \"${_price}\"/g" "$_app"
return 0
}
# ct_configure_statesync CONFIG_TOML RPC_SERVERS [TRUST_OFFSET]
# Enable cometbft state-sync so a fresh node bootstraps near chainhead instead of
# replaying from genesis — the single biggest lever for "can't keep it at chainhead"
# chains. RPC_SERVERS = comma list of trusted RPC endpoints (>=2 recommended; a single
# endpoint is duplicated). TRUST_OFFSET = blocks below head to trust (default 2000).
# Requires jq + curl. No-op (logged) if head height can't be fetched.
ct_configure_statesync() {
_cfg="$1"; _rpc="$2"; _offset="${3:-2000}"
[ -f "$_cfg" ] || return 0
# NEVER re-arm statesync on a node that already has application state (a restored
# snapshot or a prior sync). Re-statesyncing over it leaves a broken/partial datadir and,
# for wasm chains, drops the wasm files -> startup panic. _cfg is $HOME/config/config.toml,
# so application state lives at $HOME/data/application.db.
_home=$(dirname "$(dirname "$_cfg")")
if [ -e "$_home/data/application.db" ]; then
ct_log "statesync: existing data dir, skipping"
return 0
fi
[ -n "$_rpc" ] || { ct_log "statesync: no RPC servers given, skipping"; return 0; }
_primary=$(echo "$_rpc" | cut -d, -f1)
_latest=$(curl -s "$_primary/block" | jq -r '.result.block.header.height // .block.header.height' 2>/dev/null || true)
if [ -z "$_latest" ] || [ "$_latest" = null ]; then
ct_log "statesync: could not read head height from $_primary, skipping"; return 0
fi
_trust_h=$((_latest - _offset))
_trust_hash=$(curl -s "$_primary/block?height=$_trust_h" | jq -r '.result.block_id.hash // .block_id.hash' 2>/dev/null || true)
[ -n "$_trust_hash" ] && [ "$_trust_hash" != null ] || { ct_log "statesync: no trust hash, skipping"; return 0; }
# second server defaults to the first (cometbft wants >=2 for light-client cross-check)
echo "$_rpc" | grep -q ',' || _rpc="$_rpc,$_rpc"
ct_log "statesync: enable trust_height=$_trust_h trust_hash=$_trust_hash"
# Patch ONLY the [statesync] section. CometBFT config.toml uses underscore keys
# (rpc_servers/trust_height/trust_hash); tolerate hyphen variants with [_-].
sed -i.bak -E "/^\[statesync\]/,/^\[/{
s|^([[:space:]]*enable[[:space:]]*=[[:space:]]*).*|\1true|
s|^([[:space:]]*rpc[_-]servers[[:space:]]*=[[:space:]]*).*|\1\"$_rpc\"|
s|^([[:space:]]*trust[_-]height[[:space:]]*=[[:space:]]*).*|\1$_trust_h|
s|^([[:space:]]*trust[_-]hash[[:space:]]*=[[:space:]]*).*|\1\"$_trust_hash\"|
}" "$_cfg"
return 0
}
# ct_ensure_wasm HOME_DIR WASM_SNAPSHOT_URL
# CosmWasm + IBC 08-wasm bytecode are FILES on disk that state-sync does NOT restore, so
# a state-synced wasm chain panics at startup ("wasmlckeeper failed initialize pinned codes
# / Error opening Wasm file"). Seed them from a wasm-only snapshot (e.g. polkachu
# cosmos_wasmonly.tar.lz4) when the wasm dir is missing/empty. No-op if URL unset or wasm
# already present. Best-effort (logs on failure); the fully robust path for wasm chains is a
# FULL snapshot restore. Requires lz4 + tar (installed here).
ct_ensure_wasm() {
_home="$1"; _url="$2"
[ -n "$_url" ] || return 0
if [ -d "$_home/wasm" ] && [ -n "$(ls -A "$_home/wasm" 2>/dev/null)" ]; then
return 0 # wasm already present
fi
ct_log "wasm: empty, fetching snapshot $_url"
ct_apk lz4 tar
if curl -sL "$_url" | lz4 -dc | tar -xf - -C "$_home"; then
ct_log "wasm: extracted into $_home"
else
ct_log "WARN wasm: fetch/extract failed ($_url)"
fi
return 0
}

69
cronos/scripts/init.sh Normal file
View File

@@ -0,0 +1,69 @@
#!/bin/sh
set -e # Exit on failure
echo "MONIKER: $MONIKER"
CHAINID=${CHAINID:-cronosmainnet_25-1}
CHAINNAME=${CHAINNAME:-mainnet}
API=${API:-eth,txpool,net,debug,web3}
CONFIG_DIR="/root/.cronos/config"
# Create config directory
mkdir -p "$CONFIG_DIR"
P2P_STRING="tcp:\/\/0\.0\.0\.0\:${P2P_PORT:-10521}"
NAT_STRING="${IP}:${P2P_PORT:-10521}"
env
# this goes first because it won't overwrite shit
apk add curl jq
if [ $? -ne 0 ]; then exit 1; fi
# Source the shared CometBFT helpers
. /usr/local/bin/cometbft-common.sh
if cronosd init ${MONIKER} --chain-id ${CHAINID} --home /root/.cronos/; then
# Define variables
GENESIS_URL="https://raw.githubusercontent.com/crypto-org-chain/cronos-mainnet/master/cronosmainnet_25-1/genesis.json"
SEEDS="0d5cf1394a1cfde28dc8f023567222abc0f47534@cronos-seed-0.crypto.org:26656,3032073adc06d710dd512240281637c1bd0c8a7b@cronos-seed-1.crypto.org:26656,04f43116b4c6c70054d9c2b7485383df5b1ed1da@cronos-seed-2.crypto.org:26656"
# Download config files
curl -sL "$GENESIS_URL" -o "$CONFIG_DIR/genesis.json"
# somehow it's better to make home static to /root
sed -i 's|~/|/root/|g' "$CONFIG_DIR/config.toml"
sed -i 's|~/|/root/|g' "$CONFIG_DIR/app.toml"
else
echo "Already initialized, continuing!" >&2
fi
# Localize home directory paths
ct_localize_home /root/.cronos/config
# apply a port change to the config
ct_patch_p2p "$CONFIG_DIR/config.toml" "$IP" "${P2P_PORT:-10521}"
sed -i -e "s/^pruning *=.*/pruning = \"custom\"/" $CONFIG_DIR/app.toml
sed -i -e "s/^pruning-keep-recent *=.*/pruning-keep-recent = \"100\"/" $CONFIG_DIR/app.toml
sed -i -e "s/^pruning-interval *=.*/pruning-interval = \"19\"/" $CONFIG_DIR/app.toml
sed -i -e "s/^indexer *=.*/indexer = \"null\"/" $CONFIG_DIR/config.toml
sed -i "/^\[json-rpc\]/,/^\[/{s|^address = .*|address = \"0.0.0.0:8545\"|}" "$CONFIG_DIR/app.toml"
sed -i "/^\[json-rpc\]/,/^\[/{s|^ws-address = .*|ws-address = \"0.0.0.0:8546\"|}" "$CONFIG_DIR/app.toml"
sed -i "/^\[json-rpc\]/,/^\[/{s|^api = .*|api = \"$API\"|}" "$CONFIG_DIR/app.toml"
# Set seeds
ct_set_persistent_peers "$CONFIG_DIR/config.toml" "$SEEDS"
# Configure state sync using official RPC endpoints
ct_configure_statesync "$CONFIG_DIR/config.toml" "https://rpc-cronos.crypto.org:443,https://cronos-rpc.publicnode.com:443" 2000
# Update moniker if set
if [ -n "$MONIKER" ] && [ -f "$CONFIG_DIR/config.toml" ]; then
ct_set_moniker "$CONFIG_DIR/config.toml" "$MONIKER"
fi
exec cronosd start --chain-id ${CHAINID} $@

View File

@@ -1,6 +1,6 @@
# syntax = docker/dockerfile:1.2 # syntax = docker/dockerfile:1.2
ARG REPO=https://github.com/erigontech/erigon.git ARG REPO=https://github.com/erigontech/erigon.git
ARG VERSION=v3.0.7 ARG VERSION=v3.4.4
ARG COMMIT=${COMMIT:-${VERSION}} ARG COMMIT=${COMMIT:-${VERSION}}
FROM docker.io/library/golang:1.24.1-alpine3.20 AS builder FROM docker.io/library/golang:1.24.1-alpine3.20 AS builder

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
ethereum-classic-besu: ethereum-classic-besu:
image: ${ETHEREUM_BESU_IMAGE:-hyperledger/besu}:${ETHEREUM_CLASSIC_BESU_VERSION:-26.5.0} image: ${ETHEREUM_BESU_IMAGE:-hyperledger/besu}:${ETHEREUM_CLASSIC_BESU_VERSION:-26.1.0}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
@@ -103,8 +103,8 @@ services:
- traefik.http.routers.ethereum-classic-besu-pruned-bonsai.service=ethereum-classic-besu-pruned-bonsai - traefik.http.routers.ethereum-classic-besu-pruned-bonsai.service=ethereum-classic-besu-pruned-bonsai
- ${NO_SSL:-traefik.http.routers.ethereum-classic-besu-pruned-bonsai-ws.entrypoints=websecure} - ${NO_SSL:-traefik.http.routers.ethereum-classic-besu-pruned-bonsai-ws.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.ethereum-classic-besu-pruned-bonsai-ws.tls.certresolver=myresolver} - ${NO_SSL:-traefik.http.routers.ethereum-classic-besu-pruned-bonsai-ws.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.ethereum-classic-besu-pruned-bonsai-ws.rule=Host(`$DOMAIN`) && (Path(`/ethereum-classic-besu`) || Path(`/ethereum-classic-besu/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:-traefik.http.routers.ethereum-classic-besu-pruned-bonsai-ws.rule=Host(`$DOMAIN`) && (Path(`/ethereum-classic-besu`) || Path(`/ethereum-classic-besu/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- ${NO_SSL:+traefik.http.routers.ethereum-classic-besu-pruned-bonsai-ws.rule=(Path(`/ethereum-classic-besu`) || Path(`/ethereum-classic-besu/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:+traefik.http.routers.ethereum-classic-besu-pruned-bonsai-ws.rule=(Path(`/ethereum-classic-besu`) || Path(`/ethereum-classic-besu/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- traefik.http.routers.ethereum-classic-besu-pruned-bonsai-ws.middlewares=ethereum-classic-besu-pruned-bonsai-stripprefix, ipallowlist - traefik.http.routers.ethereum-classic-besu-pruned-bonsai-ws.middlewares=ethereum-classic-besu-pruned-bonsai-stripprefix, ipallowlist
volumes: volumes:

View File

@@ -109,8 +109,8 @@ services:
- traefik.http.routers.ethereum-mainnet-besu-pruned-bonsai.service=ethereum-mainnet-besu-pruned-bonsai - traefik.http.routers.ethereum-mainnet-besu-pruned-bonsai.service=ethereum-mainnet-besu-pruned-bonsai
- ${NO_SSL:-traefik.http.routers.ethereum-mainnet-besu-pruned-bonsai-ws.entrypoints=websecure} - ${NO_SSL:-traefik.http.routers.ethereum-mainnet-besu-pruned-bonsai-ws.entrypoints=websecure}
- ${NO_SSL:-traefik.http.routers.ethereum-mainnet-besu-pruned-bonsai-ws.tls.certresolver=myresolver} - ${NO_SSL:-traefik.http.routers.ethereum-mainnet-besu-pruned-bonsai-ws.tls.certresolver=myresolver}
- ${NO_SSL:-traefik.http.routers.ethereum-mainnet-besu-pruned-bonsai-ws.rule=Host(`$DOMAIN`) && (Path(`/ethereum-mainnet-besu`) || Path(`/ethereum-mainnet-besu/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:-traefik.http.routers.ethereum-mainnet-besu-pruned-bonsai-ws.rule=Host(`$DOMAIN`) && (Path(`/ethereum-mainnet-besu`) || Path(`/ethereum-mainnet-besu/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- ${NO_SSL:+traefik.http.routers.ethereum-mainnet-besu-pruned-bonsai-ws.rule=(Path(`/ethereum-mainnet-besu`) || Path(`/ethereum-mainnet-besu/`)) && Headers(`Upgrade`, `websocket`)} - ${NO_SSL:+traefik.http.routers.ethereum-mainnet-besu-pruned-bonsai-ws.rule=(Path(`/ethereum-mainnet-besu`) || Path(`/ethereum-mainnet-besu/`)) && HeadersRegexp(`Upgrade`, `(?i)websocket`)}
- traefik.http.routers.ethereum-mainnet-besu-pruned-bonsai-ws.middlewares=ethereum-mainnet-besu-pruned-bonsai-stripprefix, ipallowlist - traefik.http.routers.ethereum-mainnet-besu-pruned-bonsai-ws.middlewares=ethereum-mainnet-besu-pruned-bonsai-stripprefix, ipallowlist
ethereum-mainnet-besu-node: ethereum-mainnet-besu-node:

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
ethereum-hoodi-erigon3-archive: ethereum-hoodi-erigon3-archive:
image: ${ETHEREUM_ERIGON3_IMAGE:-erigontech/erigon}:${ETHEREUM_HOODI_ERIGON3_VERSION:-v3.4.2} image: ${ETHEREUM_ERIGON3_IMAGE:-erigontech/erigon}:${ETHEREUM_HOODI_ERIGON3_VERSION:-v3.4.4}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
@@ -141,7 +141,7 @@ x-upstreams:
frameSize: 20Mb frameSize: 20Mb
msgSize: 50Mb msgSize: 50Mb
url: $${WS_URL} url: $${WS_URL}
chain: ethereum chain: hoodi
method-groups: method-groups:
enabled: enabled:
- debug - debug

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
ethereum-hoodi-erigon3-minimal: ethereum-hoodi-erigon3-minimal:
image: ${ETHEREUM_ERIGON3_IMAGE:-erigontech/erigon}:${ETHEREUM_HOODI_ERIGON3_VERSION:-v3.4.2} image: ${ETHEREUM_ERIGON3_IMAGE:-erigontech/erigon}:${ETHEREUM_HOODI_ERIGON3_VERSION:-v3.4.4}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
@@ -141,7 +141,7 @@ x-upstreams:
frameSize: 20Mb frameSize: 20Mb
msgSize: 50Mb msgSize: 50Mb
url: $${WS_URL} url: $${WS_URL}
chain: ethereum chain: hoodi
method-groups: method-groups:
enabled: enabled:
- debug - debug

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
ethereum-hoodi-erigon3: ethereum-hoodi-erigon3:
image: ${ETHEREUM_ERIGON3_IMAGE:-erigontech/erigon}:${ETHEREUM_HOODI_ERIGON3_VERSION:-v3.4.2} image: ${ETHEREUM_ERIGON3_IMAGE:-erigontech/erigon}:${ETHEREUM_HOODI_ERIGON3_VERSION:-v3.4.4}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
@@ -141,7 +141,7 @@ x-upstreams:
frameSize: 20Mb frameSize: 20Mb
msgSize: 50Mb msgSize: 50Mb
url: $${WS_URL} url: $${WS_URL}
chain: ethereum chain: hoodi
method-groups: method-groups:
enabled: enabled:
- debug - debug

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
ethereum-mainnet-erigon3-archive: ethereum-mainnet-erigon3-archive:
image: ${ETHEREUM_ERIGON3_IMAGE:-erigontech/erigon}:${ETHEREUM_MAINNET_ERIGON3_VERSION:-v3.4.2} image: ${ETHEREUM_ERIGON3_IMAGE:-erigontech/erigon}:${ETHEREUM_MAINNET_ERIGON3_VERSION:-v3.4.4}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
ethereum-mainnet-erigon3-minimal: ethereum-mainnet-erigon3-minimal:
image: ${ETHEREUM_ERIGON3_IMAGE:-erigontech/erigon}:${ETHEREUM_MAINNET_ERIGON3_VERSION:-v3.4.2} image: ${ETHEREUM_ERIGON3_IMAGE:-erigontech/erigon}:${ETHEREUM_MAINNET_ERIGON3_VERSION:-v3.4.4}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
ethereum-mainnet-erigon3: ethereum-mainnet-erigon3:
image: ${ETHEREUM_ERIGON3_IMAGE:-erigontech/erigon}:${ETHEREUM_MAINNET_ERIGON3_VERSION:-v3.4.2} image: ${ETHEREUM_ERIGON3_IMAGE:-erigontech/erigon}:${ETHEREUM_MAINNET_ERIGON3_VERSION:-v3.4.4}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
ethereum-sepolia-erigon3-archive: ethereum-sepolia-erigon3-archive:
image: ${ETHEREUM_ERIGON3_IMAGE:-erigontech/erigon}:${ETHEREUM_SEPOLIA_ERIGON3_VERSION:-v3.4.2} image: ${ETHEREUM_ERIGON3_IMAGE:-erigontech/erigon}:${ETHEREUM_SEPOLIA_ERIGON3_VERSION:-v3.4.4}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
ethereum-sepolia-erigon3-minimal: ethereum-sepolia-erigon3-minimal:
image: ${ETHEREUM_ERIGON3_IMAGE:-erigontech/erigon}:${ETHEREUM_SEPOLIA_ERIGON3_VERSION:-v3.4.2} image: ${ETHEREUM_ERIGON3_IMAGE:-erigontech/erigon}:${ETHEREUM_SEPOLIA_ERIGON3_VERSION:-v3.4.4}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
ethereum-sepolia-erigon3: ethereum-sepolia-erigon3:
image: ${ETHEREUM_ERIGON3_IMAGE:-erigontech/erigon}:${ETHEREUM_SEPOLIA_ERIGON3_VERSION:-v3.4.2} image: ${ETHEREUM_ERIGON3_IMAGE:-erigontech/erigon}:${ETHEREUM_SEPOLIA_ERIGON3_VERSION:-v3.4.4}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

View File

@@ -162,7 +162,7 @@ x-upstreams:
frameSize: 20Mb frameSize: 20Mb
msgSize: 50Mb msgSize: 50Mb
url: $${WS_URL} url: $${WS_URL}
chain: ethereum chain: hoodi
method-groups: method-groups:
enabled: enabled:
- debug - debug

View File

@@ -163,7 +163,7 @@ x-upstreams:
frameSize: 20Mb frameSize: 20Mb
msgSize: 50Mb msgSize: 50Mb
url: $${WS_URL} url: $${WS_URL}
chain: ethereum chain: hoodi
method-groups: method-groups:
enabled: enabled:
- debug - debug

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
ethereum-hoodi-reth: ethereum-hoodi-reth:
image: ${ETHEREUM_RETH_IMAGE:-ghcr.io/paradigmxyz/reth}:${ETHEREUM_HOODI_RETH_VERSION:-v2.2.0} image: ${ETHEREUM_RETH_IMAGE:-ghcr.io/paradigmxyz/reth}:${ETHEREUM_HOODI_RETH_VERSION:-v2.1.0}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
@@ -168,7 +168,7 @@ x-upstreams:
frameSize: 20Mb frameSize: 20Mb
msgSize: 50Mb msgSize: 50Mb
url: $${WS_URL} url: $${WS_URL}
chain: ethereum chain: hoodi
method-groups: method-groups:
enabled: enabled:
- debug - debug

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
ethereum-hoodi-reth-pruned: ethereum-hoodi-reth-pruned:
image: ${ETHEREUM_RETH_IMAGE:-ghcr.io/paradigmxyz/reth}:${ETHEREUM_HOODI_RETH_VERSION:-v2.2.0} image: ${ETHEREUM_RETH_IMAGE:-ghcr.io/paradigmxyz/reth}:${ETHEREUM_HOODI_RETH_VERSION:-v2.1.0}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle
@@ -169,7 +169,7 @@ x-upstreams:
frameSize: 20Mb frameSize: 20Mb
msgSize: 50Mb msgSize: 50Mb
url: $${WS_URL} url: $${WS_URL}
chain: ethereum chain: hoodi
method-groups: method-groups:
enabled: enabled:
- debug - debug

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
ethereum-mainnet-reth: ethereum-mainnet-reth:
image: ${ETHEREUM_RETH_IMAGE:-ghcr.io/paradigmxyz/reth}:${ETHEREUM_MAINNET_RETH_VERSION:-v2.2.0} image: ${ETHEREUM_RETH_IMAGE:-ghcr.io/paradigmxyz/reth}:${ETHEREUM_MAINNET_RETH_VERSION:-v2.1.0}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
ethereum-mainnet-reth: ethereum-mainnet-reth:
image: ${ETHEREUM_RETH_IMAGE:-ghcr.io/paradigmxyz/reth}:${ETHEREUM_MAINNET_RETH_VERSION:-v2.2.0} image: ${ETHEREUM_RETH_IMAGE:-ghcr.io/paradigmxyz/reth}:${ETHEREUM_MAINNET_RETH_VERSION:-v2.1.0}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
ethereum-mainnet-reth: ethereum-mainnet-reth:
image: ${ETHEREUM_RETH_IMAGE:-ghcr.io/paradigmxyz/reth}:${ETHEREUM_MAINNET_RETH_VERSION:-v2.2.0} image: ${ETHEREUM_RETH_IMAGE:-ghcr.io/paradigmxyz/reth}:${ETHEREUM_MAINNET_RETH_VERSION:-v2.1.0}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

View File

@@ -33,7 +33,7 @@ x-logging-defaults: &logging-defaults
services: services:
ethereum-mainnet-reth-minimal: ethereum-mainnet-reth-minimal:
image: ${ETHEREUM_RETH_IMAGE:-ghcr.io/paradigmxyz/reth}:${ETHEREUM_MAINNET_RETH_VERSION:-v2.2.0} image: ${ETHEREUM_RETH_IMAGE:-ghcr.io/paradigmxyz/reth}:${ETHEREUM_MAINNET_RETH_VERSION:-v2.1.0}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

View File

@@ -52,7 +52,7 @@ services:
args: args:
LLVM_IMAGE: ${LLVM_IMAGE:-snowstep/llvm} LLVM_IMAGE: ${LLVM_IMAGE:-snowstep/llvm}
LLVM_VERSION: ${LLVM_VERSION:-20250912105042} LLVM_VERSION: ${LLVM_VERSION:-20250912105042}
RETH_VERSION: ${ETHEREUM_MAINNET_RETH_VERSION:-v2.2.0} RETH_VERSION: ${ETHEREUM_MAINNET_RETH_VERSION:-v2.1.0}
RETH_REPO: ${ETHEREUM_MAINNET_RETH_REPO:-https://github.com/paradigmxyz/reth} RETH_REPO: ${ETHEREUM_MAINNET_RETH_REPO:-https://github.com/paradigmxyz/reth}
ARCH_TARGET: ${ARCH_TARGET:-native} ARCH_TARGET: ${ARCH_TARGET:-native}
PROFILE: ${RETH_BUILD_PROFILE:-maxperf} PROFILE: ${RETH_BUILD_PROFILE:-maxperf}

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
ethereum-mainnet-reth-pruned: ethereum-mainnet-reth-pruned:
image: ${ETHEREUM_RETH_IMAGE:-ghcr.io/paradigmxyz/reth}:${ETHEREUM_MAINNET_RETH_VERSION:-v2.2.0} image: ${ETHEREUM_RETH_IMAGE:-ghcr.io/paradigmxyz/reth}:${ETHEREUM_MAINNET_RETH_VERSION:-v2.1.0}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
ethereum-mainnet-reth-pruned: ethereum-mainnet-reth-pruned:
image: ${ETHEREUM_RETH_IMAGE:-ghcr.io/paradigmxyz/reth}:${ETHEREUM_MAINNET_RETH_VERSION:-v2.2.0} image: ${ETHEREUM_RETH_IMAGE:-ghcr.io/paradigmxyz/reth}:${ETHEREUM_MAINNET_RETH_VERSION:-v2.1.0}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
ethereum-mainnet-reth-pruned: ethereum-mainnet-reth-pruned:
image: ${ETHEREUM_RETH_IMAGE:-ghcr.io/paradigmxyz/reth}:${ETHEREUM_MAINNET_RETH_VERSION:-v2.2.0} image: ${ETHEREUM_RETH_IMAGE:-ghcr.io/paradigmxyz/reth}:${ETHEREUM_MAINNET_RETH_VERSION:-v2.1.0}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
ethereum-sepolia-reth: ethereum-sepolia-reth:
image: ${ETHEREUM_RETH_IMAGE:-ghcr.io/paradigmxyz/reth}:${ETHEREUM_SEPOLIA_RETH_VERSION:-v2.2.0} image: ${ETHEREUM_RETH_IMAGE:-ghcr.io/paradigmxyz/reth}:${ETHEREUM_SEPOLIA_RETH_VERSION:-v2.1.0}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
ethereum-sepolia-reth: ethereum-sepolia-reth:
image: ${ETHEREUM_RETH_IMAGE:-ghcr.io/paradigmxyz/reth}:${ETHEREUM_SEPOLIA_RETH_VERSION:-v2.2.0} image: ${ETHEREUM_RETH_IMAGE:-ghcr.io/paradigmxyz/reth}:${ETHEREUM_SEPOLIA_RETH_VERSION:-v2.1.0}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
ethereum-sepolia-reth-pruned: ethereum-sepolia-reth-pruned:
image: ${ETHEREUM_RETH_IMAGE:-ghcr.io/paradigmxyz/reth}:${ETHEREUM_SEPOLIA_RETH_VERSION:-v2.2.0} image: ${ETHEREUM_RETH_IMAGE:-ghcr.io/paradigmxyz/reth}:${ETHEREUM_SEPOLIA_RETH_VERSION:-v2.1.0}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
ethereum-sepolia-reth-pruned: ethereum-sepolia-reth-pruned:
image: ${ETHEREUM_RETH_IMAGE:-ghcr.io/paradigmxyz/reth}:${ETHEREUM_SEPOLIA_RETH_VERSION:-v2.2.0} image: ${ETHEREUM_RETH_IMAGE:-ghcr.io/paradigmxyz/reth}:${ETHEREUM_SEPOLIA_RETH_VERSION:-v2.1.0}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

View File

@@ -30,7 +30,7 @@ x-logging-defaults: &logging-defaults
services: services:
gnosis-chiado-erigon3-archive: gnosis-chiado-erigon3-archive:
image: ${GNOSIS_ERIGON3_IMAGE:-erigontech/erigon}:${GNOSIS_CHIADO_ERIGON3_VERSION:-v3.4.2} image: ${GNOSIS_ERIGON3_IMAGE:-erigontech/erigon}:${GNOSIS_CHIADO_ERIGON3_VERSION:-v3.4.4}
sysctls: sysctls:
# TCP Performance # TCP Performance
net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle net.ipv4.tcp_slow_start_after_idle: 0 # Disable slow start after idle

Some files were not shown because too many files have changed in this diff Show More