Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
a12bc99
chore(deps): Bump actions/checkout from 7.0.0 to 7.0.1 (#326)
dependabot[bot] Jul 24, 2026
c383b03
fix(tune): runtime HugePages reservation is grow-only (#328) (#329)
VijitSingh97 Aug 1, 2026
32be3a4
feat(setup): appliance mode — baked deps, /run units, GRUB skip (pith…
VijitSingh97 Aug 1, 2026
256bc71
test(appliance): every systemctl enable must be --runtime (#797) (#331)
VijitSingh97 Aug 1, 2026
98ef9ac
release: v1.13.0
VijitSingh97 Aug 1, 2026
6d26898
chore(perf): record miner-0 baseline for v1.13.0
VijitSingh97 Aug 1, 2026
37acb86
fix(doctor): detect kernel lockdown directly instead of inferring it …
VijitSingh97 Aug 1, 2026
25abe9b
release: v1.13.1
VijitSingh97 Aug 1, 2026
fb5ecdb
chore(perf): record miner-0 baseline for v1.13.1
VijitSingh97 Aug 1, 2026
5ee5af9
fix(setup): probe the distro's cpupower package name so Debian instal…
VijitSingh97 Aug 2, 2026
c96ff74
feat(doctor): surface missing AES-NI / AVX2 instead of mining silentl…
VijitSingh97 Aug 2, 2026
ffbf759
release: v1.14.0
VijitSingh97 Aug 2, 2026
dea38d7
chore(perf): record miner-0 baseline for v1.14.0
VijitSingh97 Aug 2, 2026
0fa4e7b
docs(#352): align four sites with accepted ADR 0002 D4 semantics
VijitSingh97 Aug 15, 2026
8d15988
docs: stack-side stratum TLS shipped — rewrite the TLS section to rea…
VijitSingh97 Aug 15, 2026
d5c8656
feat(api): mirror the last control outcome into the enriched feed (#346)
VijitSingh97 Aug 15, 2026
f28020e
fix(status): serialize the hugepages array so the stats row renders (…
VijitSingh97 Aug 15, 2026
a0396d3
test(e2e): prove the appliance contracts against a real /etc in-conta…
VijitSingh97 Aug 15, 2026
3e2fea3
fix(tune): restore pre-sweep overrides when a live sweep is interrupt…
VijitSingh97 Aug 15, 2026
561cfed
fix(doctor,apply): read the miner's own pool-connection state instead…
VijitSingh97 Aug 15, 2026
ac477be
docs: CHANGELOG entry for the status abort fix (verifier catch)
VijitSingh97 Aug 15, 2026
122454d
docs: fifth 'non-latest' instance in D6's refusal list (verifier catch)
VijitSingh97 Aug 15, 2026
1dcc8df
chore: keep the jq filter on its executed line — kcov cannot cover st…
VijitSingh97 Aug 15, 2026
cc05922
Merge pull request #355 from p2pool-starter-stack/fix/341-status-huge…
VijitSingh97 Aug 15, 2026
d6c4c1e
Merge pull request #356 from p2pool-starter-stack/docs/342-tls-reality
VijitSingh97 Aug 15, 2026
2481c9f
Merge pull request #360 from p2pool-starter-stack/docs/352-adr0002-la…
VijitSingh97 Aug 15, 2026
e6c3be8
Merge pull request #361 from p2pool-starter-stack/test/348-appliance-…
VijitSingh97 Aug 15, 2026
7823889
Merge remote-tracking branch 'origin/develop' into fix/343-pool-reach…
VijitSingh97 Aug 15, 2026
ea7aac5
Merge pull request #357 from p2pool-starter-stack/fix/343-pool-reacha…
VijitSingh97 Aug 15, 2026
f69d3bc
Merge remote-tracking branch 'origin/develop' into feat/346-control-s…
VijitSingh97 Aug 15, 2026
86b5e8a
Merge remote-tracking branch 'origin/develop' into fix/347-tune-live-…
VijitSingh97 Aug 15, 2026
aace7c5
chore: collapse the double blank line the changelog merge left
VijitSingh97 Aug 15, 2026
b43832f
Merge pull request #358 from p2pool-starter-stack/feat/346-control-st…
VijitSingh97 Aug 15, 2026
8ff692d
Merge pull request #359 from p2pool-starter-stack/fix/347-tune-live-r…
VijitSingh97 Aug 15, 2026
ab69af7
release: v1.15.0
VijitSingh97 Aug 15, 2026
3304bf1
chore(perf): record miner-2 baseline for v1.15.0
VijitSingh97 Aug 15, 2026
66da05a
refactor(#353): polish sweep — verb ERR context, apply-plan drift, st…
VijitSingh97 Aug 15, 2026
1240e16
test(e2e-real): make the upgrade phase's forward leg mandatory, not o…
VijitSingh97 Aug 15, 2026
c421ac2
test(e2e-real): pre-flight the checkout path's traversability for Dyn…
VijitSingh97 Aug 15, 2026
bbf3e12
docs(RELEASING): promise only the perf-baseline practice the fleet ac…
VijitSingh97 Aug 15, 2026
fa130fb
Merge pull request #365 from p2pool-starter-stack/chore/round2-quality
VijitSingh97 Aug 15, 2026
44ca68d
fix(api): an unreachable worker API must not abort the run, or cry ab…
VijitSingh97 Aug 15, 2026
fc2bb36
release: v1.15.1
VijitSingh97 Aug 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
name: Lint (yamllint)
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false # zizmor: artipacked
# pipx is preinstalled on ubuntu-24.04 (same path as diff-cover/zizmor); pin the version so the
Expand Down Expand Up @@ -49,7 +49,7 @@ jobs:
name: Lint (markdownlint)
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false # zizmor: artipacked
# node is preinstalled on ubuntu-24.04; `make lint-md` runs the version-pinned markdownlint-cli2
Expand All @@ -66,7 +66,7 @@ jobs:
SHFMT_VERSION: "3.13.1"
SHFMT_SHA256: "fb096c5d1ac6beabbdbaa2874d025badb03ee07929f0c9ff67563ce8c75398b1"
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false # no pushes from CI; don't leave the token in .git/config (zizmor: artipacked)
# Install PINNED, checksum-verified shellcheck + shfmt instead of the runner's preinstalled
Expand Down Expand Up @@ -98,7 +98,7 @@ jobs:
name: Test suite
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false # zizmor: artipacked
# Ubuntu is RigForge's supported target. The suite still exercises the macOS code path here via
Expand All @@ -111,7 +111,7 @@ jobs:
name: Test suite (macOS)
runs-on: macos-14 # Apple silicon; pinned (not macos-latest) to avoid image drift
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false # zizmor: artipacked
# The Linux job only SIMULATES macOS (STUB_UNAME_S=Darwin + stubbed sed/launchctl). Here the suite
Expand All @@ -137,11 +137,14 @@ jobs:
name: End-to-end (Docker)
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false # zizmor: artipacked
# Runs the real script end-to-end inside a disposable Ubuntu container (RigForge's documented
# Linux target), exercising the genuine Linux deploy path and /etc idempotency with real tools.
# linux.sh runs TWO passes (a fresh container each): the standard deploy, then
# RIGFORGE_APPLIANCE=1 (#348) proving the appliance contracts against a real /etc — units in
# /run/systemd/system, no package installs, no fstab/limits/logrotate writes, --runtime enables.
- name: Run end-to-end suite
run: make test-e2e

Expand All @@ -156,7 +159,7 @@ jobs:
# so fall back to the pushed branch itself — that's an empty diff that trivially passes.
BASE_REF: ${{ github.base_ref || github.ref_name }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0 # diff-cover needs history to diff the PR against its base branch
persist-credentials: false # the fetch below is read-only on a public repo (zizmor: artipacked)
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/links.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
# lychee uses GITHUB_TOKEN to make authenticated GitHub requests and dodge the anon rate limit.
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false # zizmor: artipacked
- name: Install pinned lychee
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ github.ref_name }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
# Releasing goes through `gh` with GH_TOKEN below, not `git push`, so the checkout never
# needs the token left in .git/config (zizmor: artipacked).
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
GITLEAKS_VERSION: "8.30.1"
GITLEAKS_SHA256: "551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb"
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0 # scan EVERY commit, not just the tip — a secret is still a leak once pushed
persist-credentials: false # zizmor: artipacked
Expand All @@ -60,7 +60,7 @@ jobs:
env:
ZIZMOR_VERSION: "1.25.2"
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false # zizmor: artipacked
# pipx is preinstalled on ubuntu-24.04; same install path as diff-cover in ci.yml's coverage job.
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tool-bump.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
env:
GH_TOKEN: ${{ github.token }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false # zizmor: artipacked; the push authenticates explicitly below
- name: Check every pinned tool, open one PR per stale pin
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/xmrig-bump.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
pull-requests: write
actions: write
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
# zizmor: artipacked — never persist the token in .git/config; the push step below
# authenticates explicitly with the job token instead.
Expand Down
147 changes: 147 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,153 @@ All notable changes to RigForge are documented here. The format is based on

## [Unreleased]

## [1.15.1] - 2026-08-15

### Fixed

- **An unreachable worker API no longer aborts the run, or cries abort while succeeding (#364).**
The API readers had a "propagate" mode that let curl's exit escape, so an unreachable miner would
"surface upstream". Nothing upstream ever read it — every caller branches on an empty body — and
letting it escape broke two different ways depending on the bash running the script:

- **Any caller that was not guarded aborted outright.** Measured on a rig (Linux, bash 5.2): with
the API refusing connections, `tune`/`autotune`'s sampling loop and a bare `_status_api_summary`
both died with `[ERROR] rigforge aborted ... (exit 7)`. An API that went away mid-sweep — the
miner restarting under you — took the sweep with it. This is the failure #210 first hit on
miner-0 and papered over with a `|| true` at one call site.
- **On bash 3.2 (macOS) even the guarded callers printed the abort banner.** `status` wraps its
read in `( ... ) || true` and still emitted two `[ERROR] rigforge aborted while running 'status'`
lines to stderr before printing its correct "worker API not reachable" line and exiting 0 — the
reported shape. `set -E` inherits the ERR trap into the `$( )` the caller reads through, and 3.2
does not carry the caller's suppressed-errexit context into that child, so the trap fires there
once per frame the failure unwinds through. Bash 5.2 does carry it and stays quiet, which is why
this showed up on dev machines and not on the rigs. Spending the line operators are taught to
read as "something broke" on a routine, handled, exit-0 path is what made #341's real abort easy
to miss.

The mode is gone. Both readers now always return 0 with an empty body when the API is unreachable
— the contract every caller already assumed — so neither failure shape is reachable, and #210's
guard-inside-the-`$( )` idiom is no longer needed for these readers.

## [1.15.0] - 2026-08-15

### Added

- **The enriched feed mirrors the last control outcome (#346).** Pithead's host runner caps its
synchronous `/status` poll after a worker-apply, so a slow auto-rollback outruns it and the change
history row froze at `accepted`. The sister API's `rigforge` block now carries `control` —
`{change_id, status, reason}` read from the control status file — so the next routine poll of the
open read feed catches the terminal outcome without a new authenticated dial to the control port.
A rig that never took a control change, or an unreadable/malformed status file, serves
`control: null`; the mirror never breaks the feed.

- **`doctor` and `apply` now notice when the rig isn't mining at all (#343).** With `pools[0].url`
pointed at an unresolvable host, XMRig loops on DNS errors forever — and `doctor` still said "all
critical checks passed" while `apply` said "Applied config and restarted". Both now ask the miner
itself: its local API's `connection.uptime` is positive exactly while a stratum connection is
live. `doctor` gains a pool-connection check — connected reports the pool, connection age and
accepted shares; running-but-disconnected counts as an issue (the rig is not mining); a silent
API is advisory only; and with the service stopped, one guarded TCP dial of `pools[0]` stands in.
`apply` polls briefly after the restart and warns when no live connection appears — warn, never
refuse: the pool may be legitimately down at apply time, so the exit code stays 0.

### Fixed

- **An interrupted live sweep no longer persists the mid-sweep candidate (#347).** `tune --live`
(and `tune --now --long`) applies every candidate straight into `tune-overrides.json` and restarts
the miner on it, but the cleanup trap only restored the temp dir and the service — a Ctrl+C, a
dropped SSH session, or an error mid-sweep left an arbitrary half-measured candidate saved and
running, silently costing hashrate until the next re-tune. The trap now restores the pre-sweep
overrides and restarts the miner on them, through the same restore step the `--confirm` revert leg
uses. `autotune` (and `tune --now`) had the same gap with its per-trial prefetch merges; its trap
restores the pre-sweep mode via the same merge the sweep uses, so knobs pinned by an offline
`tune` survive the abort too.

- **`status` no longer aborts on a healthy rig (#341).** XMRig's `/2/summary` reports
`"hugepages"` as an array (`[pages, total]`); the status renderer fed it to jq's `@tsv`,
which rejects arrays — so the operator's first command printed an abort line instead of
the stats block, on every rig running v1.14.0. The renderer now joins the pair as
`HugePages: N/N`, scalars pass through, and the suite's shared fixture carries the real
array shape so the class can't return.

## [1.14.0] - 2026-08-02

### Added

- **Missing AES-NI / AVX2 is surfaced instead of mining silently slow (#338).** RandomX without
AES-NI falls back to XMRig's soft-AES path, roughly 4x slower, and nothing anywhere said why — the
last undelivered acceptance criterion from #1. `setup`/`apply` now warn at configure time when the
CPU flags lack `aes` (and, advisory, `avx2` — that one only slows dataset init), and `doctor`
counts a missing AES-NI as an issue. Judged only when an x86-style `flags` line exists in
`/proc/cpuinfo`; macOS, ARM and stubbed sandboxes read as unknown, and unknown never manufactures
an issue (the #333 lockdown stance). Never aborts: a knowingly-old rig is a valid choice.

### Fixed

- **Debian: dependency install no longer fails on `linux-tools-common` (#327).** The apt dependency
list named `linux-tools-common` unconditionally, but that package is Ubuntu-only — Debian ships
cpupower as `linux-cpupower` — and apt's install transaction is all-or-nothing, so the one unknown
name failed the ENTIRE install: git, build-essential and cmake never arrived either. `setup` now
probes with `apt-cache show` (the same guard the kernel-versioned `linux-tools-$(uname -r)`
package already had) and adds whichever name the distro actually ships; when neither exists it
warns and moves on — cpupower is a tuning aid, never worth losing the compiler toolchain over.

## [1.13.1] - 2026-08-01

### Fixed

- **`doctor` detects kernel lockdown directly instead of inferring it from MSR failure (#333).**
When kernel lockdown is active (distro kernels — Ubuntu, RHEL, Debian — enable it automatically
under UEFI Secure Boot), every `/dev/cpu/*/msr` write is denied and the MSR prefetcher mod
silently can't apply, costing ~5–15% RandomX. `doctor` only reacted after something downstream had
already failed, and its remedy for the most common cause was wrong: `msr.allow_writes=on` is dead
code under lockdown, because the kernel checks `security_locked_down(LOCKDOWN_MSR)` and returns
before the `allow_writes` filter is ever consulted (`arch/x86/kernel/msr.c`). `doctor` now reads
the actual state from `/sys/kernel/security/lockdown` *before* the MSR probes — cause before
symptom — and flags active lockdown (`integrity` and `confidentiality` both block the write) as a
counted issue naming the level, the cost, and the real fix (disable Secure Boot, with the
board-specific menu path). Reading beats inferring from `mokutil`: Secure-Boot-implies-lockdown is
a distro patch, not upstream behaviour. The three messages that guessed between causes now name
the one that applies, the missing-`msr`-module hint no longer blames Secure Boot (the in-tree
signed module loads fine under it — that's a modprobe/packaging problem), and `secure_boot` joins
the guided `bios` checklist (#80), leading it, verified against the same securityfs probe so
`doctor` and `bios` can't disagree. Unreadable securityfs stays advisory — unknown, never a
manufactured issue.

## [1.13.0] - 2026-08-01

The pithead#797 appliance release: an opt-in setup mode for the read-only appliance image —
baked deps, runtime units, image-owned kernel cmdline — plus a grow-only runtime HugePages
reservation so a co-resident stack's pool is never shrunk out from under it.

### Added

- **Appliance mode: `RIGFORGE_APPLIANCE=1` (pithead#797 R1).** One opt-in env flag for running
`setup` on the Pithead appliance image, whose root filesystem is read-only and whose `/etc` is a
volatile overlay — every write there vanishes at reboot, and the image's boot path re-runs setup
each boot instead of relying on persisted state. Under the flag, setup installs no packages (the
toolchain is baked at image build; if a required tool is absent, setup fails naming it), skips the
GRUB leg deliberately (the kernel cmdline, including any 1 GB-hugepage reservation, is
image-owned), renders its systemd units into `/run/systemd/system` and enables them with
`--runtime`, mounts `hugetlbfs` at runtime instead of appending to `fstab`, and skips the
`limits.conf` memlock append (the unit already sets `LimitMEMLOCK=infinity`). Runtime tuning is
unchanged: `modprobe msr`, the grow-only HugePages sysctl (#328), and the performance governor all
work on a read-only root — each decision proven on the pithead#797 R0 bench. `setup --dry-run`
previews the same decisions. Everything else (a normal Linux install, macOS) behaves exactly as
before.

### Fixed

- **Runtime HugePages reservation is grow-only (#328).** `tune_kernel`'s runtime sysctl wrote the
miner's computed requirement absolutely, which SHRINKS a pool another consumer already reserved
(a co-hosted pithead stack's p2pool/monerod share the same 2MB pool) down to its in-use floor —
zero free pages on both sides, measured live on the pithead#797 appliance bench. The write is now
availability-based: pages the miner can draw on = free + whatever a running miner already holds;
the pool grows by the shortfall only and never shrinks. Fresh single-purpose rigs see the same
reservation as before; re-runs that find enough available write nothing. This is the runtime half
of #305's co-resident keep-existing guard, and it applies with or without
`hugepages_reserve_extra_mb` set. The `setup --dry-run` plan previews the same decision.

## [1.12.0] - 2026-07-19

The pithead#597 producer release: the control-upgrade `/status` contract a one-click worker
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

[![CI](https://github.com/p2pool-starter-stack/rigforge/actions/workflows/ci.yml/badge.svg)](https://github.com/p2pool-starter-stack/rigforge/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)
![Platform: Ubuntu 22.04+](https://img.shields.io/badge/Platform-Ubuntu%2022.04%2B-E95420?logo=ubuntu&logoColor=white)
![Platform: Ubuntu 22.04+ / Debian 12](https://img.shields.io/badge/Platform-Ubuntu%2022.04%2B%20%2F%20Debian%2012-E95420?logo=ubuntu&logoColor=white)
[![Miner: XMRig](https://img.shields.io/badge/Miner-XMRig-F26822?logo=monero&logoColor=white)](https://github.com/xmrig/xmrig)
[![Companion: Pithead](https://img.shields.io/badge/Companion-Pithead-F26822)](https://github.com/p2pool-starter-stack/pithead)

Expand Down Expand Up @@ -51,8 +51,8 @@ you like to your stack's single endpoint.
`autotune` in `config.json` re-tunes on a monthly schedule.
- An opt-in `watchdog` restarts a wedged miner (alive but hashing 0 H/s), and with `max_temp_c` set
it stops the miner above that temperature and resumes once it cools.
- `doctor` health-checks HugePages, the MSR mod, the governor, and the service; `status` shows live
hashrate, pool, uptime, and shares.
- `doctor` health-checks HugePages, the MSR mod, the governor, the service, and the pool
connection (the miner's own view of it); `status` shows live hashrate, pool, uptime, and shares.
- `bios` is a guided, resumable walkthrough of the BIOS/UEFI changes RigForge can't make itself
(XMP/EXPO, SMT, PBO/Eco Mode), and re-verifies what took after the reboot.
- `backup` and `restore` snapshot your config and tuning; `support-bundle` collects a redacted
Expand Down Expand Up @@ -147,7 +147,7 @@ sudo ./rigforge.sh apply # regenerate config + restart (no rebuild)
git pull && sudo ./rigforge.sh upgrade # rebuild + restart if the XMRig pin moved

sudo ./rigforge.sh tune --now # run a live tune now — keep the best prefetch mode
sudo ./rigforge.sh doctor # health check: HugePages, MSR, governor, service
sudo ./rigforge.sh doctor # health check: HugePages, MSR, governor, service, pool connection
./rigforge.sh logs # follow live logs, no root needed (also: status; sudo for start / stop / restart)
sudo ./rigforge.sh # provision (or re-provision) the worker — idempotent
```
Expand Down
Loading