docs: network tabs, ext4/XFS guidance, and README-only content moved to the site - #22919
docs: network tabs, ext4/XFS guidance, and README-only content moved to the site#22919bloxster wants to merge 20 commits into
Conversation
014fa71 to
fe29cba
Compare
The Polygon tab carried September 2025 figures behind a warning that Erigon's final Polygon-supporting series is 3.1.*. The numbers are not measured any more and the support statement already lives in Supported Networks and in "How to run a Polygon node". Removed the tab, not those. Sepolia, Hoodi and Chiado had no disk figures anywhere, though all three are listed as supported networks and all three are synced by QA. Added with archive only; full and minimal read "-" because only the QA full-node and minimal-node sync runs upload disk-usage artifacts and both matrices pin mainnet and gnosis. Filling those cells is a QA-capacity decision, not a docs edit. Note for review: the mainnet Minimal row recommends 64 GB RAM against Full's 32 GB, which reads as a transcription error (Gnosis is internally consistent at 16 GB). Left untouched here — it needs an engineering answer, not a docs guess. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The Overview table recommended RAID 0 for multiple disks and said ZFS "may be considered for Archive nodes for their data integrity features, but complex RAID-Z setups are generally not recommended" — advice that pulls in two directions in one cell, and that no longer matches the footprint. An archive node is about 2 TB, so it fits on a single 4 TB drive: striping buys nothing and doubles the chance of losing the datadir. Replaced with a Filesystem section recommending ext4 or XFS on one NVMe device, mounted noatime. Anything else is called unverified rather than bad, since we have not measured it. The section also states why redundancy matters less here than for a database-backed service (snapshots are content-addressed and refetchable, only chaindata is worth backing up). optimizing-storage.md opened by recommending "a fast NVMe-RAID disk", which would have contradicted the new section, so it now points at it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…D advice Two defects from an adversarial review pass. The Sepolia / Hoodi / Chiado captions justified the empty full and minimal cells by naming the QA workflows that upload disk-usage artifacts. That detail is branch-dependent and wrong on this branch: release/3.5 has no qa-sync-from-scratch-full-node.yml at all, and its minimal-node workflow has no measurement step, so nothing on release/3.5 produces the artifacts update-disk-sizes.yml waits for. Every figure in disk-sizes.json is "source": "manual" for that reason. Captions now state the fact — archive is the only mode measured on these networks — and the CI story moves to the PR body where it can be acted on. The Filesystem section argued against RAID 0 in terms broad enough to read as arguing against redundancy, while help-center/best-practices.md and help-center/troubleshooting.md both recommend disk RAID and backups against hardware failure. Split the two: RAID 0 striping buys nothing at this footprint, mirroring plus ECC is the right answer for failure protection, and Best Practices is linked rather than contradicted. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The Filesystem section said "both are in use by operators running Erigon". There is no evidence for that, internal or external. ext4 is evidenced — every disk figure on these pages is measured on it — but the XFS half was an assumption about an operator base nobody has surveyed. The only Erigon-on-XFS instance on record is issue #13881, and that node failed for an unrelated reason (kernel 3 on CentOS 7). Now states what is measured and says plainly that XFS is untested here, rather than borrowing credibility it has not earned. Same discipline the disk figures on these pages were just put under. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
fe29cba to
a854b97
Compare
The three networks added in the first commit carry `measured_at: 2026-07-29`, but `ci_last_updated` still read `2026-07-21`, so the record claimed it was last updated eight days before the newest measurement it contains. `update-disk-sizes.py:80` writes this field as the day CI refreshed the JSON, so it has to be at or after every `measured_at` in the file. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Moves the content that lived only in README.md into the pages that own it, so the README can drop it without anything being lost: - Sync times table -> get-started/hardware-requirements - Hetzner reserved-range blocklist -> help-center/troubleshooting, linked from the Network Security section of fundamentals/security - Downloader torrent-log behaviour -> fundamentals/logs - make DIST=<path> install -> get-started/installation - Beacon API RAM cost and the --beacon.api enabling flag -> fundamentals/caplin - --batchSize guard against chaindata growth -> fundamentals/database Four other README items were checked and are already documented, in better form, so they are not migrated: the SIGUSR1/pprof diagnostics (help-center troubleshooting, which also documents --pprof.addr and uses curl rather than requiring a Go toolchain), chaindata deletion (fundamentals/database, which states the consequences the README omitted), the WSL caveats (installation, which covers DrvFS, the remote-DB rpcdaemon requirement and the WSL2 NAT address), and the --sync.loop.block.limit default of 5000 (already in the CLI reference). The README's "MDBX locks the db for exclusive access" rationale is deliberately not carried over: it contradicts the single-writer/many-reader model documented in fundamentals/database. Three corrections made while moving: - The Hetzner list had 127.16.0.0/12 "Private-Use Networks RFC 1918", which is a corrupted loopback row — 172.16.0.0/12 was already listed separately. It is restored to 127.0.0.0/8 Loopback. The list is attributed to the IANA IPv4 Special-Purpose Address Registry rather than RFC 5735, which does not contain 100.64.0.0/10 (RFC 6598, 2012) and is itself obsoleted by RFC 6890. - The torrent-log level is described as the more verbose of --torrent.verbosity and WARN. The README said "whichever is lower", which reads backwards in this codebase: erigonToSlogLevel is 12-4*lvl, so the slog min() is the more verbose threshold. - The sync-times table loses its to-the-minute precision. The README published values like "4h 23m" with no stated provenance, and they are not measured by anything on this branch: there is no qa-sync-from-scratch workflow and no in-sync-delay measurement anywhere in .github. Where CI observations did exist they ran well above the published cells (Ethereum full 5h06-5h48 over four runs against 4h23; Gnosis full 1h55-2h07 against 1h05). Replaced with coarse ranges chosen to span both the published values and those observations, and labelled "not measured by CI" so the page does not imply an accuracy it cannot support. The figures are worth keeping in some form — they are the only sync-time guidance published anywhere — but not at a precision nothing backs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
yperbasis
left a comment
There was a problem hiding this comment.
Combined review; every point below was checked against the branch code.
High
docs/site/help-center/troubleshooting.md:47—kill -6 $(pidof erigon)signals every erigon process on the host, while the sentence says "the running instance", singular. Multi-instance hosts are a documented setup (fundamentals/database.mdrecommends--db.size.limitexactly for them), and SIGABRT is destructive. Usekill -6 <pid>and let the reader pick the PID. The SIGUSR1 line above can keep$(pidof erigon)— it is harmless.
Medium
docs/site/docs/fundamentals/database.md:96— the mechanism is wrong.--batchSizeis the execution commit threshold (execution/stagedsync/exec3.go:commitThreshold := cfg.batchSize.Bytes()); collation is driven separately byCollateAndPrune, and how much data sits inchaindata/between snapshot builds depends on chain progress, not on commit granularity. The real link: bigger batches mean bigger single MDBX write transactions, which grow the file's high-water mark in larger steps. Keep the ≤1G advice, fix the mechanism clause, and avoid "cap" — it is a heuristic, not a bound.docs/site/help-center/troubleshooting.md:75— "Blocking them is good practice on any host" goes too far:--caplin.local-discoverydeliberately enables private-IP peering, and the CLI reference already warns it "may cause issues with some hosts (for example, Hetzner)" (configuring-erigon.mdx:472). Scope the advice to public-facing nodes. Also, "whose stricter filtering is what prompted this note" names the wrong cause: the Hetzner problem is their abuse/netscan detection flagging outbound dials to reserved ranges, not their firewall filtering them.docs/site/docs/fundamentals/security.md:23-25— same cause mix-up: "impose additional firewall requirements" fits the ports-to-open half, but blocking the reserved ranges is self-protection against Hetzner's abuse policy, not a Hetzner-imposed firewall rule. Reword, e.g. "additional firewall requirements and operational pitfalls".llms-full.txt(both copies) — the generator dropsTabItemlabels, so the five disk tables appear back-to-back with no network names; three share an identical two-column schema and differ only in values. The defect is pre-existing ingenerate-llms.py, but this PR makes it much worse. Emit each tab label as a heading and add a regression test — here, or in a tracked follow-up.
Low
docs/site/docs/get-started/hardware-requirements.mdx:33— use a stable identifier and the non-root fsck pass:UUID=… /data ext4 defaults,noatime 0 2.docs/site/docs/get-started/hardware-requirements.mdx:22— the CPU cell has the same concatenation defect fixed one row up: "Full nodes8–16 cores".docs/site/docs/get-started/hardware-requirements.mdx:50— "with the sole exception of the--prune.modeflag" is contradicted by the three new EL-only tabs; say "unless a tab notes otherwise".docs/site/docs/fundamentals/optimizing-storage.md:9— the intro names only ext4, while the linked Filesystem section allows ext4 or XFS.
Considered and deliberately not requested: carving 192.0.0.9/.10 out of 192.0.0.0/24 (globally reachable anycast, but practically irrelevant — standard bogon lists, including the linked answer, block the whole /24), and splitting Cloud vs dedicated-server firewall guidance (the "stateless firewall" paragraph predates this PR).
…ange scope All three from @yperbasis, each verified against the code before changing. - help-center/troubleshooting: `kill -6 $(pidof erigon)` would abort every erigon on the host while the sentence said "the running instance". Now `kill -6 <pid>`, with the reason stated. The SIGUSR1 line above keeps `$(pidof erigon)` — it is harmless. - fundamentals/database: the `--batchSize` mechanism was wrong. It is the Execution stage's commit threshold (`commitThreshold := cfg.batchSize.Bytes()`, execution/stagedsync/exec3.go:174); collation runs separately via CollateAndPrune, and how much sits in `chaindata/` between snapshot builds follows chain progress, not commit granularity. Restated via the real link — bigger batches mean bigger single MDBX write transactions, raising the file's high-water mark in larger steps. The <=1G advice stays, now described as a heuristic rather than a cap. - help-center/troubleshooting: "good practice on any host" overreached, since `--caplin.local-discovery` deliberately peers over private IPs. Scoped to public-facing nodes, with that flag called out as the exception. Also corrected the cause: Hetzner's abuse/netscan detection flags outbound dials to reserved ranges — it is not their firewall filtering them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Thanks — all three addressed in 15fd7a5, each checked against the code first. High — Medium — Medium — Gates re-run: build clean, |
There was a problem hiding this comment.
Pull request overview
This docs-only PR updates the published documentation on release/3.5 to (a) refresh supported-network disk-size tabs, (b) replace older RAID/ZFS guidance with clearer ext4/XFS single-NVMe guidance, and (c) move operator guidance that previously existed only in README.md onto docs.erigon.tech (with corresponding llms artifacts updated).
Changes:
- Remove Polygon disk-size tab (outdated) and add Sepolia/Hoodi/Chiado disk-size tabs (archive-only measured).
- Add a new “Filesystem” section recommending ext4/XFS on a single NVMe with
noatime, and update storage-optimization guidance to point at it. - Migrate several operator-facing README-only sections into the site (sync-time ranges, Hetzner reserved-range blocklist, torrent log behavior,
make DIST=... install, beacon API enablement/RAM note,--batchSizeheuristic) and reflect these in llms-full artifacts.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| llms-full.txt | Updates the repo-level llms artifact to match new site docs (filesystem guidance, new networks, migrated operator content). |
| docs/site/static/llms-full.txt | Updates the published llms artifact served by the docs site to match the new content. |
| docs/site/src/data/disk-sizes.json | Adds Sepolia/Hoodi/Chiado disk measurements and bumps ci_last_updated. |
| docs/site/help-center/troubleshooting.md | Adds SIGABRT “wedged node” guidance and a Hetzner reserved-range blocklist note. |
| docs/site/docs/get-started/installation/index.mdx | Documents make DIST=<path> install for installing outside the build tree. |
| docs/site/docs/get-started/hardware-requirements.mdx | Removes Polygon tab; adds new network tabs; adds “Filesystem” section; adds sync-time ranges. |
| docs/site/docs/fundamentals/security.md | Links to the Hetzner firewall note for provider-specific firewall requirements. |
| docs/site/docs/fundamentals/optimizing-storage.md | Updates the opening recommendation to single-NVMe ext4 and links to Filesystem section. |
| docs/site/docs/fundamentals/logs.md | Documents Downloader torrent log behavior and how it relates to verbosity flags. |
| docs/site/docs/fundamentals/database.md | Extends --batchSize guidance with an MDBX growth/high-water-mark heuristic. |
| docs/site/docs/fundamentals/caplin.md | Notes that Beacon API is opt-in (--beacon.api=...) and adds RAM cost guidance. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Suggested by @AskAlexSharov, and it follows from the disk-tab removal in this PR: the guide walks the reader through running an Erigon node on Polygon PoS, but `bor-mainnet` no longer exists in cmd/utils/flags.go, so there is no chain config for the network being described. Removed with every live reference to it: - the guide itself - the Polygon card on the Easy Nodes landing page, and "Polygon" in that page's description frontmatter - the "Bad block / Invalid Merkle on Polygon network" entry in help-center/common-errors-and-solutions, whose fix is to restart Bor and Heimdall services — Polygon-only, so it goes with the network Archived versions keep the guide. v3.3 and v3.4 did support Polygon, so versioned_docs is deliberately untouched. The support statement itself still lives in fundamentals/supported-networks. Build drops from 74 to 73 pages; `onBrokenLinks` is `throw`, so a passing build is proof no page still links to it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
8a6280a to
305fb63
Compare
…gontech#22973) Docs-only. Found while auditing the `release/3.6` docs backlog in erigontech#22970 — the same stale content is on `main`. ## The Polygon tab documents a network this binary cannot sync `hardware-requirements.mdx` carried a Polygon tab with September 2025 disk sizes, behind a warning that the last Polygon-supporting series is 3.1.\* and that the figures are no longer updated. On `main`, `bor-mainnet` has **zero occurrences** in `cmd/utils/flags.go` — there is no Polygon chain config left. So those were recommended disk sizes and RAM for a network the binary has no way to run. Removed. Nothing else is lost: - The support statement itself lives in [Supported Networks](https://docs.erigon.tech/fundamentals/supported-networks) and in the "How to run a Polygon node" guide — neither is touched. - The frozen `v3.4` and `v3.3` versioned snapshots keep their Polygon tab, which is correct: those series did support it. `release/3.5` already handles this via erigontech#22919, and erigontech#22970 does the same for `release/3.6`. This closes the last branch still publishing the figures. ## Unrelated finding on this branch, not fixed here While comparing `main` against `release/3.6`, `configuring-erigon.mdx` on this branch documents: ``` * `--witness.cache.blocks value` *(New in v3.6)*: ... ``` That flag does **not exist on `release/3.6`** — `witness.cache.blocks` has no occurrences in that branch's Go code, along with `--witness.cache.head-capture`, `--witness.cache.maxmb` and `--caplin.resume-max-staleness-epochs`. They are all `main`-only. So either the flags missed the 3.6 branch cut, or the label should name the next series. I have deliberately **not** guessed a version — someone who knows the release plan should decide whether to correct the label or backport the flags. Flagging it rather than silently editing. ## Verification - `npm ci && npm run build` in `docs/site` — clean. `onBrokenLinks`, `onBrokenMarkdownLinks` and `onBrokenAnchors` are all `throw`, so a passing build proves no link or anchor depended on the removed tab. - `python3 docs/site/scripts/render-disk-sizes.py --check` — page still matches `disk-sizes.json` (the tab held hardcoded values, not `ds:` markers, so the record is unaffected). - `python3 docs/site/scripts/generate-llms.py --check` — 4 llms artifacts match, 74 pages. - `python3 -m unittest discover docs/site/scripts` — 78 tests, OK. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Bloxster <gianni.morselli@erigon.tech> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…llms - help-center/troubleshooting: `kill -6 <pid>` -> `kill -SIGABRT <pid>`. The name is more readable than the number and matches the `kill -SIGUSR1` example directly above. The explicit-PID guidance from the earlier review stays. - get-started/hardware-requirements: missing comma after "For failure protection". - get-started/hardware-requirements: the testnet captions said "the only mode measured on this network", which is unambiguous inside a tab but not once the llms renderer flattens the tabs away — a linear reader could not tell which network each table belonged to. Each caption now names its network (Sepolia / Hoodi / Chiado), which fixes the artifact without touching the renderer. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
@yperbasis ready for another look when you have a moment — all three of your points are addressed, plus Copilot's. Your review (
Copilot ( Also added since you looked, on @AskAlexSharov's suggestion: the Polygon easy-node guide is removed along with its landing-page card and the Bor/Heimdall "Bad block" error entry — Gates: build clean at 73 pages ( |
…ontech#22975) Suggested by @AskAlexSharov. Companion to erigontech#22973 (Polygon disk tab) — opened separately because that PR had already entered the merge queue and its branch was frozen. ## Why `docs/get-started/easy-nodes/how-to-run-a-polygon-node.md` walks the reader through running an Erigon node on Polygon PoS. On `main`, `bor-mainnet` has **zero occurrences** in `cmd/utils/flags.go` — there is no chain config for that network, so the guide describes something the binary cannot do. ## What was removed - the guide itself - the **Polygon card** on the Easy Nodes landing page, and `Polygon` in that page's `description` frontmatter - the **"Bad block / Invalid Merkle on Polygon network"** entry in `help-center/common-errors-and-solutions` — its remedy is restarting Bor and Heimdall services, which is Polygon-only, so it goes with the network ## What was deliberately kept - `versioned_docs/version-v3.3` and `version-v3.4` keep their copies of the guide. Those series **did** support Polygon, so the archived pages remain correct — and the archive-link guard expects them. - The support statement itself stays in [Supported Networks](https://docs.erigon.tech/fundamentals/supported-networks). The same change is on `release/3.5` (erigontech#22919) and `release/3.6` (erigontech#22970), so all three branches drop it together. ## Verification - `npm ci && npm run build` — clean, **74 → 73 pages**. `onBrokenLinks`, `onBrokenMarkdownLinks` and `onBrokenAnchors` are all `throw`, so a green build proves no remaining page links to the removed guide. - `generate-llms.py --check` — 4 artifacts match, 73 pages. - `render-disk-sizes.py --check` — unaffected, still matches. - `python3 -m unittest discover docs/site/scripts` — 78 tests, OK. - Confirmed no tracked live reference remains outside `versioned_docs/`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Bloxster <gianni.morselli@erigon.tech> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
yperbasis
left a comment
There was a problem hiding this comment.
Follow-up review at 4e4aec0; every point checked against the branch. My previous review had nine points, not three — the six still open are repeated below as one-liners marked (carried), merged with new findings from a second pass.
Medium
- Polygon removal is incomplete.
docs/site/docs/index.mdx:30,docs/site/docs/get-started/index.mdx:52-58, and the 404 overridedocs/site/src/theme/NotFound/Content/index.tsx:6still advertise "… and Polygon nodes";llms-full.txtlines 9 and 28 mirror the first two. The build cannot catch this — the cards link to/get-started/easy-nodes/, which exists; only the text is stale. Same sweep:docs/site/help-center/common-errors-and-solutions.md:59-61("Connect: connection refused") still uses Heimdall as its example and cites--bor.heimdall.url, which does not exist on this branch (the flag is--bor.heimdall,cmd/utils/flags.go:831) — reword to a generic external service or drop the entry. - (carried)
docs/site/docs/fundamentals/security.md:24— "impose additional firewall requirements" still names the wrong cause for the reserved-range half; blocking those ranges is self-protection against Hetzner's abuse detection, not a Hetzner-imposed rule. - (carried)
llms-full.txt:99,107— the mainnet/gnosis tables are still unlabeled; the caption fix covers only the three new tabs. Emit each TabItem label as a heading ingenerate-llms.pyand add a regression test, or file the tracked follow-up.
Low
- (carried)
docs/site/docs/get-started/hardware-requirements.mdx:33— use a stable identifier and the non-root fsck pass:UUID=… /data ext4 defaults,noatime 0 2. - (carried)
hardware-requirements.mdx:22— the CPU cell still reads "Full nodes8–16 cores", the same concatenation defect fixed one row up. - (carried)
hardware-requirements.mdx:50— "with the sole exception of the--prune.modeflag" is contradicted by the three "Execution layer only" tabs; say "unless a tab notes otherwise". - (carried)
docs/site/docs/fundamentals/optimizing-storage.md:9— the intro names only ext4, while the linked Filesystem section allows ext4 or XFS. docs/site/docs/get-started/installation/index.mdx— step "3. Running Erigon" still runs./build/bin/erigondirectly after the optional 2.4 install to/opt/erigon. Add to 2.4 that you then run the installed copy (e.g./opt/erigon/erigon), and that/optneeds sudo or a pre-created writable directory.docs/site/src/data/disk-sizes.json— theci_last_updatedbump to 2026-07-29 misstates the field:update-disk-sizes.py:80stamps it only after a CI artifact update, nothing enforces "at or after everymeasured_at", and nothing consumes it. Revert the bump, or rename/document it as a general last-updated date.docs/site/help-center/common-errors-and-solutions.md:63— "## Chain-Specific Issues" is now an empty heading; drop it.- The three new disk figures byte-match the #22866 refresh measured on v3.6 archive nodes, while the mainnet/gnosis tabs come from a different measurement set (2.03 vs 2.17 TB, 673.59 vs 731.16 GB). Fine as indicative numbers; consider a source note in the captions or a re-measure on a 3.5 node.
PR body
- "#22915 … must not merge until this has deployed" is stale: #22915 merged on 2026-08-03. Main's README now points readers to the Hetzner troubleshooting anchor for "the reserved IPv4 ranges to block", which only this PR adds, and the sync-times table and the Beacon-API RAM note currently exist nowhere — so this should land promptly once the points above are fixed.
- "there is no
qa-sync-from-scratch-*workflow" is false for this branch:release/3.5hasqa-sync-from-scratch.yml(matrix: mainnet, gnosis, sepolia, hoodi, chiado; weekly cron plus push) andqa-sync-from-scratch-minimal-node.yml. Thein-sync-delayhalf is true and the published "not measured by CI" wording can stay, but correct the body — and the sync-times table could later be driven from that workflow.
…d entry The easy-node guide for Polygon went away in 305fb63, but three card descriptions still advertised it — the landing page, the Get Started index, and the 404 override. The build could not catch these: the cards link to /get-started/easy-nodes/, which still exists, so only the prose was stale. The "Connect: connection refused" help-center entry used Heimdall as its example and pointed at `--bor.heimdall.url`, which does not exist on this branch (the flag is `--bor.heimdall`, cmd/utils/flags.go:831). Reworded to services Erigon actually talks to here, naming flags verified against cmd/utils/flags.go: `--authrpc.addr`, `--authrpc.port`, `--private.api.addr`. Dropped the now-empty "Chain-Specific Issues" heading left behind by the Polygon cleanup. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- hardware-requirements: the CPU cell had the same concatenation defect fixed
one row up ("Full nodes8-16 cores"); the fstab example used a /dev/nvme name
and fsck pass 1, so it now uses a UUID and pass 2 for a non-root filesystem.
- hardware-requirements: "with the sole exception of the --prune.mode flag" was
contradicted by the three execution-layer-only tabs — now "unless a tab notes
otherwise".
- hardware-requirements: the Sepolia, Hoodi and Chiado figures come from the
#22866 refresh, measured on the snapshotter-bm-v36-* archive nodes, while the
mainnet and gnosis tabs come from a separate measurement set. Captions now say
so rather than leaving the mismatch implicit.
- security: blocking the reserved ranges is self-protection against Hetzner's
abuse detection, not a firewall rule Hetzner imposes. Split the two halves.
- optimizing-storage: the intro named only ext4 while the Filesystem section it
links allows ext4 or XFS.
- installation: `make install` runs `mkdir -p "$(DIST)"` (Makefile:630), so a
path under /opt needs root; step 3 also still ran ./build/bin/erigon after the
optional install, which is not the copy a system user would run.
- disk-sizes.json: revert the ci_last_updated bump from 81b46de. That commit
read the field as a file-level last-updated, but update-disk-sizes.py:80 only
stamps it after a CI artifact refresh, and every row here is source: manual —
so the bump claimed a CI update that never happened.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ibutable strip_mdx() removed <TabItem> wholesale along with every other JSX component, which dropped the label — often the only thing saying which variant the block below describes. On the hardware-requirements page that left five disk-size tables back to back with no network names, three of them sharing an identical two-column schema and differing only in values. Each label now becomes a heading. The level is one below the enclosing section so a tab never outranks its own section, but never shallower than the first heading after the tab group — otherwise that heading would be swallowed as a subsection of the last tab, which is the shape the installation page has (h1, OS tabs, then "### All Operating Systems"). Nine regression tests cover the level rules, sibling tabs, the three label quoting forms Docusaurus accepts, unlabelled tabs, and TabItem inside a fence. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The Filesystem section said what to use but never why, so it read as taste.
It justified ext4/XFS only by provenance ("that is what we measure"), which
gives an operator nothing to reason with when their platform offers ZFS.
Both halves of the reasoning were already published elsewhere in these docs and
simply not connected to the filesystem advice:
- known-issues already says to optimise disk *latency*, not throughput or IOPS.
Added the two reasons Erigon's reads cannot be pre-warmed — the EVM reads
arbitrary state, and Merkle trie updates read whichever nodes happen to
neighbour the updated key — so every filesystem layer lands on top of them.
- known-issues already documents btrfs `autodefrag` multiplying write I/O by up
to 100x. Both anchors are now linked from here.
Names the filesystems to avoid and the mechanism for each: ZFS keeps its own
write-ahead log and its own cache (ARC), which competes with the OS page cache
that Erigon's memory-mapped database depends on; btrfs is a copy-on-write
B-tree of pages underneath MDBX, itself a B-tree of pages.
This does not pick ext4 over XFS. The mechanism argues against copy-on-write
and database-like filesystems, and neither ext4 nor XFS is one, so the existing
"either, and we have not measured XFS" wording stands.
Source: Erigon core devs, via the maintainer of these docs.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Cross-checking this PR against the rest of the site turned up three places that disagreed with it. FAQ #5 published "as of September 2025, a full node requires about 920GB, an archive node around 1.77TB" and then, in the same sentence, pointed at Hardware Requirements "for up-to-date figures" — where this branch measures 419.04 GB and 2.03 TB. So the full-node figure was overstated by 2.2x and archive understated, on the companion page to our most-visited one. Replaced with the qualitative answer plus the pointer: duplicating the numbers in a second, unguarded place is what let them drift, and hardware-requirements is marker-driven with a CI guard (render-disk-sizes.py) while the FAQ is not. layer-2-networks: the page description advertised "Running Erigon for Polygon PoS, Bor, and other Layer 2 networks", but Polygon appears nowhere in the page — it covers OP-node and Erigon Nitro. It also fed that stale line into llms.txt. multiple-instances: dropped the "# For Polygon networks" label from --sync.loop.block.limit, which is a generic flag (node/cli/flags.go:117, "maximum number of blocks to process per loop iteration", default 5000) and not Polygon-specific. The snippet also mixed `export` with bare CLI flags in one bash fence, so it was split into the env var and the flags, and the env var now uses the ERIGON_ prefix that dbg_env.go:43 explicitly asks users for. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
yperbasis
left a comment
There was a problem hiding this comment.
Combined review at 621e0b8: my remaining points plus five raised by a Codex pass, each verified against the branch before inclusion. All points from my previous review are addressed.
High
docs/site/help-center/troubleshooting.md:66-71— the ports table this PR now endorses (security.md:24sends readers there "for the ports their edge firewall must allow") listsP2P (Caplin) | 9000 | TCP+UDP, but Caplin's defaults are--caplin.discovery.port=4000(UDP) and--caplin.discovery.tcpport=4001(TCP) —cmd/utils/flags.go:869-878; 9000 is the external-CL convention (Lighthouse, Prysm). Also "Hetzner applies a stateless firewall" is wrong for Cloud (stateful, per Hetzner's firewall FAQ) and right only for dedicated/Robot. Fix the Caplin rows (keep a 9000 row only if labelled for external CLs) and split or soften the stateless sentence. The defective lines predate this PR, but the new link makes them load-bearing. (Codex)
Low
docs/site/scripts/generate-llms.py:153— grouping splits tab sets on any heading between two TabItem openings, so a heading inside the first tab's body would demote the following sibling tab one level and attribute it to that heading. No current page has headings inside tab bodies, so this is latent — but grouping on<Tabs>/</Tabs>boundaries is cheap while the code is fresh. (Codex)docs/site/scripts/generate-llms.py:91— a label-less<TabItem value="X">emits no heading (pinned bytest_generate_llms.py:173), while Docusaurus renders thevalueas the visible label whenlabelis absent. Fall back tovalue, so a future unlabelled tab does not silently reintroduce the unlabelled-tables problem this PR fixes. (Codex)docs/site/docs/get-started/hardware-requirements.mdx:40— "impossible to predict, and therefore impossible to pre-warm" overclaims: Erigon itself pre-warms viadoms.EnableTrieWarmup(true)andexec.BlocksReadAhead(execution/stagedsync/exec3.go:200,223). "cannot be fully predicted, so part of every block's reads lands cold" keeps the argument intact. (Codex)docs/site/docs/get-started/hardware-requirements.mdx:51— "compression, encryption, dedup — each cost latency" is a blanket claim; OpenZFS guidance treats LZ4 compression as a frequent net win for throughput workloads. Drop compression from the list or scope the claim to the read path of this latency-bound workload. (Codex)docs/site/help-center/frequently-asked-questions-faqs.md:15— "a measured figure and a measurement date for every network and pruning mode" overclaims: Sepolia/Hoodi/Chiado measure archive only (Full and Minimal read-), and the page tabs five networks, not every supported one. Say "for the networks and pruning modes it measures".- Draw the Polygon line deliberately:
interacting-with-erigon/bor.md, the Polygon Bridge/Heimdall gRPC sections ingrpc.md, and the twobormentions ininteracting-with-erigon/index.mdstill document Polygon-only APIs with no support-status note. They are not wrong — the namespace is wired (rpc/jsonrpc/daemon.go:152) andcmd/utils/flags.goblank-importspolygon/chain, so--chain=bor-mainnet/amoyremain selectable (which also means "no occurrences of bor-mainnet in cmd/utils/flags.go" tested the wrong thing). Keep them with a one-line note pointing at Supported Networks, or remove them in a follow-up. Not a blocker.
PR body
- "#22915 … must not merge until this has deployed" — stale; it merged 2026-08-03.
- "there is no
qa-sync-from-scratch-*workflow" — false on this branch:qa-sync-from-scratch.ymland the minimal-node variant both exist. - "78 tests" — now 87.
- The intro's "
ci_last_updatedhas to sit at or after everymeasured_at" metadata fix was subsequently reverted in bb80611; drop or reword.
The breakdown was labelled "Real numbers from a Nov 2024 mainnet archive node" and totalled 2.3 TB — a figure predating Erigon 3's current snapshot format, and the same vintage of staleness #22866 removed from the README. It also only listed the state and history subdirectories, leaving the largest component to a parenthetical "the remaining ~1.2 TB is mostly block/transaction .seg data". Re-measured today on a release/3.5 mainnet archive node (ext4), and now lists every component including the block/transaction segments, which turn out to be the single largest at 993.33 GB — roughly half the datadir. Total 2041.15 GB, consistent with the 2.03 TB published on hardware-requirements for 2026-07-19 plus two weeks of chain growth. The measurement also confirms the claim made a few paragraphs above, that chaindata/ rarely exceeds 20 GB even on an archive node: it is 9.82 GB here. Also: - FAQ #5 now carries only the pointer to hardware-requirements, with no figures of its own — a second copy of the numbers is what let them drift in the first place. - multiple-instances: the remaining bare SNAPSHOT_MADV_RND now uses the ERIGON_ prefix, so the page no longer shows both spellings. Both resolve (common/dbg/dbg_env.go:38-52 tries bare, then prefixed), but the bare form logs a warning telling the user to add the prefix. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Four pages spelled the same variable two different ways — `ERIGON_SNAPSHOT_MADV_RND` in known-issues and best-practices, bare `SNAPSHOT_MADV_RND` in performance-tricks, configuring-erigon and multiple-instances — with nothing explaining that both are accepted. Both do work: `envLookup` (common/dbg/dbg_env.go:38-52) tries the bare name and then `ErigonEnvPrefix + name`. But it logs "use ERIGON_ prefix for env" when it resolves the bare form, so the prefixed spelling is the one Erigon asks for. Rather than rename one variable, the CLI reference now states the convention once — it applies to every variable that goes through the `Env*` helpers, not just this one — and the usage examples use the prefixed form. The reference entries keep their bare declared names, which is what appears in the source. Scoped deliberately: the Docker variables (`DOCKER_UID`, `DOCKER_GID`, `XDG_DATA_HOME`) are excluded, since they are read by Docker and the XDG spec rather than by Erigon, and prefixing them would break them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…rding Caplin's ports were wrong in the Hetzner note, which this PR made load-bearing by pointing security.md at it. The table listed "P2P (Caplin) 9000 TCP+UDP"; Caplin's defaults are --caplin.discovery.port=4000 (UDP) and --caplin.discovery.tcpport=4001 (TCP), cmd/utils/flags.go:869-878. 9000 is the external-CL convention, so it is now labelled as such instead of attributed to Caplin. The "Hetzner applies a stateless firewall" sentence was also true only of dedicated/Robot — the Cloud firewall is stateful — and now says which is which. generate-llms.py, two latent defects in the tab-heading code added here: - Tab sets were grouped by "no heading between two TabItems", so a heading inside one tab's body would split the set and demote every tab after it. Sets are now delimited by <Tabs>…</Tabs>. No current page has headings inside tab bodies, so this was latent; the generated artifacts are byte-identical. - A TabItem with `value` but no `label` emitted no heading, while Docusaurus renders `value` as the visible label — so a future unlabelled tab would have silently reintroduced the unlabelled-tables problem this PR fixes. It now falls back to `value`. The test that pinned the old behaviour is replaced by three: the fallback, label-wins-over-value, and no-attributes-at-all. Two overclaims in the new filesystem prose: - "impossible to predict, and therefore impossible to pre-warm" was wrong — Erigon pre-warms via doms.EnableTrieWarmup(true) and exec.BlocksReadAhead (execution/stagedsync/exec3.go:200,223). Now "does pre-warm what it can, but ... cannot be fully predicted, so part of every block's reads lands cold", which is the argument that was actually intended. - "compression, encryption, dedup — each cost latency" was blanket; LZ4 is often a net win. Compression is dropped and the claim scoped to the read path. Also: the FAQ pointer no longer implies every network and mode is measured (Sepolia, Hoodi and Chiado are archive-only), and bor.md carries a note that 3.1.* is the last series officially supporting Polygon, since the namespace is still wired and --chain=bor-mainnet still selectable. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
All points from the 12:26 review are addressed at 01a3ec9. Each was verified against the branch before acting on it; none turned out to be mistaken.
The four PR-body points were already fixed before this review arrived — the description now corrects the Two things you flagged earlier that I want to confirm are settled rather than silently dropped:
Two changes in this round go slightly beyond your points, both surfaced by a site-wide consistency pass — flagging them explicitly so they are not a surprise in the diff:
Also standardised the Gates on every commit: |
yperbasis
left a comment
There was a problem hiding this comment.
Combined review at 01a3ec9: four points from a Codex pass plus three of mine, each verified before inclusion — against the branch, Hetzner's Cloud firewall FAQ, Prysm's docs, and the linked Stack Exchange answer.
High
docs/site/help-center/troubleshooting.md:66— "make sure the following ports are reachable inbound and outbound" is a trap on Hetzner Cloud: outbound stays allow-all only while no outbound rule exists. Per Hetzner's FAQ, "If you define one or more outbound rules, the outbound direction also changes to implicit 'deny'" — so a reader who adds outbound rules for these three ports cuts off DNS, NTP and HTTPS, including webseeds, and snapshot download breaks. Split the advice: Cloud — inbound rules only, leave outbound rules empty; Robot — stateless, rules in both directions including return traffic. The closing line at line 76 then also needs the Robot panel as the counterpart to the Cloud Console /hcloud. The sentence predates this PR, but the rewrite and the newsecurity.mdlink make it load-bearing. (Codex)
Medium
docs/site/help-center/troubleshooting.md:69-72— the table omits the Downloader's BitTorrent port42069TCP+UDP, whichfundamentals/default-ports.md:14marks Public; with Cloud's inbound default-deny, following this table means no incoming torrent peers. Add the row and state the table is not exhaustive, linking Default ports as the authoritative list (it also carries the opt-in shutter port). (Codex)docs/site/help-center/troubleshooting.md:74— "conventionally9000TCP+UDP for Lighthouse, Prysm and friends": Prysm defaults to 13000 TCP / 12000 UDP, and Lighthouse additionally uses QUIC on 9001 UDP. Name the clients that actually default to 9000 (Lighthouse, Teku, Nimbus) or defer to the client's own docs. (Codex; found independently too)
Low
docs/site/help-center/troubleshooting.md:99— "The same list expressed in iptables syntax" overclaims: the linked answer covers 14 of the 16 ranges, deliberately omitting127.0.0.0/8and255.255.255.255/32— an OUTPUT drop on loopback would break local inter-component traffic (e.g. RPC Daemon →127.0.0.1:9090). Say "near-identical" and keep the omission as a caveat.docs/site/docs/fundamentals/configuring-erigon.mdx:573— "read by Docker rather than by Erigon" is wrong forXDG_DATA_HOME: Erigon reads it on Linux to resolve the default datadir (node/paths/paths.go:52,node/ethconfig/config.go:140), just via plainos.Getenvwithout prefix support. Reword to "which do not take theERIGON_prefix".docs/site/docusaurus.config.ts:95— deleting the Polygon guide leaves/get-started/easy-nodes/how-to-run-a-polygon-nodea 404 for external links, and the client-redirects plugin already has a precedent entry. Add a redirect to/fundamentals/supported-networks(or to the frozen/v3.4/…copy of the guide).docs/site/scripts/generate-llms.py:83—_TABITEM_TAGmatches within one line, so a valid multiline<TabItemopening tag emits no heading and the later multi-line component strip deletes the label. Latent — no current page writes one — but the fix is small: accumulate lines until>before matching, plus a regression test. (Codex)
The wording fixes need the usual generate-llms.py regeneration.
| --- | ||
| title: "Layer 2 Networks" | ||
| description: "Running Erigon for Polygon PoS, Bor, and other Layer 2 networks." | ||
| description: "Running Erigon alongside an OP-node, and Erigon Nitro for Arbitrum." |
There was a problem hiding this comment.
@yperbasis , @awskii -- is this statement still valid to publish in docs ?
There was a problem hiding this comment.
Yes — this line should publish. The old description ("Running Erigon for Polygon PoS, Bor, and other Layer 2 networks") named content the page does not contain; the new one matches the page's two actual sections — running an op-node alongside Erigon, and Erigon Nitro. The subject is real and public: erigontech/nitro-erigon on Docker Hub is active ("Erigon L2 Arbitrum archive node", last pushed 2026-03-30), and the main-fe4c973 tag the page pins exists.
Two problems in the section body predate this PR (it only touches the description line) and belong in a follow-up rather than here: the Docker command's --l2rpc="http://rpcserver:port never closes its quote, so the command is broken as written; and the pinned tag is a year old while v0.0.7/v0.0.8 exist. The Nitro team should confirm the recommended tag and whether the "Arbitrum Sequencer" status wording is still current.
| - [CLI Reference](https://docs.erigon.tech/fundamentals/configuring-erigon): Complete CLI flag reference for Erigon — all startup options, environment variables, and configuration settings. | ||
| - [Supported Networks](https://docs.erigon.tech/fundamentals/supported-networks): Mainnet, testnets, Gnosis, Polygon, and all other chains Erigon can sync. | ||
| - [Layer 2 Networks](https://docs.erigon.tech/fundamentals/layer-2-networks): Running Erigon for Polygon PoS, Bor, and other Layer 2 networks. | ||
| - [Layer 2 Networks](https://docs.erigon.tech/fundamentals/layer-2-networks): Running Erigon alongside an OP-node, and Erigon Nitro for Arbitrum. |
There was a problem hiding this comment.
This file is generated: the line mirrors the description: front matter of fundamentals/layer-2-networks.md via generate-llms.py, so it follows whatever we decide there — answered on that thread.
lystopad
left a comment
There was a problem hiding this comment.
@awskii , @yperbasis pls review these document lines. Should we publish as it is written now?
Moved here from #22919 so that all easy-node content changes land in one place. The guide walks the reader through running an Erigon node on Polygon PoS, but `bor-mainnet` no longer exists in cmd/utils/flags.go, so there is no chain config for the network being described. Removed with the references that pointed at it: - the Polygon card on the Easy Nodes landing page, and "Polygon" from its description; - the "Bad block / Invalid Merkle on Polygon network" entry in help-center/common-errors-and-solutions, which linked to the deleted guide. Only the link had to go for the build to pass; dropping the whole entry is an editorial call, made because its advice was to restart Bor and Heimdall. Its parent "Chain-Specific Issues" heading held nothing else, so it goes too. The connection-refused entry in the same file is generalised here rather than separately, because it used `--bor.heimdall.url` as its worked example — a flag that does not exist at all. The real flag is `bor.heimdall` (cmd/utils/flags.go:831); `bor.heimdall.url` appears nowhere in the Go source. It now points at the Engine API and inter-component address flags, which is what a reader hitting that error today is actually misconfiguring. Added a client redirect from the removed URL to fundamentals/supported-networks, following the existing precedent for the NAT page move. The guide was published for a long time, so without one every inbound link 404s. This does not finish removing Polygon from the docs, and is not meant to: configuring-erigon still documents `--bor.heimdall`, `--bor.withoutheimdall`, `--bor.period`, `--bor.minblocksize` and the `--polygon.*` flags, and supported-networks, bor.md and grpc.md all still cover Polygon. Reference material for a network people may still run against an older series is a separate question from a tutorial for one that has no chain config. Build drops from 74 to 73 pages; `onBrokenLinks` is `throw`, so a passing build is proof no page still links to it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SFH8scMUyJQ8Pd8dMP7kMr
…ine TabItem All seven points from the 2026-08-05 review, each verified against source or the cited upstream document before changing anything. **High — the firewall advice was a trap on Hetzner Cloud.** "Reachable inbound and outbound" was written for both product lines, but Cloud's outbound stays allow-all only while no outbound rule exists; per Hetzner's FAQ, defining one flips the whole direction to implicit deny. A reader who added outbound rules for these ports would cut off DNS, NTP and HTTPS — webseeds included — and break their own snapshot download. Now split: Cloud gets inbound rules only with the outbound list left empty, Robot gets rules in both directions because it is stateless. The closing line gained the Robot panel as the counterpart to the Cloud Console and `hcloud`. **Medium — the port table omitted the Downloader.** `42069` TCP+UDP is marked Public in fundamentals/default-ports.md:14, so under Cloud's inbound default-deny the table as written meant no incoming torrent peers. Row added, and the table now says it is not exhaustive, pointing at Default ports as the authoritative list. **Medium — the external-CL port was wrong for one of the clients named.** "Conventionally 9000 TCP+UDP for Lighthouse, Prysm and friends" — Prysm defaults to 13000 TCP and 12000 UDP, and Lighthouse also uses 9001 UDP for QUIC. Now names the clients that do default to 9000 (Lighthouse, Teku, Nimbus), gives Prysm's actual defaults, and says to check the client's own docs rather than assuming. **Low — "the same list expressed in iptables syntax" overclaimed.** The linked answer covers 14 of the 16 ranges, leaving out `127.0.0.0/8` and `255.255.255.255/32` on purpose. Now "near-identical", with the reason: an OUTPUT drop on loopback would break Erigon's own inter-component traffic, such as the RPC Daemon reaching the core node on 127.0.0.1:9090. **Low — the XDG_DATA_HOME claim was mine and it was wrong.** Erigon reads it directly to resolve the default datadir (node/paths/paths.go:52, node/ethconfig/config.go:140); it is merely grouped under the Docker variables in the doc. The tip now draws the distinction that actually holds — those variables do not take the `ERIGON_` prefix — instead of claiming Erigon never reads them. **Low — the removed Polygon guide left a 404.** Added a client redirect to fundamentals/supported-networks, following the existing precedent for the NAT page move. The guide itself remains readable in the v3.4 archive. **Low — a latent bug in the TabItem heading code added earlier in this PR.** `_TABITEM_TAG.search(line)` matched within a single line at both call sites, so an opening tag with its attributes spread over several lines produced no heading and then lost its label to the generic multi-line component strip. No current page writes one, but the failure would have been silent. Replaced with `_tabitem_tag_at`, which accumulates lines until the tag closes while tracking quote state, so a `>` inside an attribute value does not end it early either; both call sites skip the consumed attribute lines. Two regression tests cover the multiline tag and the angle-bracket-in-label case — 90 tests to 92, all green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SFH8scMUyJQ8Pd8dMP7kMr
|
All seven addressed in 2493b91. Each verified against source or the cited upstream document first — two of them were my own errors, noted below.
High — the firewall note. Confirmed against Hetzner's FAQ. "Reachable inbound and outbound" applied to both product lines, but Cloud's outbound is allow-all only while no outbound rule exists, so a reader adding outbound rules for these ports would deny their own DNS, NTP and HTTPS — webseeds included — and break the snapshot download they were trying to fix. Now: Cloud — inbound rules only, outbound list left empty; Robot — both directions, because it is stateless. The closing line gained the Robot panel (Server → Firewall) alongside the Cloud Console and Medium — the Downloader port. Medium — the external-CL ports. Correct, and it was wrong for one of the three clients it named. Now: Lighthouse, Teku and Nimbus default to Low — the iptables link. Now "near-identical", with the omission explained rather than just flagged: an Low — Low — the Polygon 404. Redirect to Low — the multiline Gates: @lystopad's comments on this PR are not addressed in this commit — handling them separately. |
yperbasis
left a comment
There was a problem hiding this comment.
Follow-up review at 2493b91. All seven points from my previous review are addressed and verified against the branch, and the gates hold: 92 script tests, render-disk-sizes.py --check and generate-llms.py --check clean locally, docs-site / build green in CI with broken links/anchors set to throw. A fresh pass over the full diff found one new point.
Medium
docs/site/docusaurus.config.ts:101-103— the redirect comment's rationale is false on this branch: "bor-mainnet has no chain config after 3.1".polygon/chain/config.go:82-86registersBorMainnet(chainspecpolygon/chain/chainspecs/bor-mainnet.json) ininit(), and the blank import atcmd/utils/flags.go:79wires it into--chainresolution (chainspec.ChainSpecByName,cmd/utils/flags.go:1725) — so--chain=bor-mainnetstill resolves a full chain config. The PR's ownbor.md:10states the opposite, correctly: "Thebornamespace is still wired and--chain=bor-mainnetremains selectable". This is the misconception corrected in the 2026-08-04 round, re-entered in the newest commit. Give the true reason — e.g. "The Polygon easy-node guide is removed: 3.1.* is the last series that officially supports Polygon. Inbound links land on the support statement; the guide is still readable in the v3.4 archive." The PR body's correction paragraph repeats the claim ("the page therefore describes a network with no chain config") and needs the same fix — it becomes the merge record.
Verified in this round
- Hetzner: the Cloud/Robot split with the FAQ quote, inbound-only on Cloud, the Robot panel named; the
42069row plus the non-exhaustive note; per-client external-CL ports; "near-identical" iptables wording with the loopback rationale; the XDG rewording; the Polygon redirect (v3.4 archive still carries the guide; versioned docs untouched). _tabitem_tag_at: the quote-tracking assembler is correct,_label_of's regexes match across newlines, fence handling is preserved, and the two new tests pin the multiline tag and thelabel="Version > 3.1"case. The regenerated artifacts label all five disk tables, and the installation page's OS tabs stay siblings of "All Operating Systems".- The
ERIGON_-prefix examples all hold:MDBX_LOCK_IN_RAM,SNAPSHOT_MADV_RND,SAVE_HEAP_PROFILEandHEAP_PROFILE_THRESHOLDare read viadbg.EnvBool/EnvUint(common/dbg/experiments.go:41-77), andenvLookupfalls back to the prefixed name (common/dbg/dbg_env.go:38-53). disk-sizes.jsonbyte-to-display values check out; theci_last_updatedbump is confirmed reverted; the newdatabase.mdbreakdown sums exactly to 2041.15 GB; the torrent-log wording matchesdownloadercfg.go:249(minof slog levels picks the more verbose threshold, forwarding gated by Erigon's own logger levels).
@lystopad I've answered your two threads inline. Short version: yes, the new description line should publish — it fixes a line that named content the page never had, and the Nitro image it names is real and active. The Nitro section body has two pre-existing problems (an unclosed quote in the Docker command, and a year-old pinned image tag) that deserve a follow-up, not a blocker here.
yperbasis
left a comment
There was a problem hiding this comment.
Combined review at 2493b91, following up on yesterday's: four points from a Codex pass, each verified against the branch or the cited upstream document before inclusion. The fourth — the docusaurus.config.ts:101-103 redirect comment — is already the Medium in my previous review (independently confirmed: polygon/chain/config.go:82-86 still registers bor-mainnet), so it is not repeated here.
Medium
-
docs/site/docs/fundamentals/layer-2-networks.md:3and bothllms.txt— the refreshed description advertises instructions that are not operational and overstates Nitro. (Codex)- The op-node section's Erigon command (
--caplin.blobs-immediate-backfillalone) leaves the Beacon API off — thecaplin.mdchange in this very PR says it "is not served until you enable it with--beacon.api=<namespaces>" — and the section never mentions a beacon endpoint, while--l1.beaconis among op-node's minimum required flags for blob retrieval. Blob sidecars are served under thebeaconnamespace (cl/beacon/handler/handler.go:356). As written, the setup cannot sync any post-Ecotone OP chain — that is, all of them. - "Erigon Nitro for Arbitrum": the official image description reads "support for Arbitrum sepolia network. Arbitrum One support is in progress and not yet publicly available", and the page's own heading says "for Sepolia (experimental)". The canonical run command on Docker Hub also quotes
--l2rpccorrectly and includes--l2rpc.receipt(needed for Timeboost and correctArbitrumSubmitRetryableTxgas); ours has the unclosed quote and omits the receipt endpoint.
The section body predates this PR, but the new description and regenerated
llms.txtpromote it. Minimum for this PR: description → "…experimental Erigon Nitro for Arbitrum Sepolia" (this amends my answer on @lystopad's thread — publish, with that precision). The body repair (enable--beacon.api, name--l1.beacon, fix the Nitro command) can land here or as a tracked follow-up. - The op-node section's Erigon command (
-
docs/site/help-center/troubleshooting.md:69— the Robot half is not followable: "you do need rules in both directions", but only the inbound service-port table follows. Per Hetzner's firewall docs the Robot firewall is stateless in both directions and "if none of the rules apply, then the packet will be discarded" — so enabling it with just these rules drops all return traffic: DNS replies, webseed HTTPS responses, outbound peer dials. Hetzner's own recipe adds an incoming rule for destination ports 32768–65535 with TCP flagack, plus UDP reply allowances. Add those return rules, or link Hetzner's firewall docs as the recipe and keep our table as the Erigon-specific service ports. (Codex)
Low
docs/site/scripts/generate-llms.py:107-188— the scanner matches<TabItemon any non-fenced line, so valid non-component text corrupts. Reproduced on this branch: a line containing inline code with a TabItem tag gains a spurious### Linuxheading and loses the span's content; two same-line sibling tabs lose the second label silently; a JSX-commented tag{/* <TabItem label="Old"> */}emits a heading. All three are latent — every current occurrence is a plain tag at line start — but the code is new in this PR and the fixes are small: skip inline code spans and{/* … */}ranges, and iterate matches within a line. Regression tests for the three cases either way. (Codex)
…ng modes (#23113) Stacked on #22919 — merge that first. The testnet tabs this fills in only exist on that branch, so basing here keeps the diff to a single commit. ## What this does #22919 added Sepolia, Hoodi and Chiado tabs with an **Archive-only** figure measured on a **v3.6** node, footnoted as indicative, and `-` placeholders for Full and Minimal. This replaces all of it with a complete 3×3 matrix measured on **v3.5.4**, the series this branch deploys from. | Tab | Archive | Full | Minimal | | --- | --- | --- | --- | | Sepolia | 1.10 → **1.04 TB** | – → **238.71 GB** | – → **218.06 GB** | | Hoodi | 133.73 → **115.85 GB** | – → **48.36 GB** | – → **45.61 GB** | | Chiado | 29.64 → **26.95 GB** | – → **13.32 GB** | – → **13.16 GB** | ## Provenance Every cell comes from one sweep: one binary (`3.5.4-01a3ec91`), one measurement script, each node synced from scratch and confirmed holding the live tip before measuring (head age at confirmation 0.4–3.6 s). Values are whole-datadir minus `temp/` scratch — the same basis as the existing mainnet and Gnosis rows. ## Three things worth reviewer attention **Archive figures all move down.** That is a change of measurement basis (v3.6 → v3.5.4, plus this script's whole-datadir-minus-temp), not chain shrinkage. Worth stating explicitly, since a shrinking archive would otherwise read as an error. **`"Execution layer only"` was inaccurate and is dropped.** `caplin/` is 1.08 GB — 4% of the Chiado archive total — and it *is* inside the measured total. The figures are standard Erigon + embedded Caplin with only `--prune.mode` varied, which matches the section intro and the mainnet/Gnosis rows. **Chiado Minimal and Full land within 0.16 GB.** This is real, not a copy-paste error: the chain is young enough that pruning has almost no history to remove. The tab now says so, to avoid it being read as evidence that pruning modes barely differ in general. ## Deliberately not included Sync times were measured but are not published — they describe one host's disk and 88 Mbit link, not what a reader should expect. The testnet tables stay at two columns. Mainnet and Gnosis carry "Disk Size (Recommended)" and RAM columns; disk was measured here, RAM was not, and inventing hardware recommendations seemed worse than omitting them. Happy to add them if maintainers want to set the values. ## Checks - `render-disk-sizes.py --check` — OK, page matches `disk-sizes.json` - `generate-llms.py --check` — OK, 4 files, 73 pages - `python3 -m unittest discover docs/site/scripts` — 92 tests, OK - `npm ci && npm run build` — clean, no broken links or anchors - Rendered and verified on a local `npm run serve`: 5 tabs, 15 cells, 0 stale markers, 0 leftover placeholders 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01SFH8scMUyJQ8Pd8dMP7kMr Co-authored-by: Bloxster <gianni.morselli@erigon.tech> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
The comment claimed bor-mainnet has no chain config after 3.1. It does: polygon/chain/config.go registers BorMainnet in init(), and cmd/utils/flags.go blank-imports that package to wire it into --chain, so --chain=bor-mainnet still resolves a full chain spec. bor.md:10 in this same branch says as much. Give the real reason instead: 3.1.* is the last series that officially supports Polygon. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SFH8scMUyJQ8Pd8dMP7kMr
Docs-only. Targets
release/3.5because that is the branchdocs-deploy.ymlpublishes from — the same changes onmainreach no readers. Forward-port torelease/3.6andmainto follow.Three things, plus review-fix commits. The third was #22962, fast-forwarded into this branch so the site-side work reviews as one unit.
An earlier commit here bumped
ci_last_updatedindisk-sizes.jsonon the theory that it must sit at or after everymeasured_at. That was wrong and has been reverted:update-disk-sizes.py:80stamps the field only after a CI artifact refresh, nothing consumes it, and every row in the file is currentlysource: manual— so the bump asserted a CI update that never happened. Renaming or wiring up the field is a separate change.1. Polygon disk figures out, Sepolia / Hoodi / Chiado in
The Polygon tab carried September 2025 figures behind a warning that the final Polygon-supporting series is 3.1.*. The numbers are no longer measured, so the tab is removed. Correction to an earlier version of this description: it said the "How to run a Polygon node" guide was being kept — a later commit in this branch removes that guide too, since 3.1.* is the last series that officially supports Polygon. The support statement itself still lives in Supported Networks, which this PR does not touch, and a client redirect now points the removed URL there.
Sepolia, Hoodi and Chiado had no disk figures anywhere despite being listed as supported and synced by QA. Added with archive only; Full and Minimal read
-, because only the QA full-node and minimal-node sync runs produce disk-usage figures and both matrices pin mainnet and gnosis. Filling those cells is a QA-capacity decision rather than a docs edit.2. ext4 or XFS on a single NVMe; RAID 0 and ZFS advice dropped
The Overview table recommended RAID 0 for multiple disks and said ZFS "may be considered for Archive nodes for their data integrity features, but complex RAID-Z setups are generally not recommended" — two directions in one cell, and no longer matching the footprint. An archive node is ~2 TB, so it fits on one 4 TB drive: striping gains no capacity we need while doubling the chance of losing the datadir.
Replaced with a Filesystem section: ext4 or XFS on one NVMe device, mounted
noatime. Anything else is called unverified rather than bad, since we have not measured it. RAID 0 (striping for speed) is separated from redundancy (mirroring for reliability) so the section agrees withhelp-center/best-practices.mdandhelp-center/troubleshooting.mdinstead of contradicting them.optimizing-storage.mdopened by recommending "a fast NVMe-RAID disk" and now points at the new section.The section then said what to use without saying why, which reads as taste and gives an operator nothing to reason with when their platform offers ZFS. Two subsections now carry the reasoning, both anchored to material already published in these docs and merely not connected to the filesystem advice:
known-issuesalready says to optimise disk latency, not throughput or IOPS. Added the two reasons Erigon's reads cannot be pre-warmed: the EVM reads arbitrary state, and Merkle trie updates read whichever nodes neighbour the updated key. Every filesystem layer lands on top of those reads.known-issuesalready documents btrfsautodefragmultiplying write I/O by up to 100x, and both anchors are now linked from here.This does not pick ext4 over XFS. The mechanism argues against copy-on-write and database-like filesystems, and neither ext4 nor XFS is one, so the "either, and XFS is unmeasured" wording stands. Sourced from Erigon core devs.
Site-wide consistency pass
Checking the rest of the site against the refreshed figures turned up four pages that disagreed with them:
render-disk-sizes.pywhile the FAQ is not.fundamentals/database.mdcarried a datadir breakdown labelled "Nov 2024" totalling 2.3 TB, and left the largest component to a parenthetical. Re-measured on a release/3.5 mainnet archive node: block/transaction segments are 993.33 GB — about half the datadir — and are now a listed row. Total 2041.15 GB, consistent with the 2.03 TB published here for 2026-07-19 plus two weeks of growth. It also confirms the page's own claim thatchaindata/stays under 20 GB on archive: it is 9.82 GB.fundamentals/layer-2-networks.mddescribed itself as "Running Erigon for Polygon PoS, Bor, and other Layer 2 networks", but Polygon appears nowhere in the page — it covers OP-node and Erigon Nitro — and that stale line was feedingllms.txt. The remaining Polygon references in the docs are reference material for shipped code (thebornamespace, the Polygon Bridge gRPC API,--polygon.wit-protocol) and are deliberately kept.fundamentals/multiple-instances.mdlabelled--sync.loop.block.limit"For Polygon networks"; it is generic (node/cli/flags.go:117, default 5000). The snippet also mixedexportwith bare CLI flags in one fence and is now split.Finally, four pages spelled the same environment variable two ways (
ERIGON_SNAPSHOT_MADV_RNDvs bareSNAPSHOT_MADV_RND) with nothing explaining that both resolve.envLookup(common/dbg/dbg_env.go:38-52) tries the bare name then the prefixed one, and logs "use ERIGON_ prefix for env" for the bare form — so the CLI reference now states the convention once, and the examples use the prefix. The Docker variables are excluded, since Docker and the XDG spec read those rather than Erigon.3. README-only operator content moved onto the site
Previously #22962, fast-forwarded into this branch. Six items existed only in
README.md, so the README could not drop them without the content being lost:get-started/hardware-requirementshelp-center/troubleshooting, linked fromfundamentals/securityfundamentals/logsmake DIST=<path> installget-started/installation--beacon.apienabling flagfundamentals/caplin--batchSizeguard against chaindata growthfundamentals/databaseFour further README items were checked and not migrated, because the site already documents them better: the SIGUSR1/pprof diagnostics, chaindata deletion, the WSL caveats, and the
--sync.loop.block.limitdefault. The README's "MDBX locks the db for exclusive access" rationale is deliberately dropped — it contradicts the single-writer/many-reader model infundamentals/database.This is the enabling half of the README cleanup. #22915 merged on 2026-08-03, so
main's README now points readers at the Hetzner troubleshooting anchor for the reserved IPv4 ranges — which only this PR adds — and the sync-times table and the Beacon-API RAM note currently exist nowhere. This should land promptly.Three corrections made while moving
The Hetzner list was corrupted. It carried
127.16.0.0/12 "Private-Use Networks RFC 1918"— a mangling of loopback and RFC 1918, with172.16.0.0/12already listed separately — plus two rows split across lines by the code fence. Restored to127.0.0.0/8 Loopback, and attributed to the IANA IPv4 Special-Purpose Address Registry rather than RFC 5735, which lacks100.64.0.0/10(RFC 6598) and is obsoleted by RFC 6890.The torrent-log level read backwards. The README said
logs/torrent.logis written at whichever is lower of--torrent.verbosityandWARN.erigonToSlogLevelis12 - 4*lvl(slogger.go:13), so higher Erigon verbosity maps to a numerically lowerslog.Level, and themin(…, slog.LevelWarn)atdownloadercfg.go:249selects the more verbose threshold. Reworded to match observed behaviour.The sync-times table lost its to-the-minute precision. The README published cells like
4h 23mwith no provenance, and nothing measures the figures as published. Correction to an earlier version of this description:release/3.5does carryqa-sync-from-scratch.yml(matrix: mainnet, gnosis, sepolia, hoodi, chiado; weekly cron plus push) andqa-sync-from-scratch-minimal-node.yml— the claim that no such workflow exists was wrong. What is absent is anin-sync-delaymeasurement, so the published "not measured by CI" wording still holds for these cells, and driving the table from that workflow is the obvious follow-up. Where CI observations existed they ran well above the published values (Ethereum full 5h06–5h48 across four runs against 4h23; Gnosis full 1h55–2h07 against 1h05). Replaced with coarse ranges spanning both, labelled not measured by CI:Kept rather than dropped because it is the only sync-time guidance published anywhere and docs(readme): drop content duplicated by docs.erigon.tech #22915 removes the README copy on the strength of this page. If a sync-from-scratch job lands on the publishing branch, this table should be driven by it.
The Beacon API "~6 GB RAM" figure is core-dev sourced and not verifiable in-repo. Kept, hedged, as the only guidance available on that cost.
4.
generate-llms.py: tab labels survive as headingsstrip_mdx()removed<TabItem>along with every other JSX component, taking the label with it. On this page that left five disk-size tables back to back with no network names — three sharing an identical two-column schema and differing only in values. The defect predates this PR but the new tabs made it much worse.Each label now becomes a heading. The level is one below the enclosing section, so a tab never outranks its own section, but never shallower than the first heading after the tab group — otherwise that heading is swallowed as a subsection of the last tab, which is exactly the shape
installationhas (h1, OS tabs, then### All Operating Systems). Nine regression tests cover the level rules, sibling tabs, the three label quoting forms Docusaurus accepts, unlabelled tabs, andTabIteminside a fence.Verification
python3 docs/site/scripts/render-disk-sizes.py --check— page matchesdisk-sizes.jsonpython3 docs/site/scripts/generate-llms.py --check— 4 llms artifacts matchpython3 -m unittest discover docs/site/scripts— 87 tests, OKnpm ci && npm run buildindocs/site— clean;npm run typecheckcleanServed the built site locally and checked the rendered pages: the three new tabs render with
-cells, no Polygon on the current version, theFilesystemsection and its two new subsections render with working anchors intoknown-issues, the refreshedfundamentals/databasebreakdown is correct, each migrated block renders as intended, and the frozenv3.4/v3.3snapshots correctly keep their Polygon tab.The site sets
onBrokenLinks,onBrokenMarkdownLinksandonBrokenAnchorsall tothrow, so a passing build proves every link and anchor added here resolves.Claims checked against source rather than assumed:
make DIST=<path> installagainstMakefile:626-633(it copies frombuild/binviaGOBIN);--beacon.apiagainstcmd/utils/flags.go:975— aStringSliceFlagwith no default, so the "not served until you enable it" wording is accurate.Claims added in later commits, checked against source:
--bor.heimdall.urldoes not exist (the flag is--bor.heimdall,cmd/utils/flags.go:831), so the connection-refused entry now names flags that do —--authrpc.addr,--authrpc.port,--private.api.addr;make installrunsmkdir -p "$(DIST)"(Makefile:630), so a path under/optgenuinely needs root;--sync.loop.block.limitis generic (node/cli/flags.go:117); theERIGON_prefix behaviour againstcommon/dbg/dbg_env.go:38-52.The
ci_last_updatedbump made earlier in this branch has been reverted —update-disk-sizes.py:80stamps it only after a CI artifact refresh, nothing consumes it, and every row issource: manual, so the bump asserted a CI update that never happened.Review round: 2026-08-05 (commit
2493b91f70)Seven points, each verified against source or the cited upstream document before changing anything. Two were my own errors.
High — the Hetzner firewall note was a trap on Cloud. It told readers to make the ports reachable "inbound and outbound" for both product lines, but Cloud's outbound stays allow-all only while no outbound rule exists; per Hetzner's FAQ, defining one flips the direction to implicit deny. A reader adding outbound rules for these ports would cut off DNS, NTP and HTTPS — webseeds included — and break the very download they were trying to fix. Now split: Cloud takes inbound rules only with the outbound list left empty, Robot needs both directions because it is stateless. The closing line gained the Robot panel alongside the Cloud Console and
hcloud.Medium — the port table omitted the Downloader.
42069TCP+UDP is marked Public infundamentals/default-ports.md:14, so under Cloud's inbound default-deny the table as written meant no incoming torrent peers. Row added, and the table now states it is not exhaustive, pointing at Default ports as the authoritative list.Medium — the external-CL port was wrong for one of the clients it named. "Conventionally
9000TCP+UDP for Lighthouse, Prysm and friends" — Prysm defaults to13000TCP and12000UDP, and Lighthouse additionally uses9001UDP for QUIC. Now names the clients that do default to 9000 (Lighthouse, Teku, Nimbus), gives Prysm's actual defaults, and says to check the client's own docs.Low — "the same list expressed in iptables syntax" overclaimed. The linked answer covers 14 of the 16 ranges, deliberately omitting
127.0.0.0/8and255.255.255.255/32. Now "near-identical", with the reason: anOUTPUTdrop on loopback would break Erigon's own inter-component traffic, such as the RPC Daemon reaching the core node on127.0.0.1:9090.Low — the
XDG_DATA_HOMEclaim was mine and it was wrong. Erigon reads it directly to resolve the default datadir (node/paths/paths.go:52,node/ethconfig/config.go:140); it is merely grouped under the Docker variables in the doc. The tip now draws the distinction that actually holds — those variables do not take theERIGON_prefix — instead of claiming Erigon never reads them.Low — the removed Polygon guide left a 404. Added a client redirect to
fundamentals/supported-networks, following the existing precedent for the NAT page move. Verified in the build output:<meta http-equiv="refresh" content="0; url=/fundamentals/supported-networks">with a matching canonical. The guide itself remains readable in the v3.4 archive.Low — a latent bug in the TabItem heading code added earlier in this PR.
_TABITEM_TAG.search(line)matched within a single line at both call sites, so an opening tag with its attributes spread over several lines produced no heading and then lost its label to the generic multi-line component strip. No current page writes one, so the failure would have been silent. Replaced with_tabitem_tag_at, which accumulates lines until the tag closes while tracking quote state, so a>inside an attribute value does not end it early either. Two regression tests cover the multiline tag andlabel="Version > 3.1"— 90 tests to 92, all green.Gates:
npm ci && npm run buildSUCCESS at 73 pages,generate-llms.py --checkclean,ruff checkandtsc --noEmitpass.Reviewed adversarially before opening and after each review round; the defects found were fixed in the review commits.
🤖 Generated with Claude Code