The sweep (main's item 1): 199 tracked text files, 783 lines. The founder's full name, first name and possessive become "the founder" (sentence starts capitalised); the lowercase operating-system user name in WSL paths and commands becomes <user>; the second owner login becomes "the second owner login"; the three earlier businesses and the two other brands become "the other business", "the earlier entity", "the earlier business" and "another brand"; the Chrome profile rule names the igneum.network profile, not the profile's label. The standing commit login igneum-labs is not a founder term here: the fresh-repository step renames it in the history (docs/plans/history-rewrite.md, tools/repo/fresh-repo.sh). The patterns never appear in plain text in the tree (a plaintext list would be the hit): tools/ci/founder-strings.b64 (perl regex, tab, a sample per row) is read by tools/ci/founder-strings-check.sh (every tracked text file, perl, known-failed first: the self-test plants each row's sample in a fixture and the hit must name the file), by tools/community/discord-hooks.mjs (the guard's founder and business rows; the test takes its fixtures from the samples) and by tools/repo/fresh-repo.sh (the business names of the rewrite rules). site/forbidden-strings.txt carries the same patterns as b64: lines, decoded case-insensitive by site/scrub.mjs and tools/ci/launch-gates-check.mjs (whose fixture now plants an encoded made-up name). The check runs in the gate's tree checks on every merge. Not in this commit, by main's word: the 105 commit messages and 40 personal-identity commits that need the history rewrite (listed, not run), and the secrets found by gitleaks over the history (reported with owners). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
8 KiB
Seed nodes: plan
3 October 2026. Scripts in infra/seed-nodes/. The first seed is live.
The first seed
| Item | Value |
|---|---|
| Name | igneum-seed-1 |
| Address | 188.245.5.161:26611 (Hetzner primary IPv4, auto-delete off, so a rebuilt server keeps it) |
| Provider, location, type | Hetzner Cloud, Falkenstein (fsn1), cx23 (2 Intel vCPU, 4 GB, 40 GB), Debian 12 |
| Cost | USD 6.49 per month net, USD 7.79 gross, USD 0.0104 per hour, 20 TB traffic included (Hetzner API, 3 Oct 2026); plus the primary IPv4, USD 0.60 per month net, 0.72 gross (pricing API). Total about USD 7.09 net, USD 8.51 gross per month. The account bills in USD: the pricing API reports currency: USD, VAT 20% |
| Firewall | inbound tcp 26611 from anywhere, tcp 22 from anywhere (the founder's instruction; SSH_SOURCE=me narrows it to this Mac's IP), icmp; RPC bound to 127.0.0.1 only |
| Network | the shared devnet (--devnet, no suffix), built from vendor/igneum-node HEAD d62708a8 plus the uncommitted finality v2 work and igneum-pow HEAD, with --features igneum-pow |
| Role | p2p open, no mining, address manager on (serves RequestAddresses), --nodnsseed, UPnP off, --externalip set |
| How the Mac reaches it | the Mac's live node sits behind NAT (192.168.68.64), so the seed cannot dial in; the Mac dials out. The addPeer RPC on the live node is refused ("Method unavailable in safe mode. Run the node with --unsaferpc"), so the working path is a relay: infra/seed-nodes/addpeer-from-mac.sh relay start, a second non-mining igneumd on the Mac (appdir /tmp/igneum-seed-relay, RPC 127.0.0.1:26680, wRPC 28680, p2p 127.0.0.1:26681) with --addpeer=192.168.68.64:26611 --addpeer=188.245.5.161:26611; it syncs from the live node and the seed syncs from it. The live node is untouched. When the live node is next restarted by hand, add --addpeer=188.245.5.161:26611 to its flags and the relay is no longer needed |
infra/seed-nodes/seeds.txt holds exactly 188.245.5.161:26611.
Verified 3 Oct 2026, 22:19 to 22:26 UTC: build on the VM 1,530 s (25.5 min, 2 vCPU, 2 jobs, 6 GB swap unused);
igneumd/2.1.0 started with the finality v2 parameters, "External address is publicly routable 188.245.5.161:26611";
the relay on the Mac connected to it at once (protocol 12) and to the live node (protocol 11); the seed completed IBD
from the relay and reported isSynced: true at 22:25:39 UTC with 12,204 blocks and sink a0a776bb129c..., the same
block count and sink the live node reported in the same second. Peer exchange: without any configuration on their
side, the live node (/kaspad:2.1.0/, protocol 11) and the Windows PC's node (192.168.68.67, /igneumd:2.1.0/,
protocol 11) learned the seed's address from the relay and dialled it themselves; the live node's getConnectedPeerInfo
lists 188.245.5.161:26611 as an outbound peer, and the seed shows three inbound peers from the Mac's public IP.
health.sh: OK igneum-seed-1 188.245.5.161 p2p=open unit=active rpc=yes synced=True blocks=12204 headers=12204 peers=3.
The seed's own known-address table is empty because all three peers are behind NAT with no routable advertised address;
the first public node that connects will populate it.
How the seed list reaches clients
- Baked into the node.
vendor/igneum-node/consensus/core/src/config/params.rsholds the per-network seed list asdns_seeders: &'static [&'static str]onParams:MAINNET_PARAMS(line 617 on 3 Oct 2026),TESTNET_PARAMS(670),SIMNET_PARAMS(721),DEVNET_PARAMS(785), all&[]since the rename commit emptied Kaspa's nine mainnet and three testnet hostnames. The connection manager resolves each entry with(seeder, default_p2p_port).to_socket_addrs()(components/connectionmanager/src/lib.rs,dns_seed_single), so a plain IPv4 literal works as an entry with no DNS at all:dns_seeders: &["188.245.5.161"]onDEVNET_PARAMSis the whole change for the devnet, and the testnet list is the same shape with the testnet seeds. The port is the network's default p2p port (devnet 26611; the testnet port is still Kaspa's and must be set with the testnet genesis). The consensus engineer owns this edit. Two consequences for packages: a client that passes--nodnsseedignores the baked list (kaspad/src/daemon.rsline 573:dns_seedersis emptied when--nodnsseedor--connectis given), so the Windows node package (proto-cuda/windows-node/start-node.ps1) and the cloud scripts must drop--nodnsseedonce the list is baked; and the list is consulted only when the node is short of outbound peers, so a node with enough--addpeerentries never asks a seed. SEED_PEERSoverride in every package. Each launcher (Windows node, cloud devnet, seed nodes, the observer's helper node) readsSEED_PEERS(comma-separatedip:port) and turns every entry into--addpeer=<entry>; the baked list is the default when the variable is empty. This is what an operator uses when the baked list is stale between releases.- DNS names only as a convenience.
seed1.igneum.networkand so on can point at the same addresses (the domains are on Vercel nameservers, so a record each), anddns_seedersaccepts a hostname too; but the IPs are the source of truth because a DNS failure or a registrar problem must not stop bootstrapping, and because the public key of nothing is involved: a seed only hands out addresses, it cannot forge blocks.
Public testnet seed set
Three to five seeds across two providers and three regions. Proposed:
| Seed | Provider | Location | Type | Per month net |
|---|---|---|---|---|
| igneum-seed-1 | Hetzner | Falkenstein (EU) | cx23 | USD 6.49 (live) |
| igneum-seed-2 | Hetzner | Ashburn (US east) | cpx11 (2 GB) or cpx21 (4 GB) | USD 20.49 or 37.49 |
| igneum-seed-3 | DigitalOcean | Singapore (sgp1) | s-2vcpu-4gb | USD 24 (DO pricing page) |
| igneum-seed-4 (optional) | DigitalOcean | New York or Frankfurt | s-2vcpu-4gb | USD 24 |
| igneum-seed-5 (optional) | Hetzner | Helsinki | cx23 | USD 6.49 |
Three seeds: about USD 50 per month; five: about USD 80 (approximate, mixed currencies). The US seed is the expensive
one because Hetzner's current cx line is EU-only. Every seed is created with create-seed.sh (the DigitalOcean
variant reserves an IP in the same way) and provisioned with provision-seed.sh, which adds the seeds already in
seeds.txt as --addpeer entries so the seeds form a full mesh among themselves. health.sh checks them all.
Rotation
- Add before removing: create and provision the replacement, run
health.shuntil it is synced and has peers. - Bake the new list (
params.rs) and release packages with it; keep the old address in the list for one release so clients on the previous build still bootstrap. - Keep the old IP alive until the release after that (a Hetzner primary IP or a DO reserved IP costs under USD 1 per
month unattached, approximate), then delete the server and the IP, and remove the entry from
seeds.txtandseeds.tsv. - A compromised seed is the one case to remove first: delete the server, release the IP, bake and release the same day. The damage a bad seed can do is bounded (it hands out addresses; the node's handshake and PoW checks are unchanged), which is why the list may sit in a release rather than behind a signature.
Health and operations
health.sh (one line per seed: p2p port reachable from the Mac, unit active, RPC answering, synced, blocks and
headers, connected peers, known and banned addresses, disk, memory, version); --watch repeats every minute. The
seed's journal: ssh -i ~/.ssh/igneum_ed25519 root@188.245.5.161 journalctl -u igneumd -f. Updating the binary:
provision-seed.sh again (it rebuilds on the VM) or BUILD_WHERE=bin to push a binary built by the cloud-devnet
builder. The database format changes with some fork commits; a seed that refuses to start after an update is wiped
(rm -rf /var/lib/igneum/*) and resyncs from its peers.
No-spend rule
Only the first seed spends tonight (approved). The remaining seeds and the 20-node network wait for the morning.