Skip to content

First-run setup never offers the SOCKS proxy it already supports: an .onion pool is unreachable unless the operator hand-edits config.json #520

Closed

Description

@VijitSingh97

What's missing

#400 gave a pool a socks5 key and shipped it in v1.17.0. Nothing in the product ever mentions
it to an operator who is not reading config.reference.json. First-run setup asks two questions,
writes a two-key pool, and an operator who typed an .onion address into the first one gets a
miner that cannot connect and no indication why.

This is the DIY install path only. On the Pithead appliance RigForge runs verify-only
(RIGFORGE_APPLIANCE=1) and its config.json is generated by Pithead, so this wizard never runs
there — that side is tracked in the Pithead repo.

What setup does today

ensure_config_exists() (rigforge.sh:269-352) asks exactly two things:

  • rigforge.sh:289 — Enter your pool URL (host:port, e.g. your-stack:3333):, re-prompted up to
    SETUP_URL_TRIES (3) and host-validated before the write (rigforge.sh:304-314). That
    hostname regex, ^[A-Za-z0-9]([A-Za-z0-9.-]*[A-Za-z0-9])?$, already accepts a v3 .onion.
  • rigforge.sh:327 — the stratum password.

Then it writes {pools: [{url, pass?}]} with jq -n (rigforge.sh:334-336). There is no third
question, and nothing downstream notices that the URL it just accepted is unreachable without a
proxy.

Everything else is already in place: _validate_host_port() (rigforge.sh:384-419) is shared
between url and socks5; parse_config() re-attaches the key (rigforge.sh:468-474);
generate_xmrig_config() passes pool fields through verbatim; tests/run.sh:359-450 covers the
parse and validation cases including an onion pool with a proxy.

The change

Two small things, plus the docs.

1. Setup infers the proxy from an .onion pool URL. The wizard is deliberately short and an
.onion address is already an unambiguous answer to "this needs Tor" — so when the entered URL's
host ends in .onion, default socks5 to 127.0.0.1:9050, say so on screen, and let the
operator override it. No new question for the LAN operator, who is almost everyone.

The alternative — always ask a third question — is worse: it is wrong to answer for every LAN rig,
and it invites a value where null is correct.

2. doctor checks the proxy is actually there. RigForge points the miner at a proxy; it does
not run one, and it should not start. But when a pool has socks5 set, doctor can say whether
anything is listening on that address and whether the miner is connected — today a missing local
tor is indistinguishable from a wrong pool address, from a dead stratum, from a bad password.
This is the whole difference between "install tor and it works" and a debugging session.

3. The docs currently say the opposite. Four places tell the operator Tor is not needed, which
was true before onion stratums existed and is now the first thing they read:

  • docs/pithead-integration.md:24 — "they do not need Tor"
  • docs/pithead-integration.md:169 — "Workers run on a trusted LAN and need no Tor"
  • docs/getting-started.md:28 — "Workers run on a trusted LAN and do not need Tor"
  • docs/hardware.md:20 — "workers do not need Tor"
  • docs/faq.md:114 — "Does the worker need Tor?"

The honest answer becomes: not on a LAN, which is the normal case; yes, and you install and run it
yourself, if your pool is an onion.

Scope — what stays out

RigForge does not install, start, or supervise a Tor client, on any platform. It is bare-metal and
single-purpose, the proxy is the operator's to arrange, and #400 settled this. An appliance rig's
Tor client is the Pithead image's job. This issue adds a prompt, a check, and honest docs — no
new dependency and no new daemon.

No ADR needed: 0001 and 0002 exist for the control path and remote upgrade, both of which changed
the trust model. This changes neither.

Testing

All of it fits the existing unit tier — tests/run.sh, no network, no Tor.

Proof Where
an .onion pool URL in setup writes a pool with the inferred socks5, and the operator's override wins tests/run.sh (drive ensure_config_exists on a piped stdin, as the existing setup tests do)
a clearnet pool URL writes no socks5 key — the minimal config stays byte-identical to today tests/run.sh
a rejected/re-prompted URL still persists nothing (the existing #344 property, unchanged) tests/run.sh
doctor reports a socks5 pool whose proxy is not listening, and is quiet when it is tests/run.sh with a loopback listener

tests/e2e/linux.sh needs no new leg: the container e2e proves setup runs, and this adds no
runtime dependency it would have to install.

Related, in the Pithead repo:

Activity

  1. added this to the v2.x - post-GA milestone on Sep 19, 2026
  2. added
    enhancementNew feature or request
    setupConfiguration and first-run setup
    securitySecurity-sensitive issue or hardening
    on Sep 19, 2026
  3. pithead-developer commented on Sep 24, 2026

    @pithead-developer
    Contributor

    Investigation brief (operator pre-read, 2026-09-23) — corrected

    Still present on develop head (dcdbc7e, 2026-09-08). ensure_config_exists() (rigforge.sh:269-352) only prompts for pool URL and password and writes {pools:[{url,pass?}]} (rigforge.sh:334-336) — no .onion detection, no socks5 offer. Everything downstream already supports it: shared validator _validate_host_port (comment block from rigforge.sh:384, function body at 390-419), parse_config re-attach (rigforge.sh:468-474), both landed with #400/#408 (merged as PR #404/#411, v1.17.0). doctor() (rigforge.sh:5439-5480) still has no check for whether a configured socks5 proxy is actually listening — confirmed no socks5 reference anywhere in doctor(). The 5 "no Tor needed" doc lines the issue names are unchanged and verified verbatim (docs/pithead-integration.md:24,169; docs/getting-started.md:28; docs/hardware.md:20; docs/faq.md:114). No PR references #520; not a duplicate.

    Root cause: the wizard was never revisited when #400 added socks5 plumbing — it still only ever writes the two original keys.

    Fix shape: three independent pieces, matches the issue's own plan — (1) in the wizard, default socks5=127.0.0.1:9050 when the entered host ends in .onion, let the operator override, write it through the existing jq path; (2) add one guarded TCP-dial check in doctor() for a configured socks5 address; (3) fix the 5 doc lines. Each is a handful of lines plus a tests/run.sh case, per the issue's own testing table.

    Evidence tier: tier-1 is sufficient — confirmed rigforge's own tier4-e2e (tests/e2e-pithead.sh, driven by bench-ci's tiers/rigforge/tier4-e2e.sh) has phases connect|worker-api|api-impact|network|stratum-auth|dashboard|dev-fee only; none exercise setup or doctor, and none touch Tor/onion. The fix changes no control-plane, deploy, or Tor-daemon-supervision surface (RigForge never runs Tor itself; doctor()'s new check is a passive, advisory TCP dial, not a change to what runs on a box). Existing container e2e already covers setup.

    Rulings needed: (a) doctor's proxy check advisory-only vs. hard-fail — recommend advisory, matching the existing API-refresh check; (b) env-var override for the onion default vs. interactive-prompt-only — recommend prompt-only, smaller diff.

    Triage: KEEP at its current milestone. rigforge#520 is already filed under v2.x - post-GA (frozen until GA per current release policy), which matches its own status: real, low-risk, ready to implement, already has full validator plumbing to build on, not a 2.0.0 blocker (no data loss, no Tari-fork interaction, and the DIY setup wizard's own scope note says it never runs against a fresh appliance install, since Pithead pre-generates config.json there and the wizard's file-exists guard short-circuits — RigForge sets no explicit RIGFORGE_APPLIANCE gate around ensure_config_exists, so this is a practical effect of appliance install order, not a hard code guard). No milestone move is warranted; the "security" label reflects a silent-failure/usability gap, not an active vulnerability.

    Verify against the code before relying on this; it was written by an investigator, not the implementer.

  4. pithead-developer commented on Sep 30, 2026

    @pithead-developer
    Contributor

    Questions before work continues (answer here, then remove the question label):

    1. Should an unreachable SOCKS proxy produce an advisory warning or make doctor exit nonzero? Default: advisory, following the investigation brief and preserving the existing miner-connection verdict.
    2. Should the onion proxy override be interactive-only or also support a new environment variable? Default: interactive-only, as recommended by the brief, because it meets the issue’s scope with less configuration.
  5. pithead-architect commented on Sep 30, 2026

    @pithead-architect

    Escalated to the human operator; the ruling lands in the runner's private question file and the worker resumes from it.

  6. pithead-developer commented on Sep 30, 2026

    @pithead-developer
    Contributor

    Merged in #548.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestsecuritySecurity-sensitive issue or hardeningsetupConfiguration and first-run setup

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions