docs · fearminer 1.15.2

Start mining with FearMiner

Set up your first rig, then use the reference when you need more control.

options · Look up an error · HiveOS · mmpOS

On this page Set up your first rig
Start here
  1. Set up your first rig
  2. Start from the command line
Manage rigs
  1. Manage rigs from the cockpit
  2. The service
  3. Change common settings
  4. Set up FearMiner on HiveOS
  5. Set up FearMiner on mmpOS
Choose and tune mining
  1. Algorithms, fees and requirements
  2. Connect to your pool
  3. Choose and manage devices
  4. Check correctness and measure speed
  5. Automatic recovery and watchdogs
Automate
  1. Save settings in a configuration file
  2. Set up alerts
  3. Use the local API
  4. Control a running miner
  5. Read mining history
Understand and troubleshoot
  1. Read the terminal panel and logs
  2. Understand an error
  3. Privacy, downloads and local files
  4. Troubleshoot a rig
Full reference
  1. Find an option or command

Start here

Set up your first rig #

Follow these steps to connect a computer and start mining from the cockpit.

A rig is a mining computer. A mining sheet saves its coin, wallet address and pool settings.

  1. Check your computer and prepare your details

    Check support for your operating system and chosen algorithm. Have your public wallet address and pool connection details ready. Never enter your wallet’s recovery phrase.

    Expected result: You have supported hardware, a public address and a pool host and port.

    What we build, and what it needs
  2. Create your cockpit

    Open the web app and save its 12 recovery words. These recover the cockpit, not your cryptocurrency wallet.

    Expected result: Your cockpit is open and its recovery words are saved.

    Start with the cockpit
  3. Install and connect the rig

    Choose Add a rig, select the rig’s operating system and run the supplied command on that rig.

    Choose the rig’s OS in Add a rig: Linux, Windows or macOS on Apple silicon. For HiveOS or mmpOS, use the dedicated setup guides.

    Expected result: FearMiner is installed and enrolled in your cockpit.

    HiveOS and mmpOS setup
  4. Check that the rig appears

    Find it in the cockpit. A connected rig may be waiting for mining settings.

    Expected result: The rig is connected, even if it is not mining yet.

    Add a rig
  5. Apply a mining sheet

    Choose the coin, add your wallet address and pool, then apply the sheet to the rig.

    Expected result: The rig receives and checks your mining settings.

    Mining sheets
  6. Confirm that mining has started

    Look for mining activity and accepted shares. An accepted share is not a payment; your pool sets its payout schedule.

    Expected result: Hashrate is reported and the pool accepts your work.

    Where the money goes
  7. Know how to pause and return

    Pause or resume from the cockpit. Keep the recovery words somewhere you can find them when opening the cockpit on another device.

    Expected result: You can stop mining activity and return to the same fleet.

    Enrolment and the remote channel

Start from the command line #

Check hardware support and prepare your public wallet address and pool host and port.

What you need first: a wallet address #

YOUR_WALLET is a public receiving address from a wallet app or an exchange account. Never a private key, a seed phrase or a password.

The chain is read off the address, so the wallet picks the algorithm; the pool is yours to choose (Connect to your pool). Algorithms, fees and requirements gives the shape of each address, Privacy, downloads and local files the checks.

  1. Download and verify the archive for the rig’s OS, then unpack it and open a terminal in that folder. The manual download instructions below include all three platforms. Prefer to download?

  2. Example: Quantus. Replace POOL:PORT and YOUR_WALLET with your pool’s connection details and public receiving address. rig1 is the worker name. On Windows use .\fearminer.exe; on Linux and macOS use ./fearminer.

    ./fearminer -a quantus -o stratum+ssl://POOL:PORT -u YOUR_WALLET -w rig1
  3. first share accepted after 12.3 s
    hashrate 588.5 MH/s

    Example output. A hashrate and an accepted share confirm that mining has started and the pool accepted your work.

  4. Ctrl+C stops a foreground run cleanly. For an installed service, use fearminer service stop; closing a terminal does not stop the service.

    fearminer service stop

Installation and manual downloads #

Details and behavior

One line installs FearMiner, checks it against the release key and keeps it running as a service. It mines what your cockpit gives it, or your wallet on the pool you choose. The manual way, download, check, run, is right below it.

These generic commands install FearMiner. To connect a cockpit, use the command supplied by Add a rig. Without a wallet or mining sheet, the miner waits for settings.

The one line

The one line #

In the cockpit, Add a rig gives the exact line, your code already in it. On HiveOS the flight sheet runs the miner: one option to add.

Open the cockpit ↗
$ curl -fsSL https://get.fearminer.com | sh
with your cockpit's codecurl -fsSL https://get.fearminer.com | sh -s -- fm1_...
no cockpit: your wallet on your poolcurl -fsSL https://get.fearminer.com | sh -s -- --wallet YOUR_WALLET --pool stratum+ssl://POOL:PORT --worker rig1
the machine's service (sudo)curl -fsSL https://get.fearminer.com | sh -s -- --system
the binary only, no servicecurl -fsSL https://get.fearminer.com | sh -s -- --no-service
checksSHA256SUMS against the release key (minisign, or OpenSSL 3), then the archive against SHA256SUMS; without either tool, download.fearminer.com and GitHub must agree. On Windows the two hosts must agree, and fearminer verify checks the signature afterwards. Nothing runs before
installsa service of your account, no password: it starts with the machine (at your logon on Windows) and restarts after a crash; --system for the machine's, with sudo
minesthe mining sheet your cockpit gives it, or --wallet with --pool; with neither, it watches the cards and waits
thenfearminer service status, fearminer service logs (The service)
Prefer to download?

Prefer to download? #

The same files on both hosts:

Then check, unpack and run by hand:

The warning at the first run

Check the download with a tool that is not ours: the command above compares the archive against SHA256SUMS. minisign -Vm SHA256SUMS -P <the release key> checks the signature the same way. Once you trust the binary, fearminer verify SHA256SUMS does both offline (Privacy, downloads and local files).

$ curl -LO https://github.com/fearminer/fearminer/releases/latest/download/fearminer-linux-x86_64.tar.gz
$ curl -LO https://github.com/fearminer/fearminer/releases/latest/download/SHA256SUMS
$ grep ' fearminer-linux-x86_64.tar.gz$' SHA256SUMS | sha256sum -c -
$ tar xzf fearminer-linux-x86_64.tar.gz && cd fearminer-*-linux-x86_64
$ ./fearminer -o stratum+ssl://POOL:PORT -u YOUR_WALLET -w rig1

Linux

Verify the download before following the platform’s first-run instructions. Verify a download

Nothing of the sort happens on Linux or on HiveOS: no SmartScreen, no Gatekeeper, no quarantine flag to clear. Unpack, run fearminer verify, mine.

The pool is yours to choose: its host and port are on the pool's own page. FearMiner never picks one for you, and a wallet without a pool is refused (E224).

Flight sheet: a custom miner. Set up FearMiner on HiveOS has the full sheet and the HiveOS name of each algorithm.

Windows and macOS stop an unsigned binary at the first run; a scanner may file any miner under HackTool. What they say and what to click is below. Privacy, downloads and local files: checking the download is ours.

It works when you see this

It works when you see this #

job 9dd830e6 diff 18.25G
✔ 1/1 · GPU0 · 18.25G · 24 ms
hashrate 618.4 MH/s (10m 611.9, session 609.8, eff 598.2 / 97.8 %)

job 4b1c77a2 diff 40.0K
✔ 1/1 · CPU · 40.0K · 31 ms
hashrate 7.1 kH/s (10m -, session -, eff -)

A job, an accepted share, a hashrate: it is mining. The first block is a GPU rig, the second a CPU one.

eff and the averages read - until ten shares are accepted in the window. Read the terminal panel and logs reads the whole start-up block line by line.

To stop: q in the terminal panel, or Ctrl+C. Either one stops cleanly, exit code 0.

Where the money goes

Where the money goes #

An accepted share is not a payment. The pool credits it and pays you later.

which poolthe one you gave with -o, named by the pool line at start
your balanceon that pool's own dashboard, under the address you gave
when it is paidat the payout threshold and on the schedule that pool sets, minus that pool's own fee

The payout threshold, the schedule and the pool's fee are the pool's, not FearMiner's. FearMiner's own fee is separate and is shown in the terminal panel header (Algorithms, fees and requirements).

Manage rigs

web cockpit

Manage rigs from the cockpit #

Check your rigs and send commands from your phone or PC. The cockpit is free and uses end-to-end encryption.

Details and behavior

The cockpit at app.fearminer.com is free, needs no account and is end-to-end encrypted: the relay between it and your rigs passes sealed messages it cannot read. It shows the fleet's hashrate and history, sets what each rig mines, and pauses, resumes or restarts a rig.

Open the cockpit ↗

Add a rig

Add a rig #

1Open app.fearminer.com, Create my cockpit, write down the 12 words. They are your fleet: no account, no password, and the only way back on another device.
2Add a rig gives one line with your code in it (fm1_...). Run it on the rig (Set up your first rig).
3The rig shows up within seconds. Give it a mining sheet: it mines.

FearMiner already installed: fearminer enroll fm1_... on the rig, no restart. It prints the rig's name (XXXX-XXXX-XXXX-XXXX) and the fleet's; the cockpit shows the same names: compare them.

$ fearminer enroll fm1_...
$ fearminer remote status
Mining sheets

Mining sheets #

whatwhat a rig mines: the algorithm, the wallet and its pools (at least one, your choice); the cockpit's flight sheet
checkedby the rig, as a start would: the wallet against the chain, the pools, the options. A bad sheet is refused with the reason; the mining goes on as it was
appliedthe same algorithm reloads without a stop; another algorithm, or a rig that was only watching, restarts the miner, never the service
keptacross reloads and restarts, over the rig's own configuration (remote-sheet.json in the state directory); the previous sheet is kept for a one-gesture revert
TensorCasha sheet with its wss:// pool needs FearMiner 1.7.1 or later on the rig; the cockpit leaves an older rig out and says why. The pool's token is not in the sheet: the rig keeps it, started with -p token-file=<path>
no sheet yeta rig installed without a wallet watches its cards and waits for one

Cockpit updates are available for eligible Linux services. HiveOS manages its own updates; mmpOS needs the new release URL. On Windows and macOS, run the installer again.

What the relay sees

The wallet notice #

A new wallet applies at once by default. Set --remote-wallet-delay on a rig to make it wait; cancel a pending change from the cockpit or with fearminer remote cancel on the rig.

Details and behavior
whena sheet with another wallet than the one mined
waits--remote-wallet-delay minutes, 0 by default (applies at once); with a notice the rig mines to the old wallet meanwhile
announcedwith both addresses, to the notifiers (Set up alerts) and the rig's journal
cancelledfrom any cockpit, or fearminer remote cancel on the rig

With a notice, someone who got into your cockpit cannot move your hash in silence: you have that long to see it and stop it.

HiveOS · mmpOS #

HiveOS flight sheets and mmpOS profiles choose what to mine. The cockpit can monitor, pause, resume and restart these rigs. mmpOS is beta and has not been tested on a real rig.

HiveOS · mmpOS

Integration details and optional arguments
enrol--enroll fm1_... in the flight sheet's Extra config arguments (Set up FearMiner on HiveOS), or in an mmpOS miner profile's Arguments (Set up FearMiner on mmpOS, beta)
the cockpitshows the rig, pauses, resumes and restarts it
what it minesthe flight sheet decides; the rig refuses a mining sheet and says why. The same on mmpOS
the servicenot needed, and refused (E802): HiveOS or mmpOS runs the miner
Enrolment and the remote channel

Enrolment and the remote channel #

commandwhat it does
fearminer enroll CODEJoin the fleet of the code. The same fleet again changes nothing; another fleet is refused until --leave.
fearminer enroll --statusThe fleet this rig belongs to, its name, the channel.
fearminer enroll --leaveLeave the fleet at once: its commands are refused from then on. Mining goes on.
fearminer remote statusThe rig, its fleet, the channel, the link, the sheet and a pending one, the last ten commands. --json.
fearminer remote off · onoff refuses every remote command on this machine, whatever signs it, until on. Mining goes on.
fearminer remote cancelDrop a sheet waiting for its notice: the wallet stays.

The service #

A run made permanent: the same options as a run, after service install. The one line of Set up your first rig does it for you. Nothing is installed unless the check a start makes passes first.

Linuxa systemd unit of your account, started at boot (lingering on)
macOSa LaunchAgent of your account
Windowsa task at your logon, the miner in its own window
containerLinux without systemd (Vast.ai, RunPod, Docker): a background process of your account, as root there with --allow-root. Put ~/.local/bin/fearminer service start in the machine's start script (Vast.ai: the On-start script of the template) so it starts again after a restart
--systemthe machine's service, with sudo, on Linux and macOS; on Linux under a dedicated fearminer account
restartsafter a failure; not after a stop you asked for, nor after exit 2, 4 or 12
HiveOS, mmpOSrefused, nothing written (E802): the flight sheet runs the miner
$ fearminer service install -o stratum+ssl://POOL:PORT -u YOUR_WALLET -w rig1
$ fearminer service status
$ fearminer service logs
commandwhat it does
fearminer service install [OPTIONS]Check the options as a start would, copy the binary to a fixed place, write the settings, then declare, enable and start the service. Again: replaces the settings; with no option: refreshes the binary.
fearminer service statusInstalled or not, mining, monitoring or stopped, since when, pid, account, binary, settings, where the log is, the rate. --json.
fearminer service logsThe last 50 lines, then follows (Ctrl+C). --no-follow stops there.
fearminer service stop · start · restartStop it cleanly, the cards put back; it starts again with the machine. start and restart as named.
fearminer service uninstallStop and remove the service, the binary it placed and service.json. The settings, the history and the keys stay, each one named.
binary~/.local/bin/fearminer · ~/Library/Application Support/fearminer/bin/ · %LOCALAPPDATA%\Programs\FearMiner\; /usr/local/bin/fearminer with --system
settingsservice.toml in the configuration directory, readable by your account only; a change saved is applied within a second
logthe journal on Linux, the miner's own rotated log file on macOS and Windows; fearminer service logs shows it everywhere

E801 to E808 are the service's codes, E809 to E812 the remote channel's, E813 to E819 the updates' and E820 a refused benchmark's (Understand an error). A miner started by hand while the service runs stops at the lock (E210) and names the service.

change what matters

Change common settings #

Set your wallet, pool, algorithm, GPUs and CPU thread count. Start with the defaults for everything else.

Details and behavior

Everything else has a working default.

wallet-u WALLET.rig1The payout address, with an optional .worker. It picks the chain when -a is left out; it always comes with a pool (-o).
pool-o stratum+ssl://host:portstratum+ssl:// is a TLS port, stratum+tcp:// or a bare host:port a plain one. Repeat -o for a backup, used while the first is down. TensorCash takes a wss://host/v1/ws pool, whose session its engine holds.
algorithm-a quantusquantus (GPU and CPU), randomx (CPU), pearl (NVIDIA sm_86, sm_89, sm_120), tensorcash (NVIDIA, 11.1 GB free). Read off the wallet when you leave it out.
cards-d 0,2Indices, PCI ids or UUIDs, comma separated; !1 excludes card 1. --list-devices prints them. Every discrete card by default; --igpu adds integrated ones.
CPU threads-t 8A count, a percentage (50%) or +N. One per physical core on randomx; off beside a GPU on quantus until -t.
$ ./fearminer -o stratum+ssl://pool.example.com:3335 -u YOUR_WALLET.rig1
$ ./fearminer -o stratum+ssl://pool.example.com:3335 -o stratum+tcp://backup.example.com:3333 -u YOUR_WALLET.rig1
$ ./fearminer -a randomx -o stratum+ssl://pool.example.com:3335 -u YOUR_WALLET.rig1 -t 50%
$ ./fearminer -a pearl -o stratum+ssl://POOL:PORT -u YOUR_WALLET -w rig1
$ ./fearminer -a tensorcash -o wss://POOL/v1/ws -u YOUR_WALLET.rig1 -p token-file=TOKEN_FILE
$ ./fearminer -o pool.example.com:3333 -u YOUR_WALLET -w rig1 -d 0,2

-u is the wallet with an optional .worker, -o the pool, -a the algorithm, -d the cards, -t the CPU threads.

fearminer -o stratum+ssl://POOL:PORT -u WALLET

Without the command line #

Open start_quantus.sh (or start_randomx, start_pearl; .bat on Windows) in a text editor, put your wallet in WALLET, your pool in POOL and a name in WORKER, run it. It refuses the placeholders and restarts the miner after a stop it can retry (Understand an error).

HiveOS

Set up FearMiner on HiveOS #

Add the custom-miner package to a flight sheet. HiveOS chooses what to mine; the cockpit can monitor and control the rig.

Details and behavior

The fearminer_custom-<version>.tar.gz asset of a release is a HiveOS custom miner: the binary and the four h-*.sh scripts in a fearminer_custom folder. HiveOS shows it as fearminer_custom. The stats come from the miner's own /hive-stats, forwarded as is.

Flight sheetvalue
Minercustom
Installation URLhttps://github.com/fearminer/fearminer/releases/download/v1.15.2/fearminer_custom-1.15.2.tar.gz
Hash algorithmqpow (Quantus) · randomx (Monero, CPU) · pearlhash (Pearl, NVIDIA sm_86, sm_89, sm_120) · tensorcash (TensorCash, NVIDIA)
Wallet and worker template%WAL%.%WORKER_NAME%
Pool URLstratum+ssl://host:port · host:port
Passx
Extra config arguments
Optional arguments
Any option: --enroll fm1_... (the cockpit, Manage rigs from the cockpit), --tls, -d 0,2, -t 0, --tls-fingerprint <sha256>, --no-supervisor, --notify-telegram ...
Package scripts

The package builds the command line from those fields:

-afrom the hash algorithm (quantus when empty)
-ofrom the pool URL
-ufrom the template
-pfrom the pass (x when empty)
--api-bind 127.0.0.1:4300so h-stats.sh can read the stats
the extra argumentslast
FEARMINER_NO_TUI=1since there is no terminal

h-run.sh passes --allow-root, since HiveOS runs every miner as root and the binary otherwise refuses to start as root.

Nothing to add to the flight sheet.

Integration details and optional arguments

A crash or a hung card restarts the mining process after a backoff.

/hive-stats comes back on the same port, with crashes per card and restarts on it.

The HiveOS watchdog covers the supervisor giving up (exit code 12).

--no-supervisor in the extra arguments runs one process and leaves every restart to HiveOS.

Stats contract:

khsthe rig total in kH/s, the object's own total_khs
hsone entry per card in kH/s, or per CPU row on a CPU algorithm (randomx) with fan and bus zero
bus_numbersmaps them to the cards
ar[accepted, rejected, invalid, "invalid per row"]: the pool's two verdicts, then the GPU solutions the CPU re-check refused before submit, summed, then one figure per row of hs, 0 on a CPU row

The overclock stays with the flight sheet: without an OC option the miner touches no clock, power limit or fan register.

--no-oc in the extra arguments makes it explicit.

HiveOS runs the miner as root, so the OC options work there without the helper.

mmpOS · beta

Set up FearMiner on mmpOS #

Add FearMiner to a custom-miner profile. This integration is beta and has not been tested on a real mmpOS rig.

Details and behavior

Beta, from 1.5.3: built to mmpOS's published custom-miner guide and checked against it, not yet run on a real mmpOS rig. Say what does not work, on the Telegram channel or in an issue. The fearminer_mmpos-<version>.tar.gz asset of a release is an mmpOS custom miner; in the mmpOS dashboard:

mmpOS dashboardvalue
Walletsthe address of the coin you mine
Poolsyour pool for that coin, SSL ticked for an SSL port, the username mmpOS proposes (%wallet_address%.%rig_name%%miner_id%) and the password x
Miner profiles, Basicsthe coin (PRL for Pearl, QTC for Quantus, XMR for Monero, TSC for TensorCash), the platform Linux / mmpOS, the miner Custom miner, and the pool of the row above
Custom miner download urlhttps://github.com/fearminer/fearminer/releases/download/v1.15.2/fearminer_mmpos-1.15.2.tar.gz, or the same file under https://download.fearminer.com/v<version>/
Advanced: Api port4444, or any free port
Advanced: ArgumentsUse the argument line below.
Optional arguments
the line mmpOS fills in for a custom miner (below), then any option: --enroll fm1_... to join a cockpit (Manage rigs from the cockpit), -d 0,2 for some cards, -t 0 for no CPU thread on Quantus
./mmp-launch.sh --coin %coin% %pool_protocol% --pool %pool_server%:%pool_port% --user %user% --password %password% --api-port %api_port%

Save the profile and select it on the rig. For an SSL pool, keep %pool_protocol% in the line, or put --tls after it.

mmpOS fetches a URL once and keeps what it got, so a new version is a new URL: to update, put the new release's in the profile.

The miner logs into mmpOS's own log, its stats reach mmpOS through /mmpos, and a cockpit shows the rig as managed by mmpOS: the profile decides what it mines.

Choose and tune mining

algorithms

Algorithms, fees and requirements #

Find a supported algorithm for your hardware, check its fee ceiling and copy a starting command.

Details and behavior

The same list is what fearminer --list-algorithms prints, one line per algorithm with a one-line description; with --json, one array of {name, coin, class, fee_bps, aliases, unit, hive, requirements, refused}.

The list is the signed engine index: a new algorithm is a new row here at the next build of this page, and a new engine on the rigs without a miner release (Engines, below).

algorithmcoinHardwarefeealiasesHiveOSunit
commonfoundryCMFDNVIDIA CUDA; no CPU engine; 8192 MiB of RAM; 7200 MiB of GPU memory free3 %cmfd, common-foundry, productionv4commonfoundryFW/s
pearlPRLNVIDIA CUDA, sm_86, sm_89, sm_120 only; no CPU engine; 4514 MiB of GPU memory free2 %pearlhash, prlpearlhashMAC/s
quantusQTCNVIDIA CUDA, Vulkan (other GPUs); CPU2 %qpow, qtc, quan, qpow-poseidon2qpowH/s
randomxXMRCPU only; 2080 MiB of RAM0.85 %rx, rx/0, monero, xmrrandomxH/s
tensorcashTSCNVIDIA CUDA; no CPU engine; 16384 MiB of RAM; 11319 MiB of GPU memory free2 %tsc, poi, proof-of-inferencetensorcashPoI/s

Fees are ceilings. Pearl collects no fee until the signed terms specify a fee endpoint. Performance examples are measurements on the named hardware, not guaranteed rates.

Fee rounds and logs

The rate in the table is per algorithm, mined in one-minute rounds on a separate connection, never on your session, and shown in the terminal panel header.

It is a ceiling from the signed engine index, never above 5 %: the signed terms from cfg.fearminer.com may lower it, never raise it. An algorithm with no fee pool in the terms is mined free, said once at start.

fee window gives when the first round is due; each round logs fee round started (1 min) and fee round ended with its share count.

Compatible new algorithms and engine updates can be downloaded and verified automatically.

Engine downloads, updates and rollback

Engine downloads, updates and rollback #

The miner hashes nothing itself: each algorithm is an engine of its own, fearminer-engine-<algo>, a signed program the miner downloads, starts and keeps up to date. The pool session, the fee, the supervisor, the sensors, the API and the terminal panel stay in the miner.

where fromdownload.fearminer.com/algos/, listed in index.json: every algorithm with its names, coin, unit, fee ceiling, requirements and versions, each build with its SHA-256
checkedthe index against the algorithms key compiled into the miner (E321 when it does not hold), each engine against the index's SHA-256 (E323), before every start
buildsLinux x86_64 (CPU; CUDA 12.9 for drivers 575 and newer; CUDA 12.4 for the 550 driver of HiveOS 0.6), Windows x86_64 (CPU, CUDA), macOS arm64. The CUDA build of the driver's line first, the CPU build last
cache<state dir>/engines/: the index and the two latest versions of each algorithm
offlinethe index cannot be fetched (E322): the cached one, else the seed the release archive carries in engines/ beside the binary, so an initial start, including from a HiveOS USB image, can use locally available engines; mining still needs a connection to the pool
updatesevery hour: a newer engine is downloaded, checked, started beside the running one, self-tested and handed the current job; the old one stops between two jobs (E326)
rollbacka new engine that fails its self-test, or mines 5 % slower over ten minutes, is rolled back and not tried again before the next index (E327)
pinning--engine quantus=<VERSION>, repeatable, or FEARMINER_ENGINE, or the engine key of the configuration file: that version runs and no update moves it
no engineno index anywhere or no build for this machine (E324), or an algorithm of a login family this miner does not speak (E325): the miner mines nothing and watches the cards
requirementsa machine below the algorithm's requirements is told so (E329)
crashan engine that dies is restarted after a backoff, the current jobs handed back (E320)
feethe fee ceiling is the index's, never above 5 %; a fee mined with another algorithm keeps that engine resident and paused, or starts it per round when the memory is short (E328)
APIengines[] of /api/v1/summary: each engine running, its algorithm, role, version, build and origin

A new algorithm of a login family the miner speaks is mined without a miner release.

The wallet of each chain

The wallet of each chain #

The chain is read off the wallet, so the address alone picks the algorithm. Each is checksum-verified at start; --ignore-wallet-check sends what you typed.

QTCan SS58 address of the Quantus network, prefix 189. A +diff suffix or a solo: prefix is passed to the pool as typed
XMR95 characters from 4 (standard) or 8 (subaddress), 106 from 4 (integrated). A testnet or stagenet address is refused by name
PRLprl1..., bech32m, checksum verified. The test networks' tprl1... and rprl1... are refused
TSCtc1q..., a segwit (bech32) address, or a base58check address of the chain, checksum verified

What we build, and what it needs #

Three builds, and nothing else is published.

Linuxx86_64, built against glibc 2.35 (Ubuntu 22.04), so glibc 2.35 or newer. No ARM build
Windowsx86_64, cross-built with mingw-w64. No 32-bit build
macOSApple silicon only, built with the macOS 15.5 SDK. No Intel build

GPU, for Quantus: an NVIDIA card of compute capability 7.0 or newer with 256 MB of memory free, on a driver of the 550 series or newer (570 for RTX 50). A card under either floor is left out of the run with its code (E310 for the memory, E308 for the driver).

Other GPUs run on Vulkan at a fraction of the rate. RandomX needs no GPU. Pearl runs on NVIDIA sm_86, sm_89 and sm_120 cards only (RTX 30, 40 and 50 series), with 4.7 GB free. TensorCash runs on NVIDIA cards only, with 11.1 GB free, and has no CPU engine.

Vulkan and Metal report no sensors, so there is no temperature, fan or power reading on them and the thermal cut-off cannot act. It covers NVIDIA cards through NVML, and nothing else (Choose and manage devices).

CPU performance tuning

The CPU engine: threads and placement #

The same rules under every algorithm.

defaultone thread per physical core, pinned one per core, spread over the NUMA nodes
-ta count 8, a share of that choice 50%, a delta -2 or +2, or one value per algorithm randomx:16
--cpu-affinitypins the workers to a mask or a list of CPUs instead
--cpu-priority 0..5their priority, on XMRig's scale
the capa -t over what the machine can spare, every thread but two and one per card, is lowered to it with a line saying so
hybrid Intelthe efficiency cores count, each at about half a performance core

RandomX: huge pages #

RandomX is 20 to 30 % faster with the dataset, the cache and the scratchpads in 2 MiB pages, up to 50 % on some machines.

Before allocating the dataset the miner counts what it needs:

dataset2080 MiB
cache256 MiB
per thread2 MiB

So 1184 pages for 16 threads.

It reads the kernel's free pool and, when short, asks the helper below to grow it, per NUMA node where there are several.

At start: huge pages 100 % (1184/1184 x 2 MiB), or E609 with the number to reserve and the command.

Without the helper, reserve by hand right after boot, while memory is unfragmented, and keep the setting across reboots.

transparent_hugepage set to always backs what did not fit.

$ sudo sysctl -w vm.nr_hugepages=1184
$ echo 'vm.nr_hugepages = 1184' | sudo tee /etc/sysctl.d/90-fearminer.conf

1 GiB pages: --1gb-pages (huge_pages_1g in the file, off by default as in XMRig).

It reserves three 1 GiB pages per NUMA node for the dataset when the CPU has them (pdpe1gb), 1 to 3 % over 2 MiB pages.

Used only where the kernel's default huge page size is 1 GiB: default_hugepagesz=1G hugepagesz=1G hugepages=3 on the kernel command line, which also reserves them before memory fragments.

Otherwise E610 says so and 2 MiB pages are used.

Windows, huge pagesgive your account the Lock pages in memory right (secpol.msc, Local Policies, User Rights Assignment), log out and in, a reboot being the sure way. E612 at start when the right is missing
Windows, MSRno MSR tweaks (E611, once): they need a kernel driver, and this miner installs none
macOSno huge pages an application can ask for, no MSR; the fallback is the only mode

RandomX: the MSR tweaks #

XMRig's prefetcher settings on Ryzen and Intel are worth up to 30 % on an Intel, up to 6 % on a Zen. Its public values:

  • Zen 1 and Zen 2
  • Zen 3
  • Zen 4 and Zen 5
  • Intel Core

They need root: the miner asks the helper before its first network connection and never runs as root.

--msr auto, the default, picks the preset from the CPU's family and model.

With the helper there it is applied. Otherwise the miner names the loss and starts anyway:

E601helper missing or sudo refuses
E603virtual machine
E604kernel lockdown (Secure Boot)
E605no msr module (modprobe msr)
E606module refuses writes
E607CPU with no public preset

Each line carries the estimated loss and the one-line fix.

--msr offwrites nothing
--msr zen3forces a preset; also zen1, zen2, zen4, zen5, intel
--msr addr:value:mask,...applies a custom list on the registers the presets tune: 0x1a4, 0xc0011020 to 0xc0011022, 0xc001102b. Any other address is refused

Original values are read first and kept in a root-owned file.

They are written back at every end of the mining process, clean stop or crash (E614, or E608 when it cannot).

One block at start gives the engine's setup:

  • JIT or interpreter
  • hardware or software AES
  • the MSR line
  • the huge-page line
  • the threads and their placement

It ends with the share of the ideal configuration reached (performance: about 52 % of the ideal configuration when both are missing).

--list-devices --json -a randomx gives the same under cpu.performance, applying nothing (null under another algorithm).

$ fearminer -a randomx -o stratum+ssl://pool.example.com:3335 -u YOUR_WALLET.rig1 -t 50% --cpu-affinity 0-7 --msr zen4
randomx  MSR zen4 preset applied on 16 CPU(s) via /usr/local/bin/fearminer-helper (sudo)
randomx  huge pages 100 % (1184/1184 x 2 MiB)
randomx  8 thread(s) on CPU 0-7 (--cpu-affinity)
randomx  performance: the ideal configuration (JIT, hardware AES, huge pages, MSR)

The helper: fearminer-helper #

fearminer-helper ships next to fearminer in the Linux archive and is the one privileged piece.

  • A separate binary: no network, no configuration file, no dependency on the miner.
  • It writes the MSR registers and grows the huge-page pools on request.
  • It logs every step to stderr and answers one JSON line.
  • The miner runs it as sudo -n fearminer-helper ... (never through a shell) before its first network connection, and holds no privilege afterwards.
  • The miner never runs as root.
  • A miner that is itself root (--allow-root, HiveOS) does the same in-process and never calls it.

Install:

  • Copy it to /usr/local/bin.
  • fearminer-helper install then prints the sudoers line for your user and this path, plus the systemd drop-in wiring it into fearminer.service; it writes nothing itself.
  • Put the line in /etc/sudoers.d and load the msr module.

Check with status: one JSON line, no privilege needed, giving what the machine allows.

  • the msr module and its allow_writes
  • kernel lockdown, Secure Boot, a hypervisor
  • huge pages free and total by size and node
  • the preset auto would pick

Search order:

  • /usr/local/bin/fearminer-helper
  • the path the sudoers line names
  • the archive's copy next to the binary, which no sudoers rule covers

A sudo that refuses one is followed by the next.

--helper PATH replaces both and is the only path tried.

When sudo refuses it, or nothing is there, E601 says so and names both paths.

$ sudo install -m 0755 fearminer-helper /usr/local/bin/fearminer-helper
$ fearminer-helper install
$ echo 'USER ALL=(root) NOPASSWD: /usr/local/bin/fearminer-helper' | sudo tee /etc/sudoers.d/fearminer-helper
$ sudo chmod 0440 /etc/sudoers.d/fearminer-helper
$ sudo modprobe msr && echo msr | sudo tee /etc/modules-load.d/msr.conf
$ sudo -n /usr/local/bin/fearminer-helper status

Original MSR values: /run/fearminer-helper/msr.json, root-owned, until msr restore or the next boot.

Pages a run reserved are returned when it stops, never below what another process uses (E615 if not).

The supervisor restores after every end of the mining process, clean stop or crash.

Under systemd the drop-in adds ExecStopPost=fearminer-helper msr restore and ExecStopPost=fearminer-helper hugepages release, the backstop if the supervisor dies.

Miner commands:

msr apply --preset auto|zen1|...|intel|LIST--dry-run prints what would be written
msr restoreputs the saved values back. With nothing saved it does nothing, exit 0 for anyone
hugepages reserve --bytes N [--1g]grows the pool
hugepages releaseeach miner passes its own name, so a release frees that run's pages only

Exits:

0done
1a failure its JSON line names
2a refused argument (a preset that is none, a reservation past the machine's memory), judged before the privilege
3not root where root is needed

Not done yet: RandomX v2 (rx/2, the next Monero fork), and a dataset copy per NUMA node (one copy for all of them today; the start line says how many nodes the threads are spread over).

Pearl

Pearl #

  • A noised int8 matrix product whose 8 x 8 tiles are hashed against the share target; the Merkle proof of a winning tile is the share.
  • sm_86, sm_89 and sm_120 (RTX 30, 40 and 50 series), with 4.7 GB free; another card is left out with the reason (E310 for the memory). The NVIDIA driver is all it needs. Not on macOS.
  • No CPU engine: -t is refused (E202).
  • The rate is in T (10^12 multiply-accumulates a second), the unit its pools credit; the API gives MAC/s, HiveOS TH/s, the efficiency GMAC/W.
  • Every proof is verified by the chain's verifier inside the engine, then again by the miner before it is sent (section 10).
  • The pool must speak Pearl's "type": "v2" stratum, and is your choice: fearminer -o stratum+ssl://POOL:PORT -u prl1... -w rig1.
  • Fee 1 %, a ceiling: nothing is charged until the signed terms name a Pearl endpoint, and the start says so.
Quantus

Quantus #

  • NVIDIA needs a driver of the 550 series or newer, 570 for RTX 50; the preflight prints the one installed.
  • A card with no native engine runs on Vulkan, at about a third of the rate.
  • On a rig with a GPU the CPU engine is off and -t N turns it on; on a rig without one it is on, with every thread but two.
  • The first start tunes the kernel on your card and caches the result; --retune measures again.
RandomX

RandomX #

  • The RandomX library of tevador, v1.2.3, built into its engine.
  • Allocated once: dataset 2080 MiB, cache 256 MiB, scratchpad 2 MiB per thread. A machine that cannot hold the dataset mines on the cache alone, many times slower, and says so at start.
  • The dataset is rebuilt on every new seed hash, every 2048 blocks, about every three days: a few seconds on every core.
  • Threads are capped by the L3 cache at 2 MiB each, and a sibling hyperthread adds nothing.
  • Huge pages are worth 20 to 30 %, up to 50 % on some machines, and the MSR tweaks up to 30 % on an Intel, 6 % on a Zen. Both below.
  • Pools speak the CryptoNote stratum: any pool XMRig connects to.
TensorCash

TensorCash #

  • A proof of inference: windows of the registered model, Qwen3-8B, run on the card, and a share is a proof of 166 to 200 KB. The rate is in PoI/s, proofs of inference a second, and compares with no hashrate.
  • NVIDIA only, with 11.1 GB of GPU memory free; a card short of it (another model loaded on it, say) is left out with E310. No CPU engine.
  • The pools are WebSocket brokers: -o wss://host/v1/ws -u tc1q....rig1 -p token-file=<path>. The engine holds the pool session and reads the pool's token from that file (mode 600); the miner never reads it or shows it. Only the first pool is used for now.
  • From the cockpit, a TensorCash sheet needs FearMiner 1.7.1 or later on the rig; the token stays on the rig, as above.
  • The engine's own settings (its backend, the model's weights pinned by their SHA-256, the host the token goes to) are a file named by TSC_POOL_CONFIG.
  • No offline benchmark: --benchmark says so and ends with code 3, and -a all skips it with the reason. Its rate is measured on a pool.
  • A rejected share, or a pool that refuses the login, ends the session (E114): the miner stays up without mining until it is restarted.
  • Fee: 2 %, mined by the engine itself on the same pool, on FearMiner's own tc1q... account, not in one-minute rounds.

pools

Connect to your pool #

Enter the connection details supplied by your pool. Add backups in the order you want FearMiner to try them.

Details and behavior
  • -o can be repeated, or given once with the URLs comma separated; FEARMINER_URL=A,B does the same.
  • The order is the priority: first pool primary, the rest its backups.
  • The wallet, the password and the TLS pins (--tls-fingerprint, --tls-spki) are given once for all pools, or once per pool in the same order.
  • Any other count is E203.
  • Every connection, probes and fee rounds included, goes through the same dialer: the proxy, the resolver and the address family policy below.
$ fearminer -o stratum+ssl://pool.example.com:3335 -o stratum+tcp://backup.example.com:3333 -u YOUR_WALLET.rig1
$ FEARMINER_URL=stratum+ssl://pool.example.com:3335,stratum+tcp://backup.example.com:3333 fearminer -u YOUR_WALLET.rig1
$ fearminer -o A -o B -u WALLET_A -u WALLET_B --tls-fingerprint SHA256,-

Failover #

  • A network error retries the same pool with a backoff, up to --pool-retries attempts (3), then moves to the next pool. Network errors: connect, TLS, read, write, a timeout, or no new job for --job-timeout seconds on an otherwise live connection. The backoff has jitter: the base doubles from 1 s to 60 s with every failure, the wait drawn at random under it. It is logged once, with its reason and the clock time of the next attempt. A session that mined for a minute starts it over.
  • A pool is left for the next one at once on: a refused login (E104); an answer that is not a login reply; a certificate that is not the pinned or the remembered one (E103, E118).
  • With every pool down (E106) the miner keeps trying them in turn, with a pause of up to 60 s between rounds and one line per round; it never exits.
  • While mining on a backup, the primary is probed every five minutes on a second connection (a login, then the socket is closed). As soon as it answers (within --max-latency when one is set), the miner goes back to it at the backup's next job change and logs pool: back on primary.
  • The fee pool is not part of the list: it has its own connection during its one-minute rounds.
  • A pool that answers but slowly can be left too. With --max-latency, when the median time from a submit to its reply (last twenty) stays over the limit for two minutes, the other pools are measured on their own connections. The fastest answering under the current median takes the session, figures on the line (E129). Nothing moves when no pool is faster. Off by default.
  • Each pool keeps its own record on /api/v1/pools: accepted, rejected, stale and unanswered shares, refusals by class, best share, uptime, reconnections, average reply time and the current reply median, from the start of the process and across reconnections.

Which pool the session is on:

terminal panelthe header
plain logconnected to <URL> (<addr>, backup 2/3)
/api/v1/summarypool
/api/v1/poolsthe whole list with its rank and the active one
/statspool, pool_index, pool_is_primary, pool_switches

The alerts pool_disconnected, pool_failover and pool_recovered follow the same moves.

--job-timeout

--job-timeout #

After --job-timeout seconds without a new job the workers stop. The miner reconnects under the same rules as a lost connection (E105).

Unless set, the figure is the chain's own:

quantus120 s
randomx300 s (the pools send a job a minute at most)
pearl180 s

The line says which; 0 turns the guard off.

TLS: the public roots, a pin, or trust on first use

TLS: the public roots, a pin, or trust on first use #

stratum+ssl:// is TLS 1.2 or 1.3 (1.3 preferred), host name as SNI. --tls adds it to a bare host:port.

The negotiated protocol and cipher print once per connection.

public rootsthe default: certificates are checked against the Mozilla store built into the binary, so no system store is needed
--tls-fingerprintpins the DER's SHA-256, as openssl x509 -fingerprint -sha256 prints it. A renewal breaks it
--tls-spki sha256/BASE64pins the public key in the notation HPKP used. Survives a renewal that keeps the key, and wins over --tls-fingerprint on the same pool

A certificate the roots do not sign (a node, a P2Pool, a private pool) must be pinned.

A failed handshake never falls back to plain TCP.

Either pin: one value for all pools, or one per pool in pool order, - for a pool without one.

A mismatch (E103) prints the pin and what the pool presented, same notation.

$ fearminer -o stratum+ssl://pool.example.com:3335 -u YOUR_WALLET.rig1 --tls-fingerprint 3a3524b6...c8307
$ openssl s_client -connect pool.example.com:3335 </dev/null 2>/dev/null | openssl x509 -fingerprint -sha256 -noout
$ fearminer -o stratum+ssl://node.lan:3335 -u YOUR_WALLET.rig1 --tls-spki sha256/BASE64
$ openssl s_client -connect node.lan:3335 </dev/null 2>/dev/null | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64
$ fearminer -o stratum+ssl://node.lan:3335 -u YOUR_WALLET.rig1 --tls-tofu
TLS: first contact with node.lan:3335: certificate 3a3524b6...c8307 remembered
$ fearminer -o stratum+ssl://node.lan:3335 -u YOUR_WALLET.rig1 --tls-tofu --tls-tofu-reset node.lan:3335
$ fearminer -o stratum+ssl://10.0.0.2:3335 -u YOUR_WALLET.rig1 --tls-insecure
TLS: 10.0.0.2:3335 TLS 1.3 TLS13_AES_256_GCM_SHA384, certificate not verified (--tls-insecure), SHA-256 3a3524b6...c8307

--tls-tofu trusts the certificate on first use.

  • The first handshake prints the pool's certificate fingerprint and keeps it in tls-pins.json in the state directory, keyed by host:port.
  • A later handshake with another certificate is refused with E118, which prints both fingerprints, and the pool is left for the next.
  • To accept the new certificate: start once with --tls-tofu-reset host:port (repeatable), or delete the entry from the file.
  • A pool with its own --tls-fingerprint or --tls-spki is checked against its pin, not the file.
  • A tls-pins.json that exists and cannot be read is E119: the miner does not start.

--tls-insecure checks nothing: whatever certificate the pool presents is accepted, with no chain, name or expiry check.

  • It is for a TLS port forward or a proxy, where the name dialled is not the pool's and the roots refuse a path that works. The E102 line of such a refusal names it, beside a pin.
  • The session stays encrypted, but anyone on the path can impersonate the pool and take the rig's work: every start says so (E120), and the TLS line prints the SHA-256 of the certificate presented, which --tls-fingerprint takes. A pin is the safer choice when the certificate is known.
  • A pool with its own pin keeps it. Refused with --tls-tofu, and when no stratum+ssl:// pool without a pin is left.
  • The fee rounds go the way the pools go. The terms, the engines, the telemetry and the cockpit's relay are always checked against the public roots.
  • It needs a restart. A cockpit's mining sheet can carry it for its pools, and a sheet that changes it restarts the miner.

The connection's TLS line gives what held.

pin verifieda pin
certificate as rememberedtrust on first use
certificate not verifiednothing, --tls-insecure
Proxy and DNS

Proxy and DNS #

--proxy socks5://[user:pass@]host:port routes every pool connection through a SOCKS5 proxy:

  • the mining session
  • the probes on the primary
  • the fee rounds
host namegoes to the proxy as a name (socks5h semantics; socks5h:// means the same), so no DNS query for a pool leaves the machine
Tora .onion pool through Tor (socks5://127.0.0.1:9050) works like any other
credentialsusername and password are sent when the proxy asks; percent-encode @ and : in them
timeouta proxied connection gets the connection timeout twice, once per leg
E115a proxy down, refusing the credentials or unable to reach the pool, with the proxy's own reply in words

The pool is never tried directly while a proxy is set.

A password in the URL is masked in the log and in --dry-run, but shows in the process list: set it in the configuration file or the environment.

The proxy carries the pool connections, the engines' downloads, the cockpit's relay link and the telemetry. These go direct, over HTTPS, and show the rig's own address to their endpoints:

  • the fetch of the signed fee terms (cfg.fearminer.com)
  • the notifications
  • the heartbeat of --heartbeat-url

A rig that must reach the network through the proxy alone keeps the proxy for the pools: the terms fetch then fails harmlessly (E111: the miner mines with the last terms it verified, or with the built-in ones).

$ fearminer -o stratum+ssl://pool.example.com:3335 -u YOUR_WALLET.rig1 --proxy socks5://127.0.0.1:9050
network  proxy socks5://127.0.0.1:9050 (the proxy resolves) · ip any
dns      pool.example.com: resolved by the proxy socks5://127.0.0.1:9050, no local lookup
$ fearminer -o stratum+ssl://pool.example.com:3335 -u YOUR_WALLET.rig1 --dns doh --doh-url https://1.1.1.1/dns-query
network  dns doh (https://1.1.1.1/dns-query) · ip any
dns      pool.example.com → 203.0.113.10 (doh https://1.1.1.1/dns-query)
$ fearminer -o stratum+ssl://pool.example.com:3335 -u YOUR_WALLET.rig1 --ipv4-only
--dns dohresolves the pool names over DNS over HTTPS (RFC 8484, A and AAAA, answers cached for the resolver's TTL). An endpoint that does not answer falls back to the system resolver (E116, once per outage); a name it says does not exist does not (E117)
--dns doh-strictnever falls back: no answer is E116, and the pool is retried like any unreachable one
--doh-urlthe endpoint, https://cloudflare-dns.com/dns-query by default. Give the resolver by IP (https://1.1.1.1/dns-query, https://9.9.9.9/dns-query) when the local DNS is what fails

DoH hides the names from the local resolver, not the pool from the network.

The TLS SNI and the pool's address stay visible on the wire; a proxy hides those.

With --proxy the proxy resolves.

--ip 4|6|any picks the address family.

--ip 4IPv4 only; --ipv4-only is the same
--ip 6IPv6 only; --ipv6-only is the same
--ip anythe default: a pool that resolves to both is connected Happy Eyeballs style (RFC 8305), IPv6 first, IPv4 250 ms later or as soon as IPv6 fails. The first to connect wins, the other is dropped

A URL takes a bracketed IPv6 literal (stratum+tcp://[2001:db8::1]:3333).

Before the first connection the preflight's network and dns lines give how the pools will be reached and what each name resolves to.

They also give who answered: the system resolver, the DoH resolver, or the proxy with no local lookup.

Every pool socket carries TCP keepalive (60 s idle, a probe every 10 s, three probes), so a peer gone without a FIN is noticed in about a minute.

When the pool misbehaves

When the pool misbehaves #

A pool can also stall, stutter or lie; each case has a rule, a line with a code, and a counter on the pool's record (/api/v1/pools).

  • A share with no reply: a submit waits --submit-timeout seconds (10) for its verdict; past that it is unanswered, not credited, said once (E125), counted under shares.unanswered. Any reply to a share, on time or late, starts the row over (a keepalive's does not). --max-no-submit-responses (10) in a row end the session (E113): reconnected at once, left for the next pool when the next session goes the same way.
  • A refusal: every rejected share is one line with the pool's words and their class. Classes: low difficulty, stale, duplicate, unknown job, unauthorized, other, read off the Stratum v1 code when the pool sends one, off its wording otherwise. They are the pool record's rejected_by_reason counters; the last refusal's class rides the shares_rejected_high and gpu_unstable events.
  • No job: no new job for --job-timeout seconds on a live socket ends the session (E105), the workers stopped first; the figure is the chain's own unless set, and the start's pool line gives which is in force.
  • The same job again: a job whose id and work were already seen on the connection is ignored with a debug line (jobs_duplicate). A job carrying an older job's work under any id is a replay: ignored, said once per session (E128), counted (jobs_replayed); the workers stay on the current job. Judged on the content, never on the id alone.
  • A job searched out: the rig has done as many hashes on a job as the job has nonces. That is 2^32 on RandomX, whose nonce is four bytes; a Quantus job offers more than any rig searches. The search stops (E127, once per job, nonce_space_exhausted) and the workers wait for the next job instead of hashing the same nonces again.
  • A message: client.show_message is shown once, as text, tagged with the pool; the escape sequences and the control characters are taken out, the text is cut at 200 characters, and nothing in it is ever interpreted. The same text again is not shown.
  • A redirect: client.reconnect (host, port, wait) is followed only when the host is in the pool list, on any port, after the wait it asked for, capped at 60 s. A redirect anywhere else is refused with one E126 line naming the host; the session goes on where it is. A redirect to another pool of the list is a move to that pool: the session logs in with that pool's wallet, password and pin, and it counts as a pool switch.
  • Slow replies: --max-latency, above (E129).
$ fearminer -o A -o B -u YOUR_WALLET.rig1 --submit-timeout 15 --max-latency 300
E125 share unanswered: share 42 on job j7 from GPU0 not answered within 15 s (3 unanswered in a row)
E129 pool latency over the limit: pool: moving to stratum+ssl://B (backup 2/2): answers in 48 ms, stratum+ssl://A in 310 ms
[ REJECTED ] 3/10 · GPU0 · 4.00M · stale · "Stale share" · 40 ms
The wallet and its pool

The wallet and its pool #

A wallet always comes with its pool: -o (or FEARMINER_URL, url or [[pools]] in the file) beside -u, WALLET, FEARMINER_USER or user. The pool is your choice; the miner never picks one.

E224a wallet without a pool: refused before anything is touched, at a start as under --check-config and --dry-run, exit 2

Without -a, the chain comes from the address: every algorithm of the build is asked whether it decodes for its chain, nothing is guessed.

E215two chains accept one address, both named, and -a decides
E214a chain this miner cannot run
E401no chain at all

Each is refused before anything connects, exit 2, at a start as under --check-config.

With no wallet and no pool the miner mines for no one.

The preflight runs, the terminal panel shows the cards with their telemetry, /stats says mode monitoring, until Ctrl+C.

cards

Choose and manage devices #

Select GPUs, read their status and adjust supported device settings.

Details and behavior

-d picks the GPUs:

  • by index, as --list-devices prints them (PCI order, same as nvidia-smi)
  • by PCI id
  • by UUID
  • by vendor
  • by exclusion

Items combine as a set.

NVIDIA gets the exact cards; Vulkan and Metal take the first N, -d 0..N-1 only.

-d is refused on a CPU-only algorithm (RandomX).

cpu is not a card, -t picks CPU threads.

--list-devices prints the listing and nothing else.

$ fearminer --list-devices
2 GPU(s), engine cuda
  #0  NVIDIA GeForce RTX 4070 Ti  [pci:0000:01:00.0]  GPU-3f2a1b4c-5d6e-7f80-9a1b-2c3d4e5f6a7b
  #1  NVIDIA GeForce RTX 3090     [pci:0000:41:00.0]  GPU-11111111-2222-3333-4444-555555555555
pick with -d by index (-d 0,2), by PCI id (-d pci:0000:41:00.0, -d pci:41), by UUID (-d GPU-...) or by vendor (-d nvidia); leave one out with -d '!1'
-dselection
-d 0,2GPUs 0 and 2 only, by index.
-d pci:0000:41:00.0Same card by PCI id, as --list-devices prints it; stable across driver reorderings.
-d 41:00.0 · -d pci:41 · -d bus:65Shorter PCI id forms: without the domain, the bus alone in hex, or the bus in decimal.
-d GPU-3f2a1b4c-5d6e-7f80-9a1b-2c3d4e5f6a7bBy UUID, derived from the card itself: it follows the card into another slot or another rig. Write it whole, as printed (uuid: optional, case-insensitive); a prefix is not a card, nothing is guessed.
-d nvidia · -d 3,nvidiaBy vendor: every NVIDIA card, or card 3 then the rest. This build lists NVIDIA only; amd and intel select nothing and say so.
-d '!1' · -d '!pci:41:00.0' · -d '!GPU-3f2a...'Every card but this one, in any form above. A use-list and an exclude-list do not mix (E206). Quote the ! in a shell.
-d '!0' -t 2All cards left out, two CPU threads: not a mistake. The card shows Excluded, the CPU threads mine. With -t 0 instead: E301, exit 3; in monitoring mode a warning, no GPU telemetry.
-d 5An index past the cards the driver lists (a one-card rig here), or a UUID from another rig: E206, exit 2, before any engine starts, listing included. --check-config and --dry-run report the same; --device-missing first keeps the start.
-d 0,1,2 --temp-limit 85,80,_One value per card, in -d order: card 0 at 85, card 1 at 80, card 2 default. Every per-card option takes this grammar.
-d 0,1,2 --device-missing firstSame command line on a rig with fewer cards: a -d item that is not there is logged, not refused, and the per-card lists land on the cards found from the first position on (last: from the last back).
--igpuIntegrated GPUs too, even beside a discrete one; left out by default.
-t 4Four CPU threads beside the GPUs; default 0 on a rig with a GPU. On RandomX the default is one thread per physical core; -t N overrides.
--list-devices --jsonMachine-readable listing, one JSON document: cards with memory, compute capability, driver, vendor and engine, plus CPU and RAM.

Without an overclock option (below) the miner writes nothing to a card's clocks, power limit or fan curve; it only reads the driver.

--no-oc says so on the log.

The crash counters below tell you when an overclock is too much.

One value per card

One value per card #

One grammar for every per-card option (--temp-limit, --temp-resume).

  • A single value covers every card.
  • Comma-separated values go one per card, in the order of the cards mined on: -d order with a use-list, listing order otherwise; an excluded card keeps its place.
  • _ keeps that card's default.
  • A list shorter than the cards leaves the rest at their default.
  • A longer one is E206 with the count.

--dry-run prints how a list lands (gpu: --temp-limit #0 85, #2 80).

The first --temp-limit position is the common core limit.

A position that differs is that card's own, resumed the same distance below it as the common pair: --temp-limit 90,80 --temp-resume 75 pauses card 1 at 80, resumes it at 65.

--device-missing

--device-missing #

A -d item naming no card here (-d 5 on a one-card rig, a UUID from another rig): E206, exit 2, before any engine starts; --check-config says the same.

--device-missing first or last (FEARMINER_DEVICE_MISSING) keeps the configuration and mines the selected cards that exist; the log names those expected and not found.

Per-card lists lie over the cards found from the first position on (first) or from the last back (last).

A selection with no card present selects nothing: the log says no card of the selection is present, the CPU threads mine.

With -t 0 the start is E301 (exit 3), predicted by --check-config and --dry-run with the same line and code.

Excluding an absent card excludes nothing under either.

--list-devices --json

--list-devices --json #

--list-devices --json prints one JSON document:

  • the cards in the driver's order (the indices -d takes), each with its engine (null for a card left out, or on an algorithm without a GPU engine)
  • the CPU
  • the RAM

Facts come from nvidia-smi, the driver's files and sysfs, the readers of the checks before a connection.

A fact nothing gives is null, never a guess.

{"gpus": [{"index": 0, "name": "NVIDIA GeForce RTX 4070 Ti", "pci_bus_id": "0000:01:00.0",
           "uuid": "GPU-3f2a1b4c-5d6e-7f80-9a1b-2c3d4e5f6a7b", "vram_mb": {"total": 12282, "free": 11870},
           "compute_capability": "8.9", "driver": "570.86", "vendor": "nvidia", "engine": "cuda"}],
 "cpu": {"model": "AMD Ryzen 9 7950X 16-Core Processor", "physical_cores": 16, "threads": 32, "l3_mib": 64, "aes": true, "numa_nodes": 1},
 "ram_mb": 64036}
Understand device status

Device states #

MiningSearching. The row shows rate, temperature, fan, power, acc/rej and the time since the last share.
Paused (temp 91 °C) · Paused (mem 106 °C)Held by the thermal cut-off, with the sensor holding it and its reading; the plain log's minute line repeats it while the rig's rate is zero. The card finishes its search, then idles until every sensor that held it has cooled past its resume point. Not judged by the watchdog.
Degraded (E316 ...)Suspected by the watchdog, still mining: low hashrate (E313), refusals in a row (E316), share famine (E315), the reason on the row. Back to Mining when the condition clears (E317), or restarted after the grace.
Quarantined (E318 ...)Out of this run for taking the miner down --device-quarantine times within --restart-window (E318): its worker idles, its rate leaves the totals, the others carry on. A miner restart ends it; --reset-crashes clears the counters. Never the last device that could mine.
LostThe driver reported it gone (E302). The card stops alone: its worker exits, its crash is counted, the others carry on; it returns at the next start, not inside the process. Exit 10 only when nothing is left to mine on.
Excluded · Excluded (E502) · Excluded (E506)A card left out by -d !, by the preflight with its code (E502 compute capability under 7.0, E310 not enough free memory), or by a failed self-test (E506). The others mine.
MonitoringA run without a wallet: the card is watched (telemetry on the row and on /stats), no worker started on it.

Every state change is logged with its code and, under the supervisor, appended to watchdog.log. /stats carries state per card, aligned with hs; /api/v1/devices, state per entry.

Sensors #

NVML reads the NVIDIA cards twice a second:

  • core temperature
  • fan
  • board power and its limit
  • clocks
  • the driver's throttle reasons

And where the card exposes them:

  • memory temperature (most cards from the 3090 class up; a laptop or small card says nothing)
  • the energy counter
  • the volatile ECC counters (with ECC on)
  • the PCIe replay counter
  • the PCIe link now and at maximum (gen 1 x1 under load: a bad riser)

The terminal panel row shows the temperatures the card has (64°C · mem 78 · hot 81).

/api/v1/devices and /stats carry every reading (temp_mem_c, temp_hotspot_c, energy_mj, throttle_reasons, ecc_corrected, ecc_uncorrected, pcie_replays, pcie_gen, pcie_width, pcie_max_gen, pcie_max_width), null where there is none.

Throttle reasons are stable labels: idle, app_clocks, power_cap, hw_slowdown, sync_boost, sw_thermal, hw_thermal, hw_power_brake, display_clock; [] when none.

The hotspot (junction) sensor is not in NVML, so it stays absent on NVIDIA.

The last XID error is not reported: no NVML API, and the kernel log needs root.

--no-nvml leaves NVML closed, for a driver whose NVML misbehaves: every reading absent (null on /api/v1/devices and /stats).

The gpu start line then says sensors off (--no-nvml): no thermal cut-off instead of the thresholds, and mining goes on.

Vulkan and Metal report no sensors.

Thermal cut-off

Thermal cut-off #

Each sensor has its own limit:

core--temp-limit (90)
memory--temp-limit-mem (105)
hotspot--temp-limit-hotspot (100)

0 disables that sensor's cut-off.

A sensor must hold at or over its limit for --temp-hold seconds (15) before the card pauses; a dip below restarts the count.

The card finishes its search, then idles, sensor and reading on the row (Paused (mem 106 °C)).

It resumes once every sensor that held it has cooled past its resume point: core to --temp-resume (75), memory and hotspot to their limit minus --temp-hysteresis (10).

A sensor that stops answering while holding the card keeps holding it.

Logged once on pause (E306: sensor, reading, limit, resume point) and once on resume.

temp_high fires after ten seconds of pause, temp_critical after ten minutes or at 10 °C over the limit.

--temp-limit and --temp-resume take one value per card.

--temp-shutdown is the last resort, off by default.

A paused card whose core holds at or over it for --temp-hold seconds, counted from that pause, stops the miner: exit code 11, E319 on the log, a temp_critical event.

Under the supervisor the miner restarts after its backoff and gives up after --max-restarts if the card is still that hot; that card is blamed for taking the miner down.

The value must be over --temp-limit: the cut-off pauses first, the shutdown catches a card that keeps heating while paused (a dead fan, a card heated by its neighbours).

$ fearminer -o stratum+ssl://POOL:PORT -u YOUR_WALLET --temp-limit 85 --temp-limit-mem 100 --temp-hold 20 --temp-shutdown 95
$ fearminer -o stratum+ssl://POOL:PORT -u YOUR_WALLET -d 0,1,2 --temp-limit 85,80,_ --temp-resume 70,65,_
Before it connects

Before it connects #

Runs after the arguments, before the fee terms, the stats port and the pool. One line each.

driverthe NVIDIA driver, its version, libcuda and NVML present. Missing with cards present: E307. Older than the kernels need: E308
gpu #Ncompute capability against the kernels' floor of 7.0, free memory against the algorithm's need
ramthe system memory
hostbare metal or virtual machine, kernel lockdown, Secure Boot, each with its effect on the algorithm
cpuwhat the threads run beside: the cards, no GPU, or GPU not used by this algorithm

A -d index past the cards the driver lists: E206, exit 2, before any engine starts.

Nothing left to mine on: E301, exit 3, before any connection. That is every card left out by -d or by the checks, or none at all, and no CPU thread (-d '!0' -t 0 on a one-card rig). The same list with -t 2 mines on the CPU, the card shown Excluded.

--check-config runs these device checks too. --skip-preflight prints the same report and applies nothing.

Facts come from the driver's files and nvidia-smi (600 ms), never an engine. The check takes well under a second.

Crash counters

Crash counters #

A mining process that exits because of a card (hang, watchdog verdict, thermal shutdown) names it; the supervisor folds it into crashes.json in the state directory.

Keyed per card by UUID when the driver gives one, by PCI id otherwise, never by index: a card keeps its record in another slot, a new card in the same slot starts clean.

Each record:

  • count
  • last time
  • last cause
  • times of the last crashes

A card lost while the miner goes on is counted by the child.

The terminal panel row shows crashes N once there is one.

/api/v1/devices carries crashes per card, /api/v1/summary restarts, the supervisor's count this run.

Blamed for --device-quarantine restarts (3) within --restart-window, a card is Quarantined at the next start.

--reset-crashes clears the file.

A crash after a long stable run means too much overclock; a crash at the first search points at the driver, the riser or the slot.

Tuning

Tuning #

At first start the miner measures a few launch geometries on your own card and caches the best in tuning.json (~/.config/fearminer on Linux and Windows, ~/Library/Caches/fearminer on macOS).

--retune measures again, after a driver change for example.

--gpu-batch is a floor for the nonces per launch, rounded up to whole passes of the card's tuned geometry, the batch in force on the CUDA device start line.

--throttle pauses between batches, for a card that must stay quiet.

Defaults are the measured values.

Overclocking

Overclocking #

Off unless asked: without an OC option the miner touches no clock, power limit or fan register.

An overclock set outside (HiveOS flight sheet, Afterburner, nvidia-smi) stands.

--no-oc makes it explicit: every OC option and any [oc] section ignored, said on the start log.

Given an option, the card is set through NVML (NVIDIA; no X server needed, the calls of nvidia-smi -lgc, -lmc and -pl) and read back after every set.

The log, fearminer oc show and /api/v1/oc give the read-back, never what was asked.

Setting a clock, power limit or fan needs root on Linux, administrator on Windows; the miner runs as a plain user.

Run it as root with --allow-root (HiveOS does), or keep the overclock outside.

Without the privileges every set is E703 with what to do, and mining goes on at the card's current clocks.

AMD and Intel are not controlled in this version.

Six value options: --cclock, --lock-cclock, --mclock, --lock-mclock, --pl, --fan.

Each takes one value for all cards, or one per card in -d order with the --temp-limit list grammar (_ leaves that card alone).

Settings reach the card in a safe order:

  • power limit and fan
  • then memory
  • then core, held back by --oc-delay for rigs that crash when the offset lands on a cold card

One line per set; one line per refusal, with its code and the card's own bounds or steps (E701 to E705).

A refused setting leaves the others alone.

Every change opens a step; ten minutes later a summary gives the rate averaged over the window and the shares accepted, rejected and invalid since the change.

$ fearminer -o stratum+ssl://POOL:PORT -u YOUR_WALLET --lock-cclock 1500 --mclock 800 --pl 220
$ fearminer -o stratum+ssl://POOL:PORT -u YOUR_WALLET -d 0,1,2 --cclock 100,_,-50 --pl 80% --fan 70% --oc-delay 20
oc       GPU0: applied pl 176 W, mem +800; reads core 1900 MHz (+0), mem 10251 MHz (+800), pl 176 W, fan 40 %
OC step: GPU0 core +100, mem +800, pl 220 W -> hashrate over the next 10 min and rejects/invalids
$ fearminer oc show
$ fearminer oc reset
$ fearminer oc reset --defaults -d 0

Before the first set, each card's read-back (offsets, power limit, fan mode and speed, clocks) goes to oc-restore.json in the state directory, keyed by UUID: the values at launch, not the factory ones.

E706 if it cannot be written, and nothing is applied.

Put back:

  • at a clean stop
  • by the supervisor after the mining process crashed or was killed (before the restart)
  • by fearminer oc reset after a run killed without cleanup

Every restoration line carries the cause (E708).

The driver has no read-back for a lock, so a lock the miner set is reset to the driver's default, removing a lock set outside before the start too.

Offsets, power limit and fan return to their read-back.

fearminer oc showper card, its read-back, the steps and ranges it publishes, and what a run left to put back
fearminer oc reset --defaultsresets the selected cards to the driver's defaults instead

Both take -d.

In the file each option is a key of [oc] and a FEARMINER_<OPTION> variable.

Per-algorithm sets go in [oc.quantus], [oc.randomx]..., applied at start for the algorithm mined, over [oc] and under the environment and the command line.

--dry-run prints the sets and the resulting policy as oc:.

[oc]
pl = "80%"
oc_delay = 20

[oc.quantus]
lock_cclock = 1500
mclock = 800

POST /api/v1/oc is the API's one write: a set on one card at once, the delay aside, read back and recorded for the restore like the options.

It needs the token from anywhere, this machine included.

--oc-script PATH runs a program of yours once per card before mining starts, with the card in its environment.

self-test and verified shares

Check correctness and measure speed #

Run self-tests and benchmarks to check your hardware and compare performance.

fearminer --self-test
fearminer --benchmark --duration 30

Expected: a verdict per device and self-test passed, or a failure code. A benchmark reports measured speed for this machine.

Details and behavior

Every engine the run mines with answers its known-answer vectors before the first share.

Every solution a card hands back is re-computed on the CPU before submit.

A miscomputing card is found at start, not after a day of rejected shares.

One that starts miscomputing is found at its first wrong solution, which the pool never sees.

at start

CPU engines against the chain's reference:

Quantusqpow-math, the arithmetic the node validates seals with
RandomXthe library's own vectors

Each card: 256 nonces re-hashed on the CPU, then eight searches at a real target, every solution confirmed by the CPU.

Under a second on a desktop card.

while mining

Every GPU solution re-computed on the CPU (about 6 µs) before it is sent. A wrong one is dropped: E507 on the log, invalid on the card's row, never a reject at the pool. --verify-shares off turns it off.

the verdict

Answers that disagree: E506, the card left out of the run (Excluded (E506), row with no rate), told as gpu_unstable; the others mine on.

A failing CPU engine is dropped the same way.

Nothing left to mine on is exit code 3.

The verdict is kept in selftest.json; a start on the same binary, driver and cards skips the test.

What is run #

Quantus, CPU enginethe chain's three fixed (header, nonce, hash) reference vectors through the reference, then a search from a fixed nonce at difficulty 4096 on the engine's SIMD kernel, which must find the nonce the reference names; a few milliseconds
Quantus, GPU engineevery card at once: 256 searches (--self-test-nonces) under a target accepting every hash, each answer re-hashed on the CPU with the reference, the nonce's high half checked intact; then eight searches at difficulty 2^18, every solution confirmed by the CPU, all answering within five seconds
RandomXthe library's own three vectors on a light VM, on the JIT and AES paths this machine uses; about a second per key

CUDA and Metal re-check candidates on the CPU inside the kernels' crate.

A refused candidate never reaches the host, is counted apart and warns on the verdict line (E508: the shares are safe, the kernel loses them); the card mines on.

A device fails on a wrong answer that reached the host:

  • a re-hashed nonce whose hash differs
  • a solution the CPU refuses
  • no answer
$ fearminer --self-test
FearMiner 1.15.2 self-test, 256 nonce(s) per card, binary 3fa9c1d2e07b6a54
quantus cuda: GPU0 NVIDIA GeForce RTX 4070 Ti [0000:01:00.0]: pass: 256 nonces re-hashed on the CPU and 8 solutions at difficulty 262144 verified (412 ms)
quantus cpu: CPU: pass: 3 reference vectors and one search agree with the chain's arithmetic (6 ms)
verdict recorded in /home/user/.cache/fearminer/selftest.json
self-test passed
$ fearminer --self-test=all
$ fearminer -o stratum+ssl://POOL:PORT -u YOUR_WALLET --self-test --self-test-nonces 1024
The record, and when the test is skipped

The record, and when the test is skipped #

selftest.json in the state directory holds one record per engine:

verdictpass or fail
datewhen the test ran
nonce countthe nonces the test used
binaryits SHA-256
driverthe NVIDIA driver version
cardsby name and PCI id
engine configurationits SHA-256: every environment variable reaching the engines, plus --gpu-batch, --cpu-batch, --throttle, --devices, -t, --igpu
refused countthe refused candidates above

A start skips an engine's test and says so (selftest cuda: passed on <date> ...; skipped) when the record shows a pass on:

  • the same binary and the same engine version
  • the same driver
  • the same cards in the same order
  • the same engine configuration
  • at least as many nonces

It runs again on a new binary, a driver update, a card added, removed or moved, a knob changed, more nonces asked for, or a failure on record.

--self-test on a mining run forces it at start.

Alone, without pool or wallet, --self-test runs offline for the algorithm of -a (--self-test=randomx for another, --self-test=all for every algorithm of the build).

It prints one line per device and per engine, records the verdict, and exits 0, or 3 when a device failed.

Verified shares

Verified shares #

A GPU solution is re-computed on the CPU with the algorithm's reference before submit: every one while the check stays inside its budget, one in ten past it (below).

For Quantus: the Poseidon2 hash of the header and the 64-byte nonce against the target, about 6 µs on a desktop core.

A refused solution is never sent: dropped, and logged under E507 with the card and the overclock hint (first search: the miner or the driver; after a long stable run: likely the overclock).

Where it shows:

the card's terminal panel rowcounted invalid
/api/v1/devicesshares.invalid
/statsshares_invalid, and elements three and four of ar
the notifiersgpu_invalid_share with the card's count

The count is the miner's own, not the pool's.

CUDA and Metal already re-check candidates inside the kernels' crate.

Vulkan hands back its kernel's hash, and the host check is its only one.

CPU solutions are not re-checked: the engine that found them is the reference.

Every solution is checked while the check costs under 1 % of a core in the current second, and one in ten past that.

That budget is 10 ms, or 1 600 solutions a second at 6 µs; a pool serves a rig one every few seconds at most.

--verify-shares off (FEARMINER_VERIFY_SHARES=off) turns it off: a wrong solution is then submitted and counted by the pool as rejected.

Benchmark #

--benchmark measures for --duration seconds after a warm-up of one untimed search per worker: the rate, and the average power over the same window.

  • One algorithm (-a randomx), a list (-a quantus,randomx) or all of them (-a all): several run in turn, 60 s each by default, then a summary with the rate, the power, the efficiency and the change since last time.
  • An algorithm this machine cannot run (no card its engine drives, a missing CPU feature) is skipped with the reason. So is TensorCash, which has no offline benchmark: its engine needs its pool.
  • Power: the cards through their NVIDIA driver, the CPU through the Linux energy counter when it can be read (often root only); otherwise power not measured, never a guess.
  • FearMiner's overclocking options are not applied: the cards run at the clocks and the power limit they have, so the power can differ from mining with an overclock set in FearMiner.

Each figure is kept in the state directory, bench-<algo>.json: the rate, the power, the window, the threads and cards, the engine, the driver, the binary's SHA-256, the date. The next run prints the previous figure beside the new one.

From the cockpit: Benchmark in a rig's panel, or for a selection or a group, runs the same on the rigs, which stop mining during the test and go back to what they were doing (mining their sheet, or paused). The results show in the rig's panel, and the Rewards ranking uses them for the coins a rig does not mine, so it ranks the coins on your own hardware. A HiveOS or mmpOS rig refuses: its watchdog reboots a rig whose hashrate drops.

No pool, no wallet needed.

$ fearminer --benchmark --duration 30
$ fearminer -a randomx --benchmark --duration 30
$ fearminer -a all --benchmark
$ fearminer -a quantus,randomx --benchmark --duration 30
$ fearminer --benchmark --bench-seed 1
$ fearminer --benchmark --bench-seed 1 --bench-solutions 8

--bench-seed N is the deterministic benchmark.

  • Work and every worker's nonce sequence derive from the seed.
  • The run ends when every worker has found --bench-solutions solutions (4).
  • The difficulty is fixed per algorithm and device class: one solution every second or two.
  • Each worker is clocked from its first search to its last solution; the rate is their sum.
  • Every solution is re-checked on the CPU, a refused one named in the report.
  • The run is capped at six times --duration; a report that hit the cap says its checksum is not comparable.

The checksum printed is the first sixteen hex digits of the SHA-256 over the solutions' bytes, sorted.

Same hardware, seed, solution count, threads and cards: same nonces, same checksum.

The next run compares and says checksum matches the last run on this rig or CHECKSUM MISMATCH, meaning a card that miscomputes, another binary or another driver.

The checksum is FearMiner's own, comparable with no other miner.

Exact on a CPU.

On a card, a launch holding two solutions reports the one its threads reached first, about once in a few hundred launches.

A mismatch on a healthy card is rare, a repeated one is not.

supervisor and watchdog

Automatic recovery and watchdogs #

FearMiner watches for mining failures and can restart the mining process. This section explains the limits and recovery rules.

After a crash, the mining process retries after 1, 2, 4 seconds, up to 60 seconds. By default, 5 restarts within 30 minutes trigger --on-failure and exit 12. Configuration and prerequisite failures have separate rules below.

Process and recovery rules

Started to mine, fearminer is a supervisor plus the mining child it re-executes with the same arguments.

The supervisor holds no GPU context and survives whatever the driver does to the child.

The terminal panel and the plain log are the child's, unchanged.

The supervisor prints only its own events, prefixed supervisor:, and appends them to watchdog.log.

stop

  • SIGTERM, SIGINT and Ctrl+C reach the supervisor.
  • It forwards the stop to the child, waits --stop-timeout (8 s), then kills it.
  • The child cancels the searches, stops its workers with a bounded wait, prints miner stopped and exits 0.
  • A second Ctrl+C ends the child at once.

A stop completes in under ten seconds even with a card frozen.

restart

A crash (a signal, a non-zero code, a watchdog verdict) restarts the child after 1 s, then 2 s, 4 s ... capped at 60 s.

Ten minutes healthy reset the backoff.

exit 2configuration: not restarted, the supervisor exits with that code
exit 3precondition: not restarted, the supervisor exits with that code
exit 4another instance: not restarted, the supervisor exits with that code

Every restart is logged with a timestamp and its cause, sent as the alert watchdog_restart, and counted against the card it blames (crashes.json).

--device-quarantine of them in --restart-window, and the card sits the next run out.

give up

After --max-restarts restarts in --restart-window (5 in 30 min) the supervisor gives up.

  • runs --on-failure
  • sends rig_down
  • exits 12

A launcher stops on 12; a systemd unit or HiveOS can then restart the whole thing, the only case where their restart matters.

The watchdog

The watchdog #

verdictdefaultwhen
E303 hang
--hang-timeout
60 sA search that has not polled its cancellation for --hang-timeout seconds. A hung kernel cannot be interrupted from inside the process: the child marks the card Lost and exits 10, and the supervisor restarts it.
E304 zero hashrate
--zero-hashrate-timeout
300 sA card returning no hashes for --zero-hashrate-timeout seconds while the other cards mine; a lone card is judged on its own. A five-minute grace applies at start, after a thermal resume and after a reconnection. Exit 11, restarted.
E305 ghost hashrate10 × the expected share time, 10 to 60 minA card hashing at its usual rate with no accepted share while the pool accepts shares from the other devices. Exit 11, restarted. When no device gets any share the pool is the suspect: said once (E110), and the no-share rule below takes over.
E313 hashrate low
--hashrate-min · --hashrate-grace · --hashrate-reference
50 % · 300 sA card's ten-minute average under a share of its reference: the session's best ten-minute average, or --hashrate-reference. An absolute rate (300M) uses the rig's summed average instead, CPU threads included, so it fires on a CPU-only rig too. The card goes Degraded (E313, alert hashrate_low), the rig is said low. Still under after --hashrate-grace: exit 11. Back over: Mining again (E317).
E314 hashrate suspect
--hashrate-max
offA ten-minute average over a maximum, card or rig: the figure is wrong, not the card. Said once an hour (E314, alert hashrate_suspect), never a restart.
E315 share famine
--share-famine
5 ×A card at a nominal rate finding no share for N expected intervals (the difficulty over its rate, never under 10 min); no pool verdict needed, unlike the ghost rule. The card goes Degraded (E315) and its search is restarted: the worker finishes its search, idles a moment, comes back on the newest job with a fresh seed. A share ends it. A whole famine again after the restart: exit 11.
E316 rejects on one card
--max-rejects-device
5A card's shares refused in a row, stale ones aside: Degraded (E316, likely the overclock) until the pool accepts one of its shares.
E114 rejects on the session
--max-rejects
15Shares refused in a row on the session, from any device: the session reconnects (E114); refused the same way again, the next pool.
E113 no reply to a share
--max-no-submit-responses
10Submits left unanswered for --submit-timeout, in a row, before the session reconnects; a second such run moves to the next pool. 0 turns it off.
E110 no accepted share
--no-share-timeout
1800 sNo accepted share from any device since the session connected: the next pool of the list (the same one again with a list of one, E110); a second such period there, exit 11.
E318 quarantine
--device-quarantine
3The crash counters blame a card for N restarts within --restart-window: at the next start it is Quarantined (E318, alert gpu_quarantined), its worker idles, its rate leaves the totals, the others carry on. Never the last device that could mine. A miner restart ends it, --reset-crashes clears the counters.
E302 device lostalwaysThe driver reported the card gone: it stops alone (E302), its worker exits, its crash is counted, the others carry on; it returns at the next start, not inside the process. Exit 10 only when nothing is left to mine on (no card, no CPU thread).
  • One record per GPU worker, judged twice a second, plus the session's own verdicts.
  • Every verdict is logged with its code and cause and appended to watchdog.log.
  • Each rule is off on its own at 0.
  • A paused or quarantined card is not judged.
  • A card's clocks (grace, share windows, ten-minute average) start over on a thermal resume and on a session reconnect.
  • The session-level rules (--max-rejects, --max-no-submit-responses, --no-share-timeout) apply to a CPU-only rig too.
$ fearminer -o stratum+ssl://POOL:PORT -u YOUR_WALLET --hashrate-min 60% --hashrate-grace 600 --share-famine 8 --max-rejects-device 3
$ fearminer -o stratum+ssl://POOL:PORT -u YOUR_WALLET --hashrate-reference 600M,350M --hashrate-max 1.2G --device-quarantine 2
--on-failure

--on-failure #

exit (the default) or script:<path>: the script runs first, with the exit code, the cause and the restart count in its environment, then the supervisor exits 12. Power-cycle a riser there, or page someone.

$ fearminer -o stratum+ssl://POOL:PORT -u YOUR_WALLET --max-restarts 5 --restart-window 30 --on-failure script:/opt/fearminer/on-failure.sh
# on-failure.sh: FEARMINER_EXIT_CODE, FEARMINER_CAUSE, FEARMINER_RESTARTS in its environment
--no-supervisor · --no-watchdog

--no-supervisor · --no-watchdog #

--no-supervisorruns the old single process: for systemd, HiveOS or another watchdog that restarts the miner itself, and for debugging
--no-watchdogturns every verdict off: no hang, hashrate, share or reject check, no quarantine. A hung card stays hung, a lost card leaves the others mining either way
--allow-multipleskips the lock

A benchmark, --list-devices, --self-test and the other one-shot runs are always one process.

The supervisor (or the single process) takes an advisory lock on fearminer.lock in the state directory. A second instance exits 4 (E210).

The OS releases the lock whenever the holder dies, so a stale lock never blocks the next start.

watchdog.log

watchdog.log #

The supervisor's own log, in the state directory (~/.cache/fearminer), capped at 256 KB: every restart with its timestamp and cause, every give-up. The child's log goes to the console and, with --log-file, to the file you name.

Automate

configuration file

Save settings in a configuration file #

Keep reusable settings in one TOML file. Check the file before starting the miner.

Details and behavior

A TOML file, one key per option: the third way to set the miner up, beside the command line and the environment.

config example prints a complete one.

--dry-run shows what it makes and whether the miner would start; --check-config gives the verdict alone.

Minimal configuration: replace the wallet and pool, save as fearminer.toml, then check it before mining.

[pool]
url = ["stratum+ssl://POOL:PORT"]
user = ["YOUR_WALLET"]
worker = "rig1"
$ fearminer config example > fearminer.toml
$ fearminer --config fearminer.toml --dry-run
$ fearminer --config fearminer.toml --check-config && fearminer --config fearminer.toml
The keys

The keys #

Each key is the option's long name with underscores, at the top level or under the section named after its --help heading: [pool], [network], [devices], [cpu], [output], [benchmark], [supervisor], [watchdog], [notifications], [oc].

a switchtakes true or false
a list optionurl, user, pass, tls_fingerprint, tls_spki: a string or an array of strings
[oc]may hold one table per algorithm, [oc.quantus], [oc.randomx]..., with that algorithm's OC values alone

The pool list can also be one table per pool, [[pools]] with url, user, pass, tls_fingerprint and tls_spki.

A wallet given once under [pool] serves every pool; one inside an entry is that pool's.

${VAR} in a string is replaced by that environment variable; one that is not set is an error.

[pool]
user = "qzjd5MS1GSCpXLYp8DjZASifnkgtUpx5WwhmEzW3ppHdDe3uq"
worker = "${HOSTNAME}"
# url = ["stratum+ssl://pool.example.com:3335", "stratum+tcp://backup.example.com:3333"]

[devices]
temp_limit = 85
threads = 4

[output]
log_file = "fearminer.log"

[network]
proxy = "socks5://127.0.0.1:9050"

[oc]
pl = "80%"

[[pools]]
url = "stratum+ssl://pool.example.com:3335"
tls_fingerprint = "SHA256"
Where it is looked for

Where it is looked for #

The first that exists is read; --config "" reads none. The miner never writes it, and it is nowhere near the state directory.

1--config PATH · FEARMINER_CONFIG
2fearminer.toml beside the binary
3~/.config/fearminer/fearminer.toml · %APPDATA%\fearminer\fearminer.toml · ~/Library/Application Support/fearminer/fearminer.toml
E211a file named with --config that does not exist, and a syntax error too; exit 2
E212an unknown key, with the nearest known key suggested (temp-limit: did you mean temp_limit?)
E213a value of the wrong type, or a ${VAR} that is not set

A mistake never leaves an option silently at its default.

Precedence #

defaults < file < FEARMINER_* < command line

Lowest first. A list is replaced as a whole by the source that sets it, never merged: pools in the file and -o on the command line give the command line's pools only.

--dry-runprints the result: one line per key with its value and source (default, file <path>, env FEARMINER_X, cli), the password as ***, then the mode, the algorithm, the pools, the cards left out, then the --check-config verdict
--check-configruns a start's checks (the options, -d against the cards the driver lists, the pool list rules, the wallet against its chain) and prints the verdict alone, contacting nothing

Exit 0 when the miner would start, 2 with the coded reason otherwise.

A value an option refuses (--pool-retries 0) is an E202 line from either, and from a start.

The supervisor and its mining child read the same file: --dry-run shows what mines.

The whole file, as fearminer config example prints it
# FearMiner configuration file (TOML), as `fearminer config example` prints it.
#
# Every option of `fearminer --help` has a key here: the option's long name
# with underscores (--temp-limit is temp_limit), at the top level or under the
# section named after its --help heading, as below. The pool list can also be
# written one table per pool:
#
#   [[pools]]
#   url = "stratum+ssl://host:port"
#   user = "WALLET.rig1"          # optional: one wallet under [pool] serves all
#   pass = "x"
#   tls_fingerprint = "SHA256"      # or tls_spki = "sha256/BASE64"
#
# Precedence, lowest first: the defaults, this file, the FEARMINER_* environment
# variables, the command line. A list (the pools, the per-pool values) is
# replaced as a whole by the source that sets it, never merged. ${VAR} in a
# string is replaced by that environment variable; one that is not set is an
# error, and so is a key that is not an option. The file is read from --config
# (FEARMINER_CONFIG), else fearminer.toml beside the binary, else the one in
# the configuration directory (~/.config/fearminer, %APPDATA%\fearminer,
# ~/Library/Application Support/fearminer). The miner never writes it.
#
# As printed, this file changes nothing: without a wallet and a pool the miner
# starts in monitoring mode. To mine, set both user (the wallet) and url (the
# pool you chose, stratum+ssl://POOL:PORT): a wallet without a pool is refused
# (E224), the miner never picks a pool for you.

[pool]

# Pool URL: stratum+tcp://host:port, stratum+ssl://host:port, or host:port
# (plain TCP unless --tls). The host is resolved on every connection. Repeat
# it (or separate the URLs with commas) for backup pools: the first is the
# primary, the others are tried in order when it fails, and the miner returns
# to the primary when it answers again
# (--url, FEARMINER_URL)
# url = []

# Wallet address, with an optional worker name as WALLET.WORKER. One value is
# used on every pool; one per pool (repeated, or comma separated, in the order
# of the pools) when a backup needs another
# (--user, FEARMINER_USER)
# user = []

# Worker name, appended to --user as WALLET.WORKER when it has none
# (--worker, FEARMINER_WORKER)
# worker = <NAME>

# Pool password. Pools ignore it; x by convention. One value for every pool,
# or one per pool like --user. A real password here is visible in the process
# list: put it in a file and use --pass-file
# (--pass, FEARMINER_PASS)
# pass = []

# Read the pool password(s) from this file instead of -p: one line for every
# pool, or one line per pool in the order of the pools. Wins over -p and
# FEARMINER_PASS when both are given. On Unix the miner warns when other users
# can read the file
# (--pass-file, FEARMINER_PASS_FILE)
# pass_file = <PATH>

# Send the wallet to the pool without checking that it is an address of the
# algorithm's chain (the banner then says UNCHECKED)
# (--ignore-wallet-check, FEARMINER_IGNORE_WALLET_CHECK)
ignore_wallet_check = false

# Use TLS on a bare host:port (a stratum+ssl:// URL implies it)
# (--tls, FEARMINER_TLS)
tls = false

# Pin the pool's TLS certificate by its SHA-256 fingerprint (64 hex digits),
# for a pool with a self-signed certificate. Without it the certificate is
# checked against the public roots. One value for every pool, or one per pool
# like --user (a dash, -, for a pool without one)
# (--tls-fingerprint, FEARMINER_TLS_FINGERPRINT)
# tls_fingerprint = []

# Pin the pool's TLS certificate by the SHA-256 of its public key (SPKI), as
# sha256/BASE64 (the HPKP notation); a pin that survives a certificate renewal
# that keeps the key. One value for every pool, or one per pool like --user (a
# dash, -, for a pool without one). Wins over --tls-fingerprint for the same
# pool
# (--tls-spki, FEARMINER_TLS_SPKI)
# tls_spki = []

# Connection attempts on a pool, on a network error, before the next pool of
# the list is tried. A pool that refuses the login is left for the next one at
# once. With every pool down the miner keeps trying them in turn, with a pause
# of up to 60 s between rounds, for ever
# (--pool-retries, FEARMINER_POOL_RETRIES)
pool_retries = 3

# Seconds without a new job from the pool, on a connection that is otherwise
# alive, before the session is treated as dead: the workers stop and the miner
# reconnects under the same rules as a lost connection. Without it, the
# algorithm's own figure, which the start says. 0 turns the guard off
# (--job-timeout, FEARMINER_JOB_TIMEOUT)
# job_timeout = <SECS>

# Seconds a submitted share waits for the pool's reply before it is counted as
# unanswered (E125); --max-no-submit-responses unanswered submits in a row
# reconnect the session
# (--submit-timeout, FEARMINER_SUBMIT_TIMEOUT)
submit_timeout = 10

# The most a pool may take to answer a submit, in milliseconds, as the median
# of the last twenty replies: over it for two minutes, the session moves to a
# pool of the list that answers faster, when one does (E129). 0 turns it off
# (--max-latency, FEARMINER_MAX_LATENCY)
max_latency = 0

# Algorithm to mine, or the coin's name (--list-algorithms for the names and
# aliases). Without it, the chain is read off the wallet; the engine index's
# default algorithm when no wallet is given
# (--algo, FEARMINER_ALGO)
# algo = <ALGO>

# List the algorithms the engine index lists (the cached or the release's
# copy), with their fee ceiling, and exit; with --json, one array of {name,
# coin, class, fee_bps, aliases, unit, hive, hive_units, default,
# requirements, options, refused}
# (--list-algorithms)
list_algorithms = false

# Hold an algorithm's engine at a version of the signed index, ALGO=VERSION
# (repeatable, or comma-separated): that version runs, from the cache or
# downloaded, and the hourly update leaves the algorithm alone
# (--engine, FEARMINER_ENGINE)
# engine = []

# An option of the algorithm's engine, NAME=VALUE (repeatable, or
# comma-separated): --list-algorithms says which an algorithm has and the
# values each takes. One the algorithm does not have, or a value it does not
# take, is refused
# (--engine-opt, FEARMINER_ENGINE_OPT)
# engine_opt = []

# The option an earlier miner had for one engine's precision: now --engine-opt
# precision=VALUE, which this still sets for an algorithm whose engine has it.
# Ignored by the others
# (--tsc-precision, FEARMINER_TSC_PRECISION)
# tsc_precision = <VALUE>

[network]

# Reach every pool through this SOCKS5 proxy (Tor: socks5://127.0.0.1:9050),
# with a username and a password as socks5://user:pass@host:port. The pool
# names are sent to the proxy, which resolves them: no DNS query leaves the
# machine for them, and a .onion pool works. A proxy that fails is a
# connection that failed; the pool is never contacted directly. socks5h:// is
# accepted and means the same
# (--proxy, FEARMINER_PROXY)
# proxy = <URL>

# How the pool names are resolved: system (the operating system's resolver),
# doh (DNS over HTTPS at --doh-url, the system resolver when the endpoint does
# not answer, never for a name it says does not exist) or doh-strict (DNS over
# HTTPS and nothing else). DoH hides the names from the local resolver, not
# the pool from the network: the TLS SNI stays visible. Moot with --proxy
# (--dns, FEARMINER_DNS)
dns = "system"

# The DNS-over-HTTPS resolver (RFC 8484) for --dns doh and doh-strict. Name it
# by its IP (https://1.1.1.1/dns-query) when the resolver's own name is what
# the local DNS cannot resolve
# (--doh-url, FEARMINER_DOH_URL)
doh_url = "https://cloudflare-dns.com/dns-query"

# The address families a pool is reached on: any (IPv6 first, IPv4 250 ms
# later, the first to connect wins), 4 or 6
# (--ip, FEARMINER_IP)
ip = "any"

# IPv4 only: the same as --ip 4
# (--ipv4-only)
ipv4_only = false

# IPv6 only: the same as --ip 6
# (--ipv6-only)
ipv6_only = false

# Trust a pool's TLS certificate on first use: remember its fingerprint at the
# first handshake (tls-pins.json in the state directory) and refuse any other
# certificate from that pool afterwards. For a node or a P2Pool on a
# self-signed certificate; a pool with --tls-fingerprint or --tls-spki is
# checked against its pin instead
# (--tls-tofu, FEARMINER_TLS_TOFU)
tls_tofu = false

# Accept whatever TLS certificate a stratum+ssl:// pool presents: no chain,
# name or expiry check. For a TLS port forward or a proxy, where the name
# dialled is not the pool's and the public roots refuse a path that works (a
# network that blocks plaintext stratum, say). The session stays encrypted,
# but anyone on the path can impersonate the pool, which every start says
# (E120). A pool with --tls-fingerprint or --tls-spki is still checked against
# its pin, and the fee sessions go the way the pools go. Refused with
# --tls-tofu, and with no stratum+ssl:// pool without a pin to apply it to
# (--tls-insecure, FEARMINER_TLS_INSECURE)
tls_insecure = false

# Forget the certificate remembered for this pool (host:port, as the E118 line
# prints it) before connecting, so the one it presents now is trusted and
# remembered instead. Repeat it for several pools
# (--tls-tofu-reset)
# tls_tofu_reset = []

# A relay of your own for the remote control, tried before the built-in one
# (wss://relay.fearminer.com): wss://HOST[:PORT], or ws:// for one on this
# machine or this network. Repeat it for several. Nothing is contacted until
# the rig is enrolled (fearminer enroll)
# (--remote-relay, FEARMINER_REMOTE_RELAY)
# remote_relay = []

# Minutes a new wallet from a cockpit's mining sheet waits before it applies,
# announced with both addresses; any cockpit or `fearminer remote cancel`
# drops it meanwhile. 0 applies at once
# (--remote-wallet-delay, FEARMINER_REMOTE_WALLET_DELAY)
remote_wallet_delay = 0

# No automatic update. A service the cockpit can update (Linux, systemd, with
# its updater) installs a newer release by itself, within two hours of seeing
# it; with this, only the cockpit's Update button or fearminer service update
# does. The cockpit can turn it back on or off for the rig
# (--no-auto-update, FEARMINER_NO_AUTO_UPDATE)
no_auto_update = false

# Join the fleet of this code at start (fm1_..., from the cockpit's Add a
# rig): the same as `fearminer enroll CODE`, for a service, a HiveOS flight
# sheet, an mmpOS miner profile or a provisioning script. Nothing happens once
# the rig is in that fleet
# (--enroll, FEARMINER_ENROLL)
# enroll = <CODE>

[devices]

# GPUs to mine on, comma separated (default: all): an index as --list-devices
# prints it (0), a PCI id (pci:0000:41:00.0, 41:00.0, or the bus alone as
# pci:41 in hex or bus:65 in decimal), a UUID as --list-devices prints it
# (GPU-3f2a..., whole), a vendor (nvidia, amd, intel: every card of it), or
# cards to leave out with a leading ! (!1, !pci:41:00.0, !GPU-3f2a...,
# !nvidia), or none for no GPU at all (the CPU threads alone; the only way to
# leave out the GPU of an Apple silicon Mac). A list of cards to use and a
# list to leave out do not mix; the CPU is chosen with -t, not here. On NVIDIA
# the exact cards are picked; the Vulkan and Metal engines take the first N
# cards and accept only -d 0..N-1
# (--devices, FEARMINER_DEVICES)
# devices = <LIST>

# What to do when -d names a card this machine does not have: match refuses
# the start (E206); first and last keep the configuration and mine on the
# cards present, the per-card lists (--temp-limit 85,80) laid over them from
# the first position on, or from the last back
# (--device-missing, FEARMINER_DEVICE_MISSING)
device_missing = "match"

# Pause a GPU whose core stays at or over this temperature, in degrees
# Celsius, for --temp-hold seconds, until it has cooled to --temp-resume; 0
# turns the core cut-off off. One value for every card, or one per card in -d
# order (85,80,_,90: _ keeps the default, a shorter list leaves the rest at
# it)
# (--temp-limit, FEARMINER_TEMP_LIMIT)
temp_limit = 90

# Core temperature a GPU paused by --temp-limit resumes mining at, in degrees
# Celsius; must be under --temp-limit. One value for every card, or one per
# card in -d order, as --temp-limit
# (--temp-resume, FEARMINER_TEMP_RESUME)
temp_resume = 75

# Pause a GPU whose memory sensor stays at or over this temperature for
# --temp-hold seconds, until it has cooled by --temp-hysteresis; 0 turns the
# memory cut-off off. Cards without the sensor are not judged on it
# (--temp-limit-mem, FEARMINER_TEMP_LIMIT_MEM)
temp_limit_mem = 105

# Pause a GPU whose hotspot sensor stays at or over this temperature for
# --temp-hold seconds, until it has cooled by --temp-hysteresis; 0 turns the
# hotspot cut-off off. Cards without the sensor are not judged on it
# (--temp-limit-hotspot, FEARMINER_TEMP_LIMIT_HOTSPOT)
temp_limit_hotspot = 100

# How far under its limit the memory or hotspot sensor must cool before the
# GPU resumes, in degrees Celsius. The core keeps its own pair, --temp-limit
# and --temp-resume
# (--temp-hysteresis, FEARMINER_TEMP_HYSTERESIS)
temp_hysteresis = 10

# How long a sensor must stay at or over its limit before the GPU is paused,
# in seconds; a shorter spike changes nothing. 0 pauses at the first reading
# (--temp-hold, FEARMINER_TEMP_HOLD)
temp_hold = 15

# Stop the miner (exit code 11) when a paused GPU's core stays at or over this
# temperature for --temp-hold seconds, counted from the pause: the last resort
# against a card that keeps heating while paused. 0, the default, turns it
# off; must be over --temp-limit
# (--temp-shutdown, FEARMINER_TEMP_SHUTDOWN)
temp_shutdown = 0

# Do not open NVML: no GPU sensors (temperatures, fan, power, clock, throttle,
# energy), the thermal cut-off has nothing to read and mining goes on. For a
# driver whose NVML misbehaves
# (--no-nvml, FEARMINER_NO_NVML)
no_nvml = false

# CPU mining threads: a count (8), a percentage of the automatic choice (50%,
# a hint rounded to a thread), a delta of it (-2, +2), or one per algorithm
# (ALGO:16,OTHER:32, with a bare value for the others). The automatic choice
# is 0 on a rig with a GPU (the CPU earns about 0.5% of the rate there for 17%
# of the power) and every thread but two on a machine without one; for an
# algorithm whose engine says what a thread needs of the cache, one thread per
# physical core, capped by the L3 cache. More than the machine can spare
# (every thread but two, and one per card) is capped to that, and the cpu line
# of the log says so
# (--threads, FEARMINER_THREADS)
# threads = <N|N%|-N|ALGO:N,...>

# Mine on integrated GPUs too, even beside a discrete one
# (--igpu, FEARMINER_IGPU)
igpu = false

# Do not act on the checks run before the first connection (driver version,
# compute capability, free GPU memory): the report is still printed, but no
# card is left out and nothing stops the start
# (--skip-preflight, FEARMINER_SKIP_PREFLIGHT)
skip_preflight = false

# Measure the GPU launch geometry again, ignoring the cached result
# (--retune, FEARMINER_RETUNE)
retune = false

# Run the known-answer test of the engines: on a mining run, always at start
# (it is otherwise skipped when the same binary, engine, driver and cards
# passed it before); alone, without a pool or a wallet, run it offline for the
# algorithm of -a (or for ALGO as --self-test=ALGO, or for every one with
# --self-test=all), print the verdict per device and exit 0, or 3 on a failure
# (--self-test, FEARMINER_SELF_TEST)
# self_test = <ALGO>

# Nonces the self-test searches on each card, every one re-hashed on the CPU
# (--self-test-nonces, FEARMINER_SELF_TEST_NONCES)
self_test_nonces = 256

# Re-check every GPU solution on the CPU before it is submitted (`on`, the
# default) or not (`off`): a wrong one is dropped and counted as invalid on
# the card's row instead of rejected by the pool. CPU solutions are not
# re-checked either way
# (--verify-shares, FEARMINER_VERIFY_SHARES)
verify_shares = "on"

# GPU batch size, in nonces per launch: a floor, rounded up to whole passes of
# the card's tuned geometry (the start line says the batch in force)
# (--gpu-batch, FEARMINER_GPU_BATCH)
gpu_batch = 1000000

# CPU batch size, in hashes between cancellation checks
# (--cpu-batch, FEARMINER_CPU_BATCH)
cpu_batch = 1000

# Pause between GPU batches, in milliseconds (0 = none)
# (--throttle, FEARMINER_THROTTLE)
throttle = 0

# List the GPUs this machine can mine on (index, name, PCI id, UUID) and exit;
# with --json, the machine-readable listing (the cards with their memory,
# compute capability, driver, vendor and engine, the CPU, the RAM)
# (--list-devices)
list_devices = false

# With --list-devices or --list-algorithms: print the listing as JSON. With
# --benchmark: print the machine-readable report on stdout (one JSON document,
# docs/benchmark-report.md), the progress on stderr
# (--json)
json = false

[cpu]

# Pin the CPU workers to these logical CPUs, in worker order, instead of the
# automatic placement (one per physical core, spread over the NUMA nodes): a
# hex mask (0xff, bit i for CPU i) or a list (0-7,16-23)
# (--cpu-affinity, FEARMINER_CPU_AFFINITY)
# cpu_affinity = <MASK|LIST>

# The CPU workers' priority, 0 (idle) to 5 (highest), the scale XMRig uses:
# nice 19, 5, 0, -5, -10, -15 on Linux, the thread priority class on Windows.
# Above 2 needs a privilege on Linux. Default: the process's own
# (--cpu-priority, FEARMINER_CPU_PRIORITY)
# cpu_priority = <0-5>

# For an algorithm whose engine asks for them: the MSR tweaks (the CPU's
# prefetchers, XMRig's public values), applied through fearminer-helper before
# the first connection and restored at exit. auto picks the preset from the
# CPU (zen1, zen2, zen3, zen4, zen5, intel) and skips with a coded line, never
# a refusal to start, when the helper is missing or the machine cannot take
# them (a VM, kernel lockdown, no msr module); off writes nothing; a preset
# name or a custom list addr:value:mask,... forces the values, on the
# registers the presets tune only (0x1a4, 0xc0011020 to 0xc0011022,
# 0xc001102b)
# (--msr, FEARMINER_MSR)
msr = "auto"

# For an algorithm whose engine asks for huge pages: reserve 1 GiB pages for
# its dataset (three per NUMA node) when the CPU has them (pdpe1gb), 1 to 3 %
# over 2 MiB pages. Off by default, as in XMRig. Used only where the kernel's
# default huge page size is 1 GiB (default_hugepagesz=1G on the kernel command
# line)
# (--1gb-pages, FEARMINER_1GB_PAGES)
huge_pages_1g = false

# The privileged helper (fearminer-helper), run as sudo -n PATH for the MSR
# tweaks and the huge-page reservation. Default: the installed
# /usr/local/bin/fearminer-helper (the path the sudoers line names), else the
# copy beside the miner's own binary. PATH given is the only path tried: the
# installed helper is not tried behind it, and E601 says so when sudo refuses
# PATH or nothing is there. Nothing usable at PATH is no refusal to start: a
# run that needs it says E601 and mines without the tweaks. Not used when the
# miner is itself root (--allow-root): it then does the same in-process
# (--helper, FEARMINER_HELPER)
# helper = <PATH>

[output]

# Address the stats endpoint listens on
# (--api-bind, FEARMINER_API_BIND)
api_bind = "127.0.0.1:4300"

# Do not serve the stats endpoint
# (--no-api, FEARMINER_NO_API)
no_api = false

# Plain scrolling log instead of the full-screen panel (what a pipe and a dumb
# terminal get anyway)
# (--no-tui, FEARMINER_NO_TUI)
no_tui = false

# No colour in the log, and the panel in the terminal's own colours (NO_COLOR
# in the environment does the same)
# (--no-color, FEARMINER_NO_COLOR)
no_color = false

# Debug-level log
# (--verbose, FEARMINER_VERBOSE)
verbose = false

# Also write the log to this file: one line per record, UTC timestamp, no
# colour, the pool password masked. Appended to, never truncated; rotated by
# size (--log-max-size, --log-keep). Written in both the panel and the plain
# mode
# (--log-file, FEARMINER_LOG_FILE)
# log_file = <PATH>

# Level of the log file, apart from the console's: trace, debug, info, warn or
# error. Default: debug with -v, info otherwise
# (--log-level-file, FEARMINER_LOG_LEVEL_FILE)
# log_level_file = <LEVEL>

# Size, in MB, at which the log file is rotated to <PATH>.1, .2, ...
# (--log-max-size, FEARMINER_LOG_MAX_SIZE)
log_max_size = 10

# Rotated log files kept (<PATH>.1 to <PATH>.N); 0 starts the file over
# (--log-keep, FEARMINER_LOG_KEEP)
log_keep = 5

# Send no telemetry at all: no install id is drawn or kept, and nothing goes
# to telemetry.fearminer.com (see Telemetry below). The signed fee terms are
# still fetched from cfg.fearminer.com
# (--no-telemetry, FEARMINER_NO_TELEMETRY)
no_telemetry = false

# Minutes between two telemetry beats, 5 to 1440: under 5 is raised to 5 and
# over a day lowered to a day, and the log says so
# (--telemetry-interval, FEARMINER_TELEMETRY_INTERVAL)
telemetry_interval = 15

[history]

# Keep this rig's own history in <state dir>/history.bin (`on`, the default)
# or not (`off`): one sample every 10 s for the last 24 h, then one a minute
# for a week, one every five minutes for a month and one an hour beyond, read
# by GET /api/v1/history and by fearminer history. Off writes nothing and
# keeps nothing
# (--history, FEARMINER_HISTORY)
history = "on"

# Days of history kept. Beyond a week the samples are five minutes apart,
# beyond a month an hour apart, so ninety days weigh a few megabytes
# (--history-retention, FEARMINER_HISTORY_RETENTION)
history_retention = 90

# Hard bound on the history file, in MB: the file is laid out to fit it from
# the first byte and never grows past it. The bound wins over
# --history-retention, which is cut back to fit
# (--history-max-size, FEARMINER_HISTORY_MAX_SIZE)
history_max_size = 32

[benchmark]

# Measure the hashrate and the power of this machine and exit; with -a all, or
# a list (-a ALGO,OTHER), every algorithm in turn, then a summary
# (--benchmark)
benchmark = false

# Benchmark length per algorithm, in seconds: 10 by default for one algorithm,
# 60 for several
# (--duration)
# duration = <SECS>

# Deterministic benchmark: the work and every worker's nonce sequence derive
# from this seed, the run ends after --bench-solutions solutions per worker
# instead of --duration, every solution is re-checked on the CPU, and a
# checksum of them is printed; two runs on the same hardware print the same
# checksum, a hardware error does not
# (--bench-seed)
# bench_seed = <N>

# Solutions per worker a seeded benchmark runs to
# (--bench-solutions)
bench_solutions = 4

# Untimed hashing after the engine is ready (its setup, its autotune and its
# first search done), before the clock starts: a card reaches its working
# temperature and clocks first. 0 by default: the clock starts as soon as
# every device is ready
# (--warmup)
warmup = 0

# Write the benchmark's machine-readable report (docs/benchmark-report.md,
# schema fearminer.benchmark/1) to FILE, written aside then renamed, on
# success and on failure alike
# (--report)
# report = <FILE>

[supervisor]

# Run the miner as one process, without the supervisor that restarts it after
# a crash: for systemd, HiveOS or another watchdog that restarts it itself,
# and for debugging
# (--no-supervisor, FEARMINER_NO_SUPERVISOR)
no_supervisor = false

# Seconds the supervisor waits for the mining process to stop after SIGTERM or
# Ctrl+C before killing it
# (--stop-timeout, FEARMINER_STOP_TIMEOUT)
stop_timeout = 8

# Restarts the supervisor allows within --restart-window before it gives up
# (exit code 12) and runs --on-failure
# (--max-restarts, FEARMINER_MAX_RESTARTS)
max_restarts = 5

# The window of --max-restarts, in minutes
# (--restart-window, FEARMINER_RESTART_WINDOW)
restart_window = 30

# What the supervisor does when it gives up: exit, or script:<path> to run
# that script first (FEARMINER_EXIT_CODE, FEARMINER_CAUSE and
# FEARMINER_RESTARTS in its environment), then exit
# (--on-failure, FEARMINER_ON_FAILURE)
on_failure = "exit"

# Run even when another fearminer is already running on this account (the
# single-instance lock is skipped)
# (--allow-multiple, FEARMINER_ALLOW_MULTIPLE)
allow_multiple = false

# Mine as root. Without it a miner started as root exits with code 3: it needs
# no privileges, and a bug or a hijacked configuration would have them all.
# HiveOS runs every miner as root and passes it
# (--allow-root, FEARMINER_ALLOW_ROOT)
allow_root = false

# Clear the crash counters kept per GPU across restarts, then start as usual;
# alone, without a pool, just clear them and exit
# (--reset-crashes)
reset_crashes = false

[watchdog]

# Turn the watchdog off: no hang, hashrate, share or reject check, no
# quarantine; a lost card leaves the others mining either way
# (--no-watchdog, FEARMINER_NO_WATCHDOG)
no_watchdog = false

# Seconds a search may run without a sign of life from the GPU before the card
# is declared hung and the miner exits for a restart (code 10)
# (--hang-timeout, FEARMINER_HANG_TIMEOUT)
hang_timeout = 60

# Seconds a GPU may report no hashes while the other cards mine before the
# miner exits for a restart (code 11); after a 5 min grace at start and after
# a thermal resume
# (--zero-hashrate-timeout, FEARMINER_ZERO_HASHRATE_TIMEOUT)
zero_hashrate_timeout = 300

# Seconds without any accepted share, from any device, after the session
# connected, before the miner moves to the next pool; a second such period on
# the next pool exits for a restart (code 11). 0 turns it off. A single card
# that earns nothing while the others do is judged on its own (ten times its
# expected time between shares, 10 to 60 minutes)
# (--no-share-timeout, FEARMINER_NO_SHARE_TIMEOUT)
no_share_timeout = 1800

# The least a GPU's ten-minute average may be: a share of its reference
# (`50%`, the best ten-minute average seen this session, or
# --hashrate-reference) or an absolute rate (`300M`, `1.2G`). Under it the
# card is Degraded; still under after --hashrate-grace, the miner exits for a
# restart (code 11). The rig's summed average is held to the same bound. 0
# turns it off
# (--hashrate-min, FEARMINER_HASHRATE_MIN)
hashrate_min = "50%"

# The most a GPU's ten-minute average can honestly be, in the same forms; over
# it the figure is wrong and is reported, never restarted. 0 turns it off
# (--hashrate-max, FEARMINER_HASHRATE_MAX)
hashrate_max = 0

# Seconds a GPU may stay under --hashrate-min before the miner exits for a
# restart; 0 never restarts it (Degraded and the alert only)
# (--hashrate-grace, FEARMINER_HASHRATE_GRACE)
hashrate_grace = 300

# The reference the percentages of --hashrate-min and --hashrate-max refer to,
# in H/s (`600M`): one value for every card, or one per card in engine order,
# comma separated. Learnt when not given: the best ten-minute average seen
# this session
# (--hashrate-reference, FEARMINER_HASHRATE_REFERENCE)
# hashrate_reference = <RATE[,RATE...]>

# How many expected share intervals (the difficulty over the card's rate) a
# GPU may go without finding a share, never under 10 minutes, before it is
# Degraded and its search restarted; a second famine exits for a restart (code
# 11). 0 turns it off
# (--share-famine, FEARMINER_SHARE_FAMINE)
share_famine = 5

# Shares of one GPU the pool may refuse in a row (stale ones aside) before the
# card is Degraded until it has a share accepted; also the solutions the CPU
# re-check may refuse within ten minutes. 0 turns it off
# (--max-rejects-device, FEARMINER_MAX_REJECTS_DEVICE)
max_rejects_device = 5

# Shares the pool may refuse in a row, from any device, before the session is
# reconnected; a second such run moves to the next pool. 0 turns it off
# (--max-rejects, FEARMINER_MAX_REJECTS)
max_rejects = 15

# Submits left unanswered by the pool for --submit-timeout, in a row, before
# the session is reconnected; a second such run moves to the next pool. 0
# turns it off
# (--max-no-submit-responses, FEARMINER_MAX_NO_SUBMIT_RESPONSES)
max_no_submit_responses = 10

# Restarts blamed on one GPU within --restart-window before it is Quarantined
# at the next start: left out of mining while the others carry on, until the
# miner is restarted. Never the last device that could mine. 0 turns it off
# (--device-quarantine, FEARMINER_DEVICE_QUARANTINE)
device_quarantine = 3

[notifications]

# Send the alerts to this URL as JSON (POST, format version 1, see the
# README); repeat it, or separate the URLs with commas, for several. Retried
# on a 5xx or a network error, never on a 4xx
# (--notify-url, FEARMINER_NOTIFY_URL)
# notify_url = []

# Send the alerts to a Telegram chat through a bot: the bot's token and the
# chat id, as BOT_TOKEN:CHAT_ID
# (--notify-telegram, FEARMINER_NOTIFY_TELEGRAM)
# notify_telegram = <BOT_TOKEN:CHAT_ID>

# Send the alerts to a Discord channel through its webhook URL
# (--notify-discord, FEARMINER_NOTIFY_DISCORD)
# notify_discord = <WEBHOOK_URL>

# Sign each --notify-url body with HMAC-SHA256 under this secret
# (X-FearMiner-Signature: sha256=<hex>), so the receiver can check it came
# from this miner
# (--notify-secret, FEARMINER_NOTIFY_SECRET)
# notify_secret = <SECRET>

# The least severity that is sent: info, warning, error or critical
# (--notify-min-severity, FEARMINER_NOTIFY_MIN_SEVERITY)
notify_min_severity = "warning"

# Send one test message (a rig_up) to every notifier and the heartbeat's
# /start, print what happened, and exit: 0 when every delivery went through, 1
# otherwise
# (--notify-test)
notify_test = false

# Ping this URL every 60 s (GET; POST with --heartbeat-post), plus <URL>/start
# at startup and <URL>/fail on a critical event, the healthchecks.io
# convention; an Uptime Kuma push URL works as is
# (--heartbeat-url, FEARMINER_HEARTBEAT_URL)
# heartbeat_url = <URL>

# POST the heartbeat with a small JSON body (hashrate, effective hashrate,
# shares, uptime, restarts) instead of a GET
# (--heartbeat-post, FEARMINER_HEARTBEAT_POST)
heartbeat_post = false

[oc]

# Core clock offset in MHz, signed (+100, -50), applied through the driver
# (NVIDIA, driver 520 or later). One value for every card, or one per card in
# -d order (100,_,-50: _ leaves that card alone). Without any OC option the
# miner touches no clock, power limit or fan register. Read back after it is
# set; refused with its code when the driver says no (E703: run as root with
# --allow-root)
# (--cclock, FEARMINER_CCLOCK)
# cclock = <MHZ[,MHZ...]>

# Lock the core clock at this many MHz (what nvidia-smi -lgc does); 0 removes
# the lock. One value for every card, or one per card in -d order. The driver
# cannot read a lock back, so at exit the lock is reset to the driver's
# default
# (--lock-cclock, FEARMINER_LOCK_CCLOCK)
# lock_cclock = <MHZ[,MHZ...]>

# Memory clock offset in MHz, signed (+800, -500). One value for every card,
# or one per card in -d order
# (--mclock, FEARMINER_MCLOCK)
# mclock = <MHZ[,MHZ...]>

# Lock the memory clock at this many MHz (nvidia-smi -lmc), which must be one
# of the steps the card publishes (405, 810, 5001, 10251...; E701 lists them
# otherwise); 0 removes the lock. One value for every card, or one per card in
# -d order
# (--lock-mclock, FEARMINER_LOCK_MCLOCK)
# lock_mclock = <MHZ[,MHZ...]>

# Power limit, in watts (220) or as a percentage of the card's default limit
# (80%), inside the range the card publishes (E702 shows the minimum and the
# maximum otherwise). One value for every card, or one per card in -d order
# (--pl, FEARMINER_PL)
# pl = <W|N%[,...]>

# Fan speed in percent (70%), or auto to give the fan back to the driver's
# curve. One value for every card, or one per card in -d order. A card without
# fan control (a laptop) refuses it (E704)
# (--fan, FEARMINER_FAN)
# fan = <N%|auto[,...]>

# Seconds to wait, after a card has started mining (its first accepted share,
# or 30 s at most), before its core offset and lock are applied: for the rigs
# that crash when the offset lands on a cold card. 0 applies them at start
# with the rest
# (--oc-delay, FEARMINER_OC_DELAY)
oc_delay = 0

# Ignore every OC option and any [oc] section of the file: the miner touches
# no clock, power limit or fan register, and says so at start. For a rig whose
# OC is set outside (HiveOS, Afterburner, a script)
# (--no-oc, FEARMINER_NO_OC)
no_oc = false

# Put every selected card at the driver's defaults (locks removed, offsets at
# 0, the default power limit, the fan on its curve) before the OC options are
# applied
# (--oc-reset-on-start, FEARMINER_OC_RESET_ON_START)
oc_reset_on_start = false

# Run this program once per card before mining starts, directly, never through
# a shell, with FEARMINER_DEVICE, FEARMINER_PCI_BUS, FEARMINER_UUID and
# FEARMINER_ALGO in its environment; 30 s at most, the exit code logged (E707
# when not 0)
# (--oc-script, FEARMINER_OC_SCRIPT)
# oc_script = <PATH>

# A set per algorithm, applied at start for the algorithm mined, over the [oc]
# values above and under the environment and the command line: one table per
# algorithm of the engine index ([oc.quantus], [oc.randomx], [oc.pearl],
# [oc.tensorcash], [oc.commonfoundry]), with any of the six value options
# (cclock, lock_cclock, mclock, lock_mclock, pl, fan), one value for every
# card or one per card in -d order, as under [oc]. --dry-run prints the sets
# and the policy they make.
#
# [oc.quantus]
# cclock = 100
# lock_mclock = "5001,_"
# pl = "80%"

[commands]

# Which commands a running miner takes beyond the reversible ones: read (the
# default: pause, resume, toggle and retune only), operate (restart and stop
# too), sensitive (the wallet, the pools and the overclocking too). A command
# over the level is refused with E217, a valid token or not
# (--unrestricted-api, FEARMINER_UNRESTRICTED_API)
unrestricted_api = "read"

# Run this program when EVENT happens, directly, never through a shell, with
# FEARMINER_EVENT and the event's context in its environment; 30 s at most,
# the exit code logged (E139 when not 0). Repeat it, or separate the hooks
# with commas, for several. The events: start, exit, crash, pause, resume,
# pool-switch, share-rejected-high, low-hashrate, temp-high, device-lost
# (--hook, FEARMINER_HOOK)
# hook = []

# Watch the configuration file and reload it when it changes. Off by default:
# SIGHUP and PUT /api/v1/config reload it either way. A value the new file
# gives that does not validate is refused whole (E220) and the configuration
# in force is kept
# (--watch-config, FEARMINER_WATCH_CONFIG)
watch_config = false

# Run without a console: the process detaches from the terminal and keeps
# mining after the shell that started it is gone. Implies --no-tui (there is
# no screen to draw on); give --log-file to keep the log
# (--background, FEARMINER_BACKGROUND)
background = false

# The whole process's scheduling priority, 0 (idle) to 5 (highest), on the
# same scale as --cpu-priority, which sets the worker threads' priority alone.
# Above 2 needs a privilege on Linux; refused by the OS, it is E613 and the
# miner keeps the normal priority
# (--priority, FEARMINER_PRIORITY)
# priority = <N>

notifications and heartbeat

Set up alerts #

Send mining events to your chosen notification service or webhook. Use a heartbeat to monitor whether the rig is still reporting.

Details and behavior

To a Telegram chat, a Discord channel, your own webhook, or all three.

--notify-testsends one rig_up to each and to the heartbeat's /start, prints the outcome per destination, exits 0 when every delivery went through
every messagenames the rig: the worker name, else the host's name
an eventa non-blocking push on a bounded queue
deliverya 10 s timeout, retried after 5, 30 and 120 s on a 5xx or a network error, never on a 4xx

The bot token, the webhook tokens and the secret never appear in the log.

$ fearminer -o stratum+ssl://POOL:PORT -u YOUR_WALLET --notify-telegram BOT_TOKEN:CHAT_ID --notify-test
$ fearminer -o stratum+ssl://POOL:PORT -u YOUR_WALLET --notify-discord https://discord.com/api/webhooks/...
$ fearminer -o stratum+ssl://POOL:PORT -u YOUR_WALLET --notify-url https://example.com/hook --notify-secret SECRET --notify-min-severity error
$ fearminer -o stratum+ssl://POOL:PORT -u YOUR_WALLET --heartbeat-url https://hc-ping.com/UUID
The events

The events #

eventseveritywhen
rig_upinfoThe miner is up and mining.
rig_downcriticalA clean stop, or the supervisor giving up.
gpu_downerrorA card the driver reported gone (Lost).
gpu_unstablewarningA card whose non-stale rejects reach five, a card that failed its self-test, or a watchdog verdict on it.
gpu_invalid_shareerrorA card handed back a solution the CPU re-check refused before submit; invalid in the annotations is the card's count so far.
gpu_degradedwarningA card the watchdog holds Degraded: refusals in a row, a share famine (the cause in the message).
gpu_quarantinederrorA card the watchdog left out of mining: restarted too often.
hashrate_lowwarningThe rate under 70 % of the session's best ten-minute average; with a device, that card's ten-minute average under --hashrate-min.
hashrate_recoveredinfoBack at 90 % of it; with a device, the card back over its minimum.
hashrate_suspectwarningA figure over --hashrate-max: wrong, not the card.
temp_highwarningA card held by the thermal cut-off.
temp_criticalcriticalA pause over 10 min, a reading 10 °C over the limit, or a card past --temp-shutdown, which stops the miner.
shares_rejected_highwarningMore than 5 % of 50 or more shares rejected.
pool_disconnectedwarningThe connection to the pool lost, or refused.
pool_failoverwarningThe session moved to a backup.
pool_recoveredinfoBack on the primary, or reconnected.
wallet_changedcriticalThe wallet mined to is not the one of the last session on that pool.
watchdog_restarterrorThe supervisor restarted the mining process (the cause in the message).
devfee_start · devfee_stopinfoA dev-fee round starts, ends.
block_foundinfoReserved: no pool this build speaks says whether a share was a block.
update_availableinfoThe terms carry a newer version.
What keeps the noise down

What keeps the noise down #

  • --notify-min-severity (warning by default) is the bar under which nothing is sent.
  • Pending when it appears, firing once it has held for its confirmation delay: hashrate_low 120 s, gpu_down 30 s, temp_high 10 s, pool_disconnected 60 s; the others immediate. A pool back in thirty seconds is never mentioned.
  • A firing condition repeats every four hours at most, and is resolved with a message when it clears: hashrate_low by hashrate_recovered, pool_disconnected and pool_failover by pool_recovered, temp_high by the resume, gpu_down by the card mining again.
  • rig_down covers gpu_down, which covers hashrate_low, as does pool_disconnected: a covered alert is not told, and neither is its resolution.
  • What is told within thirty seconds goes out as one group, one message per chat; a critical event does not wait. The log shows alert firing: ... and alert resolved: ... for what was sent. /stats counts alerts_firing and notifications_sent.
The webhook

The webhook #

One POST per notification: Content-Type application/json, User-Agent fearminer/<version>, X-FearMiner-Event with the event's name, and with --notify-secret X-FearMiner-Signature, the HMAC-SHA256 of the body under the secret. Body, format version 1:

POST your URL
Content-Type: application/json
User-Agent: fearminer/1.15.2
X-FearMiner-Event: gpu_down
X-FearMiner-Signature: sha256=<hex>

{
  "version": 1,
  "event": "gpu_down",
  "severity": "error",
  "status": "firing",
  "rig": "rig1",
  "ts": "2026-09-22T10:00:00.000Z",
  "fingerprint": "gpu_down/rig1/0",
  "labels": {"rig": "rig1", "device": "0", "pci": "0000:41:00.0", "device_name": "NVIDIA GeForce RTX 3090", "pool": "stratum+ssl://pool.example.com:3335"},
  "annotations": {"cause": "..."},
  "summary": "GPU0 lost (reported by the driver)",
  "details": ""
}
statusfiring or resolved
fingerprint<event>/<rig>/<device or ->: the same on both messages of one alert
labelsonly the keys that apply, device, pci and device_name for a card, pool when one is involved
annotationsthe event's figures (temp_c, cause, latest_version, ...)

Telegram gets a sendMessage with plain text (no Markdown), Discord a content with the same text, one message per group.

The heartbeat

The heartbeat #

--heartbeat-urlpinged every 60 s (± 10 %), a GET, or a POST with a small JSON body under --heartbeat-post
URL/startat startup, the healthchecks.io convention
URL/failon a critical event, the same convention

A service without them (an Uptime Kuma push URL, with its query string) works with the plain URL; its /start and /fail get 404.

Failures log at debug, one warning per ten minutes at most.

The ping: a 10 s timeout, never blocking mining.

Under the supervisor, the mining process sends the events and the heartbeat; the supervisor sends watchdog_restart and, giving up, rig_down, with the same settings.

GET  https://hc-ping.com/UUID          every 60 s
GET  https://hc-ping.com/UUID/start    at startup
GET  https://hc-ping.com/UUID/fail     on a critical event
POST {"rig","hashrate_hs","hashrate_effective_hs","shares_accepted","shares_rejected","uptime_secs","restarts","alerts_firing"}   --heartbeat-post

API

Use the local API #

Read mining status and send supported commands from your own tools. The API listens on the rig’s loopback address by default.

Details and behavior

A versioned API beside /stats, on 127.0.0.1:4300 by default: the reads, plus three writes.

POST /api/v1/oca set on a card
POST /api/v1/commandsa command
PUT /api/v1/configa configuration reload
--api-bind 0.0.0.0:4300opens it to the LAN
--no-apiturns it off

Every object under /api/v1 carries api_version (1), the path's version.

The server is up before the terms are fetched and before the first connection (zeros and nulls until then, mode already set), and stays up through reconnections and fee rounds.

Read the local miner’s hashrate. Example response excerpt:

curl -s http://127.0.0.1:4300/api/v1/summary | jq .hashrate
{ "local_hs": 618400000, "local_10m_hs": 611900000, "session_hs": 609800000, "effective_hs": 598200000, "effective_pct": 97.8 }

Units are in the field names.

_hshashes a second
_cdegrees Celsius
_wwatts
_sseconds
_pctpercent
429 with Retry-Afterpast 20 requests a second per peer on /api/v1/* and /openapi.json
405 with Allowa method a path does not take

A figure that cannot be computed yet is null.

Every write, POST /api/v1/oc, POST /api/v1/commands, PUT /api/v1/config, needs the token from anywhere, this machine included.

The token file is readable by the miner's user alone.

The token #

a loopback TCP peerneeds no token; that is the default bind
from another machineonly with --api-bind 0.0.0.0:4300: every /api/v1/* request must carry Authorization: Bearer <token>
the three writesneed it from anywhere, this machine included
a wrong token401, from anywhere
/healthz, /readyz, /stats, /hive-stats, /mmposnever ask for it

Token: 32 random bytes in base64url, made at the first start into <state dir>/api_token (mode 0600); the start log says where, never what.

fearminer token show prints it, fearminer token rotate replaces it; a running miner keeps the one it loaded until it restarts.

The token never goes in a URL.

Control endpoints and examples
endpointtokenwhat it returns
PUT /api/v1/configfrom anywhereNeeds the token from anywhere. Empty body: reread from the file, the environment and the command line. {"set": {"temp_limit": "85"}}: those keys over every source, winning at every later reload until written again or written as null, which hands the key back to the file. Validated whole before anything is applied; a configuration that does not validate is 422 with E220 and nothing changes. Answers {api_version, source, changed[], restart_required[], held[]}. 400: a key that is not an option. 422: a key that needs a restart (E219). 409: a run with no configuration to reload.
POST /api/v1/commandsfrom anywhereNeeds the token from anywhere: {"command": "pause", "devices": [0, 1]}, devices optional, left out for the whole rig. pause, resume, toggle and retune are taken by default; restart and stop need --unrestricted-api operate, else 403 with E217. Answers {api_version, command, outcome, paused, paused_devices}. 400: a name that is not a command (E216). 404: a card this run does not mine on (E218). No read on this path.
POST /api/v1/ocfrom anywhereNeeds the token from anywhere, this machine included. Body: {"device": 0, "core_offset_mhz": 100, "core_lock_mhz": 0, "mem_offset_mhz": 800, "mem_lock_mhz": 10251, "power_limit": "220", "fan": "70%"}; every value but device optional, power_limit in watts or "80%", fan a percentage or "auto", a lock of 0 unlocks. Applied at once, read back, recorded for the restore at exit. Answers {api_version, card}, the card as it reads after, a refused value in refused with its code. 400: a body that is not the set. 401: no token. 404: a card not under OC control. 409: a run without OC control.
$ curl -s http://127.0.0.1:4300/api/v1/summary | jq .hashrate
$ curl -s -H "Authorization: Bearer $(fearminer token show)" http://rig:4300/api/v1/devices
$ curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:4300/readyz
$ fearminer token rotate
$ curl -s -X POST -H "Authorization: Bearer $(fearminer token show)" -H 'Content-Type: application/json' -d '{"device": 0, "power_limit": "80%"}' http://127.0.0.1:4300/api/v1/oc
$ curl -s -X POST -H "Authorization: Bearer $(fearminer token show)" -H 'Content-Type: application/json' -d '{"command": "pause"}' http://127.0.0.1:4300/api/v1/commands
$ curl -s -X PUT -H "Authorization: Bearer $(fearminer token show)" http://127.0.0.1:4300/api/v1/config

Under HiveOS the stats port is fixed at 127.0.0.1:4300, where h-stats.sh reads /hive-stats. On a host reachable from untrusted networks, firewall the port before opening it with --api-bind.

Status endpoints
endpointtokenwhat it returns
GET /api/v1/summaryfrom another machineapi_version, version, build, uptime_s, algo, mode, session_connected, pool {url, index, is_primary, switches}, hashrate {local_hs, local_10m_hs, session_hs, effective_hs, effective_pct}, shares {accepted, rejected, stale, invalid, best_difficulty}, fee {rate_pct, seconds_mined_for_fee, seconds_mined_for_user, shares_for_fee, shares_for_user}, efficiency_kh_per_w, restarts, alerts_firing, wallet_changed, time_to_first_share_s, engines[] {algo, role, version, platform, source}, os, service, update_ready, update, engine_index {origin, url, key_id}, bench.
GET /api/v1/devicesfrom another machineapi_version and devices[], one per table row: index, kind, label, name, pci_bus_id, state, hashrate_hs, temp_c, fan_pct, power_w, power_limit_w, clock_mhz, throttle, shares {accepted, rejected, stale, invalid}, efficiency_kh_per_w, crashes; then sensors a card may have, null when it does not: temp_mem_c, temp_hotspot_c, energy_mj (driver counter in millijoules since it loaded), throttle_reasons (stable labels, [] when none), ecc_corrected, ecc_uncorrected (volatile, when ECC is on), pcie_replays, pcie_gen, pcie_width, pcie_max_gen, pcie_max_width.
GET /api/v1/poolsfrom another machineapi_version, active_index, and the failover list: per pool index, rank, is_primary, is_active and its record since the start, across reconnections: shares {accepted, rejected, stale, unanswered, best_difficulty} (best_difficulty is the best share the pool accepted), rejected_by_reason {low_difficulty, stale, duplicate, unknown_job, unauthorized, other}, uptime_s, reconnects, avg_reply_ms, latency_ms (moving median of the last twenty submit reply times, null under five), jobs_duplicate, jobs_replayed, nonce_space_exhausted.
GET /api/v1/historyfrom another machineThis rig's own history: ?from=&to=&step=&metric=&device=. Answers {api_version, from_ms, to_ms, step_s, layer, device, clock {drift_ms, gaps, samples}, t_ms[], series[{metric, unit, aggregate, values[]}]}: bucket starts once in t_ms, then one array per metric, null where nothing was sampled. layer is the resolution that answered (ten_second, minute, five_minute, hour), step_s the step the buckets are on; a finer step is raised to the layer's own, not refused. 400: a bound, a step, a metric or a device that is not one, or a range over 20 000 points (E202). 409: a run started with --history off (E223).
GET /api/v1/configfrom another machineapi_version and the effective configuration, never a secret: pools with pass "***" and the login cut at a colon, device selection, thresholds, api_bind, and the published lists reloadable[] and restart_required[] (Control a running miner).
GET /api/v1/ocfrom another machineapi_version, enabled (false without an OC option or with --no-oc), backend, delay_s, cards[], one per card under OC control: index, label, name, pci_bus_id, uuid, wanted (values asked, null where left alone), readback (core_mhz, mem_mhz, core_offset_mhz, mem_offset_mhz, power_limit_w, fan_pct, fan_manual), applied[], pending[] (held back by --oc-delay), refused[] (setting, code, reason), restore (what the card read before the run touched it).
GET /healthznever200 ok while the process answers; no data. Liveness probe.
GET /readyznever200 {ready: true} once a session is connected and a device mines, 503 {ready: false, reason} before. Readiness probe.
GET /openapi.jsonfrom another machineOpenAPI 3.0 for the above, /stats, /hive-stats and /mmpos. fearminer openapi prints the same; the archives carry it as openapi.json.
GET /stats · GET /hive-statsneverThe HiveOS custom-miner object: hs in kH/s per card (per CPU row on a CPU algorithm), total_khs their sum, temp, fan, uptime, ver, ar with four elements ([accepted, rejected, invalid, "invalid per row"]), algo, bus_numbers, the rows' state and crashes, the counters (hashes_total, accepted, rejected, shares_invalid, difficulty, best_difficulty, pool_rtt_ms, reconnects, wallet_changed, fee_percent, mode, time_to_first_share_s, hashrate_effective_hs, efficiency_kh_per_w, alerts_firing, ...) and devices with per-card shares (shares_invalid included), efficiency and sensors.

A summary, for example #

JSON example
{
  "api_version": 1, "version": "1.15.2", "build": "a1b2c3d4e", "uptime_s": 3600, "algo": "quantus", "mode": "mining",
  "session_connected": true,
  "pool": {"url": "stratum+ssl://pool.example.com:3335", "index": 0, "is_primary": true, "switches": 0},
  "hashrate": {"local_hs": 618400000, "local_10m_hs": 611900000, "session_hs": 609800000, "effective_hs": 598200000, "effective_pct": 97.8},
  "shares": {"accepted": 412, "rejected": 3, "stale": 2, "invalid": 0, "best_difficulty": 91200000000},
  "fee": {"rate_pct": 2.0, "seconds_mined_for_fee": 72, "seconds_mined_for_user": 3528, "shares_for_fee": 8, "shares_for_user": 404},
  "efficiency_kh_per_w": 2150.4, "restarts": 0, "alerts_firing": 0, "wallet_changed": false, "time_to_first_share_s": 12.3
}
Field definitions

mode is mining or monitoring. effective_hs and effective_pct are null under ten accepted shares in the window. efficiency_kh_per_w is null without a power reading. time_to_first_share_s is null before the first accepted share. Full schema of every object: /openapi.json.

A device, for example #

JSON example
{
  "api_version": 1,
  "devices": [{
    "index": 0, "kind": "gpu", "label": "GPU0", "name": "NVIDIA GeForce RTX 4070 Ti", "pci_bus_id": "0000:01:00.0", "state": "Mining",
    "hashrate_hs": 618400000, "temp_c": 64, "temp_mem_c": 78, "temp_hotspot_c": null, "fan_pct": 62, "power_w": 271, "power_limit_w": 285, "clock_mhz": 2610,
    "throttle": false, "throttle_reasons": ["power_cap"], "energy_mj": 9812044000, "ecc_corrected": null, "ecc_uncorrected": null,
    "pcie_replays": 0, "pcie_gen": 4, "pcie_width": 16, "pcie_max_gen": 4, "pcie_max_width": 16,
    "shares": {"accepted": 412, "rejected": 3, "stale": 2, "invalid": 0}, "efficiency_kh_per_w": 2281.9, "crashes": 0
  }]
}
Field definitions
stateone of the states of Choose and manage devices
throttle_reasons[] when the card is not throttled
shares.invalidcounts solutions the CPU re-check refused before submit, never seen by the pool (Check correctness and measure speed)
crashesthat card's counter, kept across restarts

A sensor the card or the driver does not give is null; with --no-nvml every sensor is null.

commands and hot reload

Control a running miner #

Pause, resume and apply supported changes without restarting the service. Some changes require the mining process to restart.

Details and behavior

Commands and a configuration reload work on a running miner, with no restart. Four ways in: the local API, the terminal panel, a signal, a file in the state directory. Nothing here leaves the machine.

reversible by default

pause, resume, toggle and retune are the only writes a miner takes by default. Each is reversible; none can move money.

three levels

Default: read. --unrestricted-api operate adds restart and stop, which end the mining; --unrestricted-api sensitive adds the wallet, the pools and the overclocking. Over the level: refused with E217, valid token or not, and told how to enable it.

nothing is interrupted

Pause: each worker finishes the search it is in. Reload: the whole configuration is validated before anything is applied. Pool change: the session ends cleanly at its next half-second round. The same process keeps mining throughout.

The commands #

commandlevelwhat it does
pausereadHolds the rig, or the cards named: each worker finishes the search it is in, then idles on the newest job. No connection dropped, nothing interrupted mid-batch. Rows read Paused (operator).
resumereadMine again. A rig-wide resume also releases the cards held one by one.
togglereadPause if mining, resume if paused: what SIGUSR1 and the terminal panel's p send.
retunereadRestarts the rig's search, or the named cards', on the newest job and with a fresh seed. The launch geometry is measured when a card's context is built and cached for the life of the process: a full re-measure is a restart with --retune.
restartoperateEnds the mining process; the supervisor starts it again. Exit code 14, not counted against --max-restarts. Needs --unrestricted-api operate.
stopoperateStop the miner for good. Needs --unrestricted-api operate.

Sensitive level: the wallet, the pool and login keys, the overclocking sets. The set of PUT /api/v1/config refuses them with E217 unless the miner was started with --unrestricted-api sensitive, whatever token was presented.

The level guards the API, and it alone.

the terminal panel's keysneed the terminal the miner draws on
a signalneeds the right to signal the process
a sentinel fileneeds write access to the miner's own state directory

<state dir>/stop stops a miner started with no unrestricted mode at all.

Four ways to send one

Four ways to send one #

  • POST /api/v1/commands, with the token from anywhere, this machine included (Use the local API).
  • The terminal panel: p holds the whole rig and lets it go again, 1 to 9 one card each (1 is GPU0).
  • SIGUSR1 toggles the rig's pause, one per signal. Send it to the pid a service manager knows, the supervisor's, which passes it to the mining process.
  • Sentinel files, no token and no right to signal needed: <state dir>/stop, /pause and /resume. The miner consumes each, that is deletes it, within a second. The same file written again is the same command again. A file that cannot be deleted is E137 and is not acted on.
$ curl -s -X POST -H "Authorization: Bearer $(fearminer token show)" -H 'Content-Type: application/json' -d '{"command": "pause", "devices": [0]}' http://127.0.0.1:4300/api/v1/commands
$ kill -USR1 $(pgrep -o fearminer)
$ touch ~/.cache/fearminer/pause
command  pause from file: the rig paused
command  stop from api refused: E217 command not allowed: stop needs --unrestricted-api operate

Every command is logged with its source (api, tui, signal, file) and its outcome, refused or not.

Hot reload

Hot reload #

SIGHUP, the file watched under --watch-config and PUT /api/v1/config all do the same.

  • The configuration is read again from the file, then the environment, then the command line, which keeps the last word, as at a start.
  • Validated whole before anything is applied.
  • The reloadable keys are applied.
  • What changed is printed, the wallet first.
a configuration that does not validaterefused whole with E220, the one in force kept entirely, the mining uninterrupted
SIGHUP, --watch-config, PUT /api/v1/config with no bodya changed key that needs a restart is not a failure: the rest is applied, the key named with E219
the set of PUT /api/v1/configstricter: a set naming such a key is refused with E219 and a 422, and nothing of that request is applied
$ fearminer -o stratum+ssl://POOL:PORT -u YOUR_WALLET --watch-config --log-file fearminer.log
$ kill -HUP $(pgrep -o fearminer)
$ curl -s -X PUT -H "Authorization: Bearer $(fearminer token show)" -H 'Content-Type: application/json' -d '{"set": {"temp_limit": "85"}}' http://127.0.0.1:4300/api/v1/config
reload   SIGHUP: 2 key(s) changed: temp_limit 90 -> 85 · url stratum+ssl://A -> stratum+ssl://B
reload   1 key(s) held from the API, over the file: temp_limit (write one as null to hand it back)
E219 the change needs a restart: algo (quantus -> randomx) is kept, the rest is applied

GET /api/v1/config serves reloadable[] and restart_required[]; fearminer --help prints them.

reloadablepool list and every per-pool value, failover timings, every --temp-* threshold, every watchdog threshold, notification targets and severity floor, heartbeat, log level, --history-retention, --history-max-size, overclocking sets, applied at once and with no --oc-delay
restart requiredalgorithm, device selection, thread count, API bind, engine and CPU knobs, network options, log file, --history itself, the supervisor's own settings, the command options themselves

Exhaustive together: every key the configuration file accepts is in exactly one.

  • A reload that changes the pool list ends the session on the air cleanly, at its next half-second round.
  • Nothing in flight, nothing held against the pool.
  • The next opens on the new primary, in the same process.
  • A key written with set keeps beating the file at every later reload.
  • Every reload names the keys it is holding, on the log and in held[].
  • Writing one as null hands it back, and needs no level.
Hooks

Hooks #

--hook <EVENT>:<PATH>, repeatable or comma-separated, runs a local program on an event.

  • The program is run directly, never through a shell.
  • It gets 30 s, then is killed.
  • Its exit code goes on the log, E139 when it is not zero.
  • Whatever a hook answers, the mining carries on.
--hookwhen it fires
startThe miner has started mining.
exitThe mining process is ending, cleanly.
crashThe mining process died and the supervisor is starting it again.
pause · resumeRig or card held or let go: a command, the terminal panel, a signal, a sentinel file or the thermal cut-off.
pool-switchThe session moved to another pool of the list, or back to the primary.
share-rejected-highThe pool is refusing too many shares (E114, E316).
low-hashrateThe hashrate is under --hashrate-min past the grace window (E313).
temp-highA card reached --temp-limit and was paused (E306).
device-lostThe driver reported a card gone (E302).

The context arrives in the environment, never on the command line: FEARMINER_EVENT always, then the fields the event has.

  • FEARMINER_DEVICE
  • FEARMINER_PCI_BUS
  • FEARMINER_UUID
  • FEARMINER_ALGO
  • FEARMINER_POOL
  • FEARMINER_CODE
  • FEARMINER_SUMMARY

A field the event does not carry is absent, not empty, so a script tells no card from card 0.

The four device variables are spelt as --oc-script spells them.

$ fearminer -o stratum+ssl://POOL:PORT -u YOUR_WALLET --hook temp-high:/opt/rig/hot.sh --hook device-lost:/opt/rig/lost.sh
# hot.sh: FEARMINER_EVENT, FEARMINER_DEVICE, FEARMINER_PCI_BUS, FEARMINER_UUID, FEARMINER_ALGO, FEARMINER_POOL, FEARMINER_CODE, FEARMINER_SUMMARY
E139 hook script failed: temp-high /opt/rig/hot.sh exited 1 after 0.4 s
  • --check-config checks the shape of the value and nothing else.
  • The path is checked when the event fires, so --hook temp-high:/nonexistent passes and is E139 the first time the rig gets hot.
  • E221 (bad hook) is the value itself, <EVENT>:<PATH> with an event that is one.
--background · --priority

--background · --priority #

--backgroundno console. The miner restarts itself with its own arguments, in a session of its own, three standard streams on /dev/null, prints the new pid, returns 0
--priority 0 to 5sets the whole process's scheduling priority
--cpu-prioritymoves the worker threads alone

The calling shell is free; a closing terminal takes neither process.

Give --log-file with it, or the log goes nowhere and only the API can read the rig.

Above 2 needs a privilege on Linux; refused by the OS: E613, and the miner keeps normal priority.

history

Read mining history #

Each rig stores its own history. Read it from the command line or through the API.

Details and behavior

Each rig keeps its own history, in its own state directory: no server, no database, nothing to set up.

It answers offline; a dashboard reads the same data over the API.

The last 24 hours are kept in memory and written to <state dir>/history.bin once a minute: a restart or a kill -9 does not lose them.

On disk the same samples are rolled up as each window closes.

stepkept forwhere it comes from
10 s24 hOne sample every 10 s, about 8 600 points, answered from memory without a byte read.
1 min7 dOne a minute, rolled up as each minute closes.
5 min30 dOne every five minutes, for the month.
1 h90 dOne an hour, out to --history-retention days, 90 by default.

The step asked for picks the layer: the last hour at 10 s from memory, last month at an hour from the coarse tier.

--history-max-size32 MB by default, a hard bound; the file is laid out to it from the first byte
--history offkeeps nothing, writes nothing

The bound wins over the retention: a rig with many cards keeps fewer days, not a bigger file.

Ninety days of an eight-card rig: about 7 MB.

A sample holds:

the riglocal and effective hashrate, shares accepted, rejected and invalid, rig power, clock drift, active pool, rig state
each cardhashrate, temperature, fan, power and clock

Folded together:

  • rates, temperatures and percentages are averaged
  • share counts added
  • pool and state the newest of the group

Every answer says which, per metric, in its aggregate field.

fearminer history #

fearminer history reads the file directly: no miner need be running, nothing is asked of the network.

$ fearminer history --from -24h --step 5m
$ fearminer history --from 2026-09-15 --to 2026-09-16 --step 1h --metric temp_c --device 0
$ fearminer history --from -7d --step 1h --format json | jq .series[0]
time_ms,time,hashrate_hs,hashrate_effective_hs,shares_accepted,temp_c_0
1789776000000,2026-09-19T00:00:00Z,611900000,598200000,37,64
1789776300000,2026-09-19T00:05:00Z,612400000,601100000,41,65
--from, --tonow, -24h, -7d, -90m, -3600s, a unix timestamp in seconds or milliseconds, an ISO 8601 UTC stamp (2026-09-20T10:00:00Z; a bare date is midnight). Default: a day ago, and now
--step10s, 1m, 5m, 1h, 1d, bare seconds. Default: the finest layer reaching back to --from. A finer step is raised to the layer's own, not refused, and the answer names the step used
--metric, --devicenarrow the output
--format csvthe default: a header row, one row per point, the time in ISO 8601 beside the milliseconds, an empty cell where nothing was sampled
--format jsonthe object the API serves

No history: E223, exit 2.

GET /api/v1/history

GET /api/v1/history #

The same data on the API port, query in the URL: the token from another machine, as everywhere under /api/v1.

$ curl -s 'http://127.0.0.1:4300/api/v1/history?from=-24h&step=5m&metric=hashrate_hs'
{"api_version": 1, "from_ms": 1789689600000, "to_ms": 1789776000000, "step_s": 300, "layer": "minute", "device": null,
 "clock": {"drift_ms": 12, "gaps": 0, "samples": 288},
 "t_ms": [1789689600000, 1789689900000, ...],
 "series": [{"metric": "hashrate_hs", "unit": "H/s", "aggregate": "avg", "values": [611900000, 612400000, null, ...]}]}
layerthe resolution that answered (ten_second, minute, five_minute, hour)
step_sthe buckets' step
400a bound, a step, a metric or a device that is not one, or a range over 20 000 points (E202)
409a run started with --history off (E223)

An unsampled bucket is null, not a zero.

Every sample carries the rig's monotonic clock and its wall clock; the interval between two is the larger of the two deltas.

NTP stepping the clock back never makes an interval negative; a machine suspended for two hours shows that gap.

Wall-clock drift: clock.drift_ms, and a metric of its own, clock_drift_ms.

history.bin

history.bin #

A 64-byte header, then one fixed-size ring per tier. The header holds:

  • FEARHIST, the magic
  • the format version
  • the sample schema version
  • the record size
  • the field counts
  • the device slots
  • each tier's capacity and step
  • a CRC-32

A record: two clocks, span, f32 values, a CRC-32.

A minute's records go out in one write per tier, at the tier's own place in the file; nothing else moves.

The file never grows and is never rewritten: the oldest sample is written over, one slot at a time.

a record torn by a power cutfails its CRC: not there
a file cut shortread for what it holds
a file that is not oursreplaced
a file that cannot be writtenE222, said once, mining untouched

None of this stops the miner starting.

A reader of another build or language stays compatible by:

  • checking the magic
  • reading field counts and record size from the header rather than compiling them in
  • taking the smaller of what it knows and what the file says
  • stepping over the rest by the record size

Fields are appended, never reordered, renamed or removed.

Understand and troubleshoot

terminal panel and log

Read the terminal panel and logs #

The terminal panel shows mining activity on the rig. Use the plain log when running without an interactive terminal.

first share accepted after 12.3 s
hashrate 588.5 MH/s

Example output. A hashrate and an accepted share confirm that mining has started and the pool accepted your work.

Terminal panel readings and keys

The terminal panel is the full-screen panel: hashrate, sparkline, share ticker, one row per card, the log.

lthe log alone
qquit
phold the whole rig and let it go again
1 to 9one card each (Control a running miner)

--no-tui prints the same records as a plain scrolling log, for a service or a mining OS.

--log-file keeps them in a file, in either mode.

local vs effective

the big figurethe local hashrate, what the cards compute
effthe effective hashrate, what the pool credits: the difficulty of the shares accepted in the last hour over that time, and its percentage of the local average over the same hour

They differ by stale shares, latency, the luck of the window and the fee rounds.

Under ten accepted shares in the hour, eff reads -, and the panel shows the estimate from the first share, dimmed, with its margin: ~118.2 T ±41 %.

shares per card

Each row shows acc/rej, the pool's verdicts on that card's shares, the stale ones in parentheses, plus the invalid count once the CPU re-check refuses a solution before submit (Check correctness and measure speed).

  • A stale is a share refused because its job was gone: latency, not the card.
  • A hardware fault shows as rejects that are not stale, or a growing invalid count.
  • Five non-stale rejects in a row hold the card Degraded (E316); five raise gpu_unstable.

kH/W

Efficiency, in the header for the rig and on each row: the session's hashes over the joules of board power the driver reports (NVML on NVIDIA), sampled twice a second.

Board power, not wall power: the supply's losses and the rest of the machine are out.

- on an engine that reports none (Vulkan, CPU).

The first minute

The first minute #

Before it connects, the miner prints where the hash goes and what it runs on: the plain log (--no-tui) shows the lines below, the terminal panel the same in its header and device rows.

fearminer 1.15.2 (a1b2c3d4e, 2026-09-22)
wallet   qzjd5MS1GSCpXLYp8DjZASifnkgtUpx5WwhmEzW3ppHdDe3uq (checksum ok)
worker   rig1
pool     stratum+ssl://pool.example.com:3335 (primary)
pool     stratum+tcp://backup.example.com:3333 (backup 2/2)
custody  pool (the pool pays the wallet)
algo     quantus
fee      2.00% of the mining time to the fee pool
build    1.15.2 (a1b2c3d4e, 2026-09-22)  sha256 3a3524b62caa8307
egress   stratum+ssl://pool.example.com:3335 · fee pool (one-minute rounds) · cfg.fearminer.com (terms, every 20 min) · telemetry.fearminer.com (telemetry every 15 min: event, install id, format, version, system, mining, hardware, hashrate bucket, features, uptime bucket, errors, pool host; fearminer telemetry show, fearminer.com/telemetry) · download.fearminer.com (engines, hourly)
driver   NVIDIA 570.86, libcuda.so.1 and libnvidia-ml.so.1 present
gpu #0   NVIDIA GeForce RTX 4070 Ti [0000:01:00.0]: compute 8.9, 11470 MB free of 12282
ram      64.0 GB
host     bare metal, kernel lockdown none, Secure Boot off
network  dns system · ip any
dns      pool.example.com → 203.0.113.10 (system resolver)
cpu      off on 32 threads, 1 GPU (-t N turns it on)
connected to stratum+ssl://pool.example.com:3335 (203.0.113.10:3335)
fee      window: 2.00 % of the time, first round in about 49 min
job 9dd830e6 diff 18.25G
first share accepted after 12.3 s
fee round started (1 min)
fee round ended: 2 share(s)
wallet
The address as checked against the chain (checksum ok), or UNCHECKED with --ignore-wallet-check. The worker is appended to it: you see what the pool sees.
pool
The pools as given with -o, the first primary, the others its backups in order. A wallet without a pool is refused before this line (E224).
custody · fee
custody: who pays the wallet (the pool). fee: the rate for this algorithm, mined in one-minute rounds on a separate connection, 2 % on Quantus, 0.85 % on RandomX, 1 % on Pearl, 2 % on TensorCash (mined by its engine on the same pool), none when the signed terms name no fee pool for it.
build · egress
build: the version and the first sixteen hex digits of the running binary's SHA-256. egress: every host the miner will talk to, and there is no other; telemetry.fearminer.com comes with its cadence, the groups of fields it sends and where to see them (with --no-telemetry its place reads no telemetry (--no-telemetry)).
driver · gpu · ram · host · network · dns · cpu
The preflight covers: the NVIDIA driver and its libraries; each card's compute capability and free memory against the algorithm's needs; the system memory; the host (bare metal or a VM, kernel lockdown, Secure Boot). Then how the pools are reached (proxy or DNS mode, address families, trust on first use), what each pool name resolves to and who answered. A card failing a check is Excluded with its code; the others mine. cpu: the CPU threads mining beside them, off on a rig with a GPU unless -t N, one per physical core on RandomX. A count past what the machine can spare (every thread but two, and one per card) is capped to it, and the line says so.
fee window · fee round
Once the engines are up, fee window gives the rate as a share of the time and when the first round is due. Each round logs fee round started (1 min) and fee round ended: N share(s). No line names the fee pool. An algorithm with no fee pool in the terms says so once and mines free.
first share
Before the first share every engine answers its known-answer test (Check correctness and measure speed); a start on the same binary, driver and cards skips it and says so. The first start also measures a few launch geometries on your card and caches the best (--retune measures again). Then the first job, then the first accepted share, said once with its delay, /stats carrying it as time_to_first_share_s. At a share a minute, the effective hashrate means something after ten minutes.

The terminal panel: the rolling hashrate, the sparkline with min, average and max, the share ticker, one row per card (state, temperature, fan, power, acc/rej, time since its last share), and the log. Keys:

l log onlyq quit--no-tui plain text--list-devices your GPUs and their indices--benchmark hashrate without a pool--self-test the engines' known answers
The plain log

The plain log #

--no-tui prints one line per record: accepted (✔) and rejected (✘) shares with the card, the difficulty and the round trip, new jobs, connections, verdicts with their code.

Once a minute a line carries three hashrates, each named for its window, then the effective one:

  • the instant rate
  • the ten-minute average
  • the session average: every hash since start over the uptime
  • what the pool credits, with its share of the local figure

The line comes whatever the rate, on the process's clock: at zero it names the paused card, as below.

--no-color drops the colour, -v adds the debug records.

19:12:14 ✔ 5/6 · GPU0 · 18.25G · 24 ms
19:12:21 hashrate 588.5 MH/s (10m 587.9, session 586.2, eff 580.2 / 98 %)
19:13:21 hashrate 0.0 H/s (10m -, session -, eff -) - GPU0 Paused (mem 106 °C) - shares 3/3 - diff 1.60M
The log file and its rotation

The log file and its rotation #

--log-file PATH writes every record the miner logs, panel mode or plain, one line each: 2026-09-20T19:33:49.788Z INFO message (UTC, milliseconds, no colour), the pool password replaced by ***.

Appended to, never truncated. Rotated by size into PATH.1 ... PATH.N.

--log-max-sizethe rotation size, 10 MB by default
--log-keepthe files kept, 5 by default; --log-keep 0 starts the file over
--log-level-filethe file's own level, debug with -v and info otherwise, so a debug file can run under a quiet console

A rotation that fails is reported on the console and the miner keeps writing.

$ fearminer -o stratum+ssl://POOL:PORT -u YOUR_WALLET --log-file fearminer.log --log-level-file debug --log-max-size 10 --log-keep 5
2026-09-20T19:33:49.788Z INFO  connected to stratum+ssl://pool.example.com:3335 (203.0.113.10:3335)

errors and exit codes

Understand an error #

Find the code from your log, or run fearminer explain CODE for its cause and suggested fix.

Details and behavior

Every fault line carries a code and a message, nothing else.

fearminer explain <CODE> prints the cause, the impact and the fix, offline.

E1xxnetwork
E2xxconfiguration
E3xxhardware
E4xxwallet
E5xxkernels and engines
E6xxprivileges and performance prerequisites (the MSR tweaks, the huge pages, the helper)
E7xxoverclocking
E8xxservice and remote control

A shipped number is never reused.

$ fearminer explain E302
E302 device lost

  cause:   The driver reported the card gone in the middle of a search: an Xid error, a PCIe reset, a crash of the card, an overclock or a power supply that cannot hold it.
  impact:  The card's worker has exited. With the watchdog on, the miner exits with code 10 and the supervisor restarts it (the card comes back with the driver, the process does not get it back); with --no-watchdog the others mine on without it.
  action:  If it struck after a long stable run, lower the clock or the power limit and try again. If it struck at the first search, check the driver (nvidia-smi, dmesg for Xid) and the riser or slot.

Exit codes #

codemeaningsupervisor
0Stop requested (SIGTERM, Ctrl+C, q), clean.
1Unclassified error.restarts
2Invalid configuration or arguments, each refusal with its code (E2xx; E4xx for a wallet that does not decode).final
3Precondition missing: no device, an engine that cannot start, every device failing its self-test, a port taken, or started as root without --allow-root.final
4Another instance is running (--allow-multiple to run several).final
10Device crash or hang.restarts
11Watchdog verdict: zero, ghost or low hashrate, a share famine, no accepted share, or a card past --temp-shutdown.restarts
12The supervisor gave up after --max-restarts in --restart-window.final
13The child died by a signal it did not expect.restarts
14A restart command was carried out: the supervisor starts the mining process again, not counted against --max-restarts.restarts
  • The supervisor exits with the child's code when it does not restart it (0, 2, 3, 4).
  • 12 when it gave up.
  • 0 after a requested stop, killed child or not.

Launchers stop on 2, 3, 4, 12 and restart on the rest; a systemd unit uses RestartPreventExitStatus=2 3 4 12.

fearminer --help prints this table.

Error codes #

A device fault (E302 to E305, E313 to E319, E506 to E508) dates itself: at the first search, the miner or the driver; after a long stable run, the overclock.

fearminer explain lists every code; fearminer explain E302, e302 or 302 prints one.

E1xx · network
E101pool unreachable
E102TLS handshake failed
E103TLS certificate pin mismatch
E104login refused
E105no job from the pool
E106no pool answers
E107pool address does not resolve
E108connection lost
E109unreadable message from the pool
E110pool accepts no share
E111fee terms not fetched
E113pool answers no submit
E114pool refuses every share
E115proxy connection failed
E116DNS over HTTPS failed
E117name not found by the DoH resolver
E118TLS certificate changed since first use
E119TLS trust file unusable
E120TLS certificate not verified
E125share unanswered
E126pool redirect refused
E127nonce space exhausted
E128job replayed by the pool
E129pool latency over the limit
E135command channel closed
E136command failed
E137sentinel file unusable
E138configuration file not watched
E139hook script failed
E2xx · configuration
E201bad pool URL
E202bad option value
E203wrong number of per-pool values
E204wallet required
E205pool required
E206bad device selection
E207stats port unusable
E208log file unusable
E209state directory unusable
E210another instance is running
E211configuration file unusable
E212unknown configuration key
E213bad value in the configuration file
E214this miner cannot run that chain
E215the wallet matches several chains
E216unknown command
E217command not allowed
E218bad command target
E219the change needs a restart
E220reload rejected
E221bad hook
E222history file unusable
E223no history kept
E224wallet without a pool
E3xx · hardware
E301no device to mine on
E302device lost
E303device hang
E304zero hashrate
E305ghost hashrate
E306thermal pause
E307NVIDIA driver missing
E308NVIDIA driver too old
E309GPU engine cannot start
E310not enough free GPU memory
E311NVIDIA driver mismatch
E312every worker has exited
E313hashrate low
E314hashrate suspect
E315share famine
E316shares refused in a row
E317device back to mining
E318device quarantined
E319thermal shutdown
E320engine process restarted
E321engine index refused
E322engine index not fetched
E323engine download refused
E324no engine to run
E325engine not supported by this miner
E326engine updated
E327engine update rolled back
E328fee engine started per round
E329machine below the algorithm's requirements
E4xx · wallet
E401wallet does not decode for the chain
E402wallet check skipped
E5xx · kernel and engine
E501kernel load failed
E502compute capability unsupported
E503tuning failed
E504degraded kernel
E505share could not be encoded
E506kernel gives wrong results
E507invalid share caught before submit
E508engine refused its own candidates
E6xx · privileges and performance
E601helper not available
E602helper call failed
E603MSR tweaks skipped in a virtual machine
E604MSR tweaks skipped under kernel lockdown
E605MSR tweaks skipped: msr module missing
E606MSR tweaks skipped: writes disabled
E607MSR tweaks skipped: no preset for this CPU
E608MSR values not restored
E609huge pages short
E6101 GB pages unavailable
E611MSR tweaks unavailable on this platform
E612Lock pages in memory right missing
E613priority not applied
E614MSR values restored
E615huge pages not released
E616run named to the helper by its pid alone
E7xx · overclocking
E701memory clock is not a step of the card
E702overclock value out of the card's range
E703overclock needs privileges
E704overclock not supported
E705overclock refused by the driver
E706overclock restore file unusable
E707overclock script failed
E708overclock restored
E8xx · service and remote
E801no service manager
E802the mining OS runs the miner
E803service manager step failed
E804service not installed
E805service privilege
E806service starts with your session
E807option makes no service
E808a service is already there
E809remote command refused
E810enrolment refused
E811relay refused the rig
E812relay unreachable
E813update refused
E814updater not installed
E815release not downloaded
E816release failed its checks
E817new binary failed its checks
E818update rolled back
E819updated
E820benchmark refused

The names are the miner's own, as explain prints them, untranslated so log line and table match word for word.

security and trust

Privacy, downloads and local files #

Check what the miner connects to, what it stores and how to verify a download.

Details and behavior

FearMiner checks the wallet before the first packet, says at every start where the hash goes, warns when it changed, refuses privileges it does not need, and lists every host it talks to.

The wallet check and the wallet-changed warning

The wallet check and the wallet-changed warning #

Checked before the miner connects anywhere.

Quantusan SS58 address of the Quantus network, prefix 189, 32-byte account, blake2b checksum verified
RandomXa Monero mainnet address, standard, subaddress or integrated, keccak checksum verified. Refused by name: testnet and stagenet
TensorCasha TensorCash tc1... segwit (bech32) address or a base58check address of the chain, checksum verified by its engine
  • The wallet is the part of -u before the .worker.
  • A +diff suffix and a solo: prefix skip the check and go as typed.
  • A non-decoding address, or one of another network: refused with the cause, exit code 2, no connection, no guessing between chains.
  • --ignore-wallet-check sends it as typed, warns at start (E402), marks the banner UNCHECKED.

Also remembered per pool host: a hash of the host and the wallet in wallets.json in the state directory, never in clear, written after the session's first accepted share.

If the file knows another wallet for that host, the next start:

  • prints WARN wallet changed since the last session on <host> (was <date>)
  • shows wallet changed in the header
  • sets wallet_changed on /stats and the API
  • sends the critical alert wallet_changed
  • keeps mining

The warning returns at every start until the new wallet earns a share.

Root and passwords

Root and passwords #

  • On Linux and macOS a miner started as root exits 3.
  • --allow-root runs it anyway; the HiveOS package passes it.
  • A systemd unit runs the miner under a dedicated user.
  • The supervisor checks once, before spawning the mining process; Windows has no check.
  • A real pool password in -p or FEARMINER_PASS (anything but the conventional x) shows in the process list, and the miner says so once at start.
  • --pass-file reads it from a file, one line per pool; the mining process sees the path, not the password.
  • A world-readable file is warned about.
  • In the log file and on /api/v1/config the password is ***.

The MSR tweaks and the huge-page reservation RandomX needs root for go through fearminer-helper (Algorithms, fees and requirements).

  • a separate audited binary, no network, no configuration
  • reached through sudo -n before the first connection and never after
  • a miner run as root does it in-process, no helper

Setting a clock, a power limit or a fan needs the miner itself as root (--allow-root), or the overclock stays outside.

The relay cannot read encrypted cockpit messages or sign your commands. It can see connection IP addresses, timing and traffic size, rig identifiers, public keys, enrollment records, software versions and last contact.

If the relay is unavailable, mining continues while the rig reconnects. Cached or bundled verified engines and fee terms can keep mining independent of FearMiner’s servers. Mining still needs a connection to your pool.

What the miner talks to #

  • Your pool, over stratum+tcp or stratum+ssl: every pool of the list when there are backups; through the SOCKS5 proxy of --proxy, which then resolves the names.
  • The fee pool, during the one-minute fee rounds, on its own connection, through the same proxy.
  • cfg.fearminer.com, for the signed fee terms, at start and every 20 minutes, direct, not through the proxy, unless HTTPS_PROXY is set. Unreachable, it delays the start by five seconds at most; the miner mines with the last verified terms (terms.bin) or the built-in ones.
  • telemetry.fearminer.com, the anonymous telemetry: a report once the run is under way, a heartbeat every 15 minutes (--telemetry-interval) and a report at a clean stop, through the same proxy and resolver as the pools. 22 fields in 12 groups (event, install, format, version, system, mining, hardware, hashrate, features, uptime, errors, pool), never a wallet, a worker name, a machine name or an address: each field, and what is done with it, on What FearMiner collects. --no-telemetry (FEARMINER_NO_TELEMETRY=1) turns it all off and costs no feature; the terms are still fetched.
  • Only if you ask for them, directly: the notification and heartbeat endpoints (api.telegram.org, discord.com, your own URLs) and the DNS-over-HTTPS resolver of --dns doh.
  • relay.fearminer.com, once the rig is enrolled in a cockpit and not before: one outgoing connection (port 443) carrying sealed messages only your fleet reads, through the same proxy and resolver as the pools. --remote-relay puts a relay of your own first.
  • download.fearminer.com, the signed engine index at start and every hour, an engine when one is missing or newer, and for a service the cockpit can update, latest.json about every hour and a release only when an update is asked or automatic (Algorithms, fees and requirements, Engines).

The egress line at start lists all of it. The stats endpoint listens on 127.0.0.1 unless --api-bind says otherwise.

One dialer for every pool connection: --proxy, --dns and --ip apply to the session, the probes and the fee rounds alike.

While a proxy is configured the pool is never contacted directly (Connect to your pool).

Verify a download

Verify a download #

Every release carries SHA256SUMS over its files and SHA256SUMS.minisig, its minisign signature by the release key.

fearminer verify has the key compiled in and checks, one line each:

  • the signature offline (Ed25519)
  • the SHA-256 of every file the sums name present in the same directory
okthe file matches its sum
MISSINGthe sums name it, it is not in the directory. Expected when you did not download every asset, and not a failure
MISMATCHthe file is there, its sum differs. This is the failure: delete it and fetch it again

Exit 0 only when the signature is good and every present file matches.

Anything else prints verification FAILED; do not run this download.

Given an archive, it looks for SHA256SUMS beside it.

minisign and sha256sum do the same by hand.

The key changes only with a release that announces it.

$ fearminer verify SHA256SUMS
$ fearminer verify fearminer-linux-x86_64.tar.gz
$ minisign -Vm SHA256SUMS -P RWQR3owV+nRhfgNJeUBqcRK868S52NFG2BOrIzKpkQ5ey6lCEfM9+3Eg
$ sha256sum -c SHA256SUMS --ignore-missing
PS> .\fearminer.exe verify SHA256SUMS
PS> Get-FileHash .\fearminer-windows-x86_64.zip -Algorithm SHA256

The sums also cover sbom.cdx.json, the binary's CycloneDX bill of materials: every component inside, with its version, to check against the advisory databases.

The Linux and Windows binaries carry their dependency list in a section cargo audit bin reads.

Every archive carries THIRD-PARTY-NOTICES.txt, the licences of the open-source components inside.

Why the binaries are unsigned

Why the binaries are unsigned #

The binaries are not code-signed yet, so Windows and macOS stop them at the first run; antivirus engines file any miner under HackTool or CoinMiner. The first says the publisher is unknown, the second says the program mines.

Check the download first. Every release carries SHA256SUMS over its files and SHA256SUMS.minisig, its minisign signature by the release key. fearminer verify has that key compiled in: the signature offline, then the SHA-256 of every file the sums name in the same directory; exit 0 only when everything matches. minisign checks the same signature with the published key. sha256sum, or Get-FileHash in PowerShell, compares a hash by hand against the sums on the release page.

A good run prints ok for every file you downloaded, and MISSING for the assets you did not: that still exits 0. Only a bad signature or a MISMATCH is verification FAILED; do not run this download: delete it, fetch it again. After that, what follows is the operating system talking about a missing signature, not about the file.

Signing is planned, with no date: an Authenticode certificate and an Apple developer account are a recurring bill. Until then the signature that counts is the one on SHA256SUMS, which you can check yourself, offline.

What it writes on disk

What it writes on disk #

Each archive unpacks into a folder named like the archive.

fearminerthe miner (fearminer.exe on Windows)
start_<algo>one launcher per algorithm: the same command with the wallet in a variable, in a restart loop
readme.txtthe same reference as this page, offline
openapi.jsonthe API description
engines/the signed engine index and this platform's engines, so a first start mines without the network
fearminer-helperLinux only: the privileged helper RandomX uses (Algorithms, fees and requirements)
~/.config/fearminer/tuning.jsonThe GPU tuning cache (%USERPROFILE%\.config\fearminer on Windows, ~/Library/Caches/fearminer on macOS).
~/.cache/fearminer/The state directory (%USERPROFILE%\.cache\fearminer on Windows; FEARMINER_STATE_DIR moves it), holding the files below.
terms.bin · fearminer.lock · crashes.jsonThe last verified terms; the single-instance lock; the crash counters per card.
selftest.json · bench-<algo>.jsonThe self-test verdicts per engine (the binary, the driver, the cards it passed on); the last benchmark per algorithm, with its checksum.
tls-pins.json · oc-restore.jsonThe certificates remembered by --tls-tofu, keyed by host:port; what each card read as before an overclock touched it, keyed by UUID, until it is put back.
/run/fearminer-helper/msr.jsonWritten by the helper, root-owned, on Linux only: the original MSR values until msr restore or the next boot.
history.binThis rig's own history, one fixed-size ring per resolution, bounded by --history-max-size (32 MB by default) and never grown past it (Read mining history).
stop · pause · resumeThe sentinel files an orchestrator with no token creates to pause, resume or stop the rig: the miner acts within a second and deletes the file (Control a running miner).
wallets.json · watchdog.log · api_tokenThe wallet fingerprints per pool host (a hash, never the wallet); the supervisor's log, 256 KB at most; the API token, readable by you alone.
telemetry-idThe telemetry's install id, 32 random hex digits, and the version of its last run, readable by your account only; never written with --no-telemetry; fearminer telemetry rotate-id replaces it.
engines/The engine cache: the signed engine index and the two latest versions of each algorithm's engine, each checked against the index before every start.
remote-commands.log · remote-sheet.json · benchmark-run.json · benchmark-last.json · update-health.jsonThe commands the fleet sent, carried out or refused, and the mining sheet it applied; a benchmark the cockpit asked for, then its result; what an update waits for once the new miner is up.
fearminer.tomlRead, never written, beside the binary or in the configuration directory. The log file only where --log-file names it.
What the relay sees

What the relay sees #

the linkone outgoing connection from the rig, port 443, no port to open, through the same proxy and resolver as the pools; made once the rig is enrolled, not before
statusevery minute, every 10 s while a cockpit is open, sealed so only your fleet reads it
the relayroutes sealed messages; it cannot read them, cannot enrol a rig, cannot sign a command
commandssigned by your fleet, for one rig, valid for a minute and once: pause, resume, toggle, retune, restart, stop, the mining sheet, update to a newer release (a Linux service with its updater) and benchmark. Each one, carried out or refused, goes to remote-commands.log on the rig
relay downthe mining goes on; the link retries on its own
your own relay--remote-relay wss://HOST, tried before wss://relay.fearminer.com

FAQ

Troubleshoot a rig #

Start with the symptom you see. Each answer gives a first check and links to the relevant reference.

Details and behavior

The option or the command that answers. When a log line carries a code, fearminer explain <CODE> answers first.

The hashrate is lower than expected.

The hashrate is lower than expected. #

Check the preflight lines: E308 (a driver older than the kernels need) or E307 (a missing libcuda) forces Vulkan, about a third of the rate. The row must read Mining, not Paused (temp), Degraded (reason on the row) or Excluded. A low eff with a normal local rate is the pool: stale shares, latency. --retune remeasures the launch geometry after a driver change. --benchmark --duration 30 measures without a pool; --bench-seed 1 adds a checksum to compare two runs.

Terminal readings

A GPU shows Paused (temp 91 °C).

A GPU shows Paused (temp 91 °C). #

The thermal cut-off. The sensor is on the row: temp for the core, mem for the memory. The core resumes at --temp-resume (75 °C), the memory at the limit minus --temp-hysteresis (10 °C). Pausing needs --temp-hold (15 s) over the limit; a spike does nothing. Improve the airflow or lower the power limit with the vendor's tool. --temp-limit 85 pauses earlier, --temp-limit 0 disables the core cut-off, --temp-limit 85,80,_ sets card 1 apart. temp_critical after ten minutes paused; --temp-shutdown 95 stops the miner if a paused card keeps heating.

Temperature limits

Shares are rejected.

Shares are rejected. #

A stale (in parentheses) arrived after its job was gone: latency to the pool, harmless under a few percent; a nearer pool or a backup helps. A non-stale reject on one card is that card: lower its overclock. Five in a row hold it Degraded until one is accepted (E316) and raise gpu_unstable. An invalid is a solution the CPU refused before sending, the same card fault caught earlier (E507). Rejects on every card at once are the pool or the login: fifteen in a row reconnect the session (E114); fearminer explain E110.

Share verification

My card says Degraded or Quarantined. What now?

My card says Degraded or Quarantined. What now? #

Degraded is a suspicion, the reason on the row, and the card keeps mining: a ten-minute average under --hashrate-min (E313, restarted after --hashrate-grace if it stays there), rejects in a row (E316, cleared by the next accepted share), a share famine (E315, its search restarted). At the first search, the miner or the driver; after a long stable run, the overclock: lower it. Quarantined (E318): the card took the miner down --device-quarantine times (3) in --restart-window (30 min), sits this run out, the others mine. Fix the cause (overclock, riser, driver) and restart; --reset-crashes clears the counters, --device-quarantine 0 turns the rule off.

Device states

The self-test failed on a card.

The self-test failed on a card. #

A wrong answer to a known input (E506): the card is left out of the run, Excluded (E506) on its row, the others mine. Run fearminer --self-test at stock clocks: still failing means a hardware or driver fault (dmesg for Xid, the riser, the slot, a driver reinstall); passing at stock and failing overclocked means the overclock. A warning on the verdict line (E508) is different: the engine refused some of its own candidates, the shares are safe, the kernel loses a few, the card mines on.

Run a self-test

The wallet is refused (E401, E214, E215).

The wallet is refused (E401, E214, E215). #

E401: the address does not decode for the chain, or belongs to another network (Monero testnet, a Quantus address with a wrong character): copy it again from the wallet. E214: this miner cannot run that chain. E215: the address fits two chains, name one with -a. --ignore-wallet-check sends it anyway, the banner says UNCHECKED, and the pool rejects the shares or pays someone else.

Wallet checks

The pool is unreachable (E101, E107, E106).

The pool is unreachable (E101, E107, E106). #

E107 is the name: check the host and the DNS. Printed once per outage; retries go to the debug log until it resolves. E101 is the port or a firewall: try the plain TCP port with stratum+tcp://, the TLS port with stratum+ssl://. E106 is every pool of the list down: the miner keeps trying them in turn and never exits. Add a backup as a second -o.

Pool connections

How do I run it at boot?

How do I run it at boot? #

fearminer service install with the options of a run (fearminer service install -o stratum+ssl://POOL:PORT -u YOUR_WALLET -w rig1): a service of your account that starts with the machine and restarts after a crash, no password; systemd on Linux, launchd on macOS, a task at logon on Windows. --system, with sudo, installs the machine's instead. The one line of Set up your first rig does it for you. HiveOS: the flight sheet. The service.

Manage a service

How do I run several rigs?

How do I run several rigs? #

The cockpit (Manage rigs from the cockpit) shows them all on one screen and sets what each one mines. Without it: The same wallet everywhere, a different worker name per rig (-w rig1, rig2, ... or WALLET.rig1): the pool shows them apart and every alert names its rig. One fearminer.toml per rig with worker = "${HOSTNAME}" needs no edit. --api-bind 0.0.0.0:4300 on each plus fearminer token show once per rig give a dashboard the API; --heartbeat-url per rig tells you which one froze.

Manage your fleet

Where are the files?

Where are the files? #

State directory ~/.cache/fearminer (%USERPROFILE%\.cache\fearminer on Windows): terms.bin, fearminer.lock, crashes.json, wallets.json, selftest.json, bench-<algo>.json, watchdog.log, api_token, history.bin. Tuning cache ~/.config/fearminer/tuning.json (~/Library/Caches/fearminer on macOS). The configuration file is read beside the binary or in ~/.config/fearminer, %APPDATA%\fearminer, ~/Library/Application Support/fearminer; the log file only where --log-file names it. The fleet, the updates and the engine cache keep a few more files there (What it writes on disk).

Local files

How is the fee taken?

How is the fee taken? #

2 % on Quantus, 0.85 % on RandomX, 1 % on Pearl, 2 % on TensorCash, printed by --list-algorithms and in the terminal panel header. Mined in one-minute rounds on a separate connection to the fee pool, never on your session. At start: fee window: 2.00 % of the time, first round in about N min; each round logs fee round started (1 min) and fee round ended: N share(s); the alerts are devfee_start and devfee_stop; /api/v1/summary counts the seconds and shares of each side. The rate is a ceiling: the signed terms can lower it or turn it off per algorithm, never raise it. TensorCash has no rounds: its engine holds the pool session and mines the fee there itself, on FearMiner's account.

Algorithms and fees

The miner restarts on its own. Why?

The miner restarts on its own. Why? #

A watchdog verdict restarted the mining process. The console line supervisor: ... and watchdog.log carry the cause and its code (E302 lost, E303 hang, E304 zero hashrate, E305 ghost, E313 low hashrate, E315 share famine, E110 no accepted share on two pools, E319 thermal shutdown). fearminer explain <CODE> says what to do. The crash counter on the row names the card; a card blamed three times in thirty minutes sits the next run out (Quarantined). Five restarts in thirty minutes: it gives up with exit code 12, and --on-failure script:<path> runs your script.

Recovery rules

It refuses to run as root.

It refuses to run as root. #

By design (exit code 3): the miner needs no privileges. Run it under your own account or a dedicated one; a systemd unit sets User=. --allow-root runs it anyway, as the HiveOS package does. What RandomX needs root for on Linux, the MSR tweaks and the huge pages, goes through fearminer-helper (Algorithms, fees and requirements), a small separate binary reached through sudo -n before the first connection. Only the overclock needs the miner itself as root.

Privileges

My GPU is not NVIDIA or Apple.

My GPU is not NVIDIA or Apple. #

It runs on the Vulkan engine, at a fraction of a native kernel's rate; the preflight says so. Vulkan and Metal take the first N cards, so -d accepts only 0..N-1. A CPU-only algorithm (RandomX) needs no GPU.

Hardware requirements

Windows says unknown publisher; the antivirus flags it.

Windows says unknown publisher; the antivirus flags it. #

The binary is unsigned: SmartScreen shows More info, then Run anyway. Some antivirus engines flag every GPU miner; whitelist fearminer.exe. Instead of a signature: fearminer verify SHA256SUMS (the release key is built in), and the build line at start, the SHA-256 of the running binary, against SHA256SUMS.

Platform warnings

RandomX is slow.

RandomX is slow. #

Read the start block. E609 huge pages short costs 20 to 30 %; an MSR line with a code (E601 to E607) up to 30 % on an Intel, 6 % on a Zen; light mode (a machine that cannot hold the 2 GiB dataset) much more. The performance line gives the share of the ideal configuration reached. fearminer-helper (Algorithms, fees and requirements) does both at start. Without it: Linux, vm.nr_hugepages with the number the E609 line gives, right after boot; Windows, Lock pages in memory. Keep 2 GiB free. Leave the thread count at one per physical core; -t takes a count, a percentage or a delta.

Huge pages

Can the miner go through Tor or a proxy?

Can the miner go through Tor or a proxy? #

Yes. --proxy socks5://127.0.0.1:9050 sends every pool connection (session, probes, fee rounds) through the SOCKS5 proxy, which resolves the pool names: no pool DNS query leaves the machine, a .onion pool works, and the pool is never tried directly while a proxy is set. The engines' downloads, the cockpit's relay link and the telemetry take the same proxy; the terms fetch and the notifications go direct. --dns doh hides the names from the local resolver without a proxy; --tls-tofu pins a node's self-signed certificate on first contact. Connect to your pool.

Proxy and DNS

Does the miner overclock my cards?

Does the miner overclock my cards? #

No. Without an OC option no clock, power limit or fan register is touched, and --no-oc says so at start. --cclock, --lock-cclock, --mclock, --lock-mclock, --pl and --fan set a card through NVML, read it back, and restore its earlier reading at exit and after a crash. fearminer oc show prints what the cards read as; fearminer oc reset restores them after a run killed without cleanup. Setting them needs root (--allow-root); E703 otherwise, and mining goes on at the card's clocks. Choose and manage devices.

Overclocking

How do I feed a dashboard?

How do I feed a dashboard? #

The cockpit at app.fearminer.com (Manage rigs from the cockpit) needs none of this. For a dashboard of your own: curl http://127.0.0.1:4300/api/v1/summary on the rig needs nothing. From another machine: --api-bind 0.0.0.0:4300 at start, then Authorization: Bearer <token>, from fearminer token show. /stats and /hive-stats serve the flat HiveOS object without a token. /openapi.json describes every field. GET /api/v1/history serves what the rig recorded itself, at the step you ask for: no time-series database needed (Read mining history). The three writes, a set on a card, a command on the running miner, a reload of the configuration, need the token from anywhere and stay inside what --unrestricted-api allows (Control a running miner).

API access

Example systemd unit
# /etc/systemd/system/fearminer.service
[Unit]
Description=FearMiner
After=network-online.target

[Service]
User=fearminer
StateDirectory=fearminer
WorkingDirectory=/var/lib/fearminer
Environment=HOME=/var/lib/fearminer FEARMINER_NO_TUI=1
EnvironmentFile=/etc/default/fearminer
ExecStart=/usr/local/bin/fearminer
Restart=always
RestartSec=2s
RestartPreventExitStatus=2 3 4 12
TimeoutStopSec=30s
KillSignal=SIGINT

[Install]
WantedBy=multi-user.target

The unit leaves the restarting to the miner's supervisor and lets systemd restart everything only once it has given up; the final codes are left alone. FEARMINER_NO_SUPERVISOR=1 in the environment file gives systemd all the restarting.

Full reference

options

Find an option or command #

Search by name, environment variable or task. Each entry shows its value, default and effect.

Details and behavior

Option, value, default, environment variable, what it does.

Every option can also be set from the environment as FEARMINER_<OPTION> and in the configuration file under its long name with underscores (--temp-limit is temp_limit; --1gb-pages is huge_pages_1g).

The command line wins over both.

Usage

Usage #

fearminer [OPTIONS] [WALLET] [COMMAND]
optionvaluedefaultFEARMINER_*what it does
WALLETThe wallet: the same as -u, and like it given with a pool (-o); without -a the chain is read off the address.
-h, --helpPrint the help. -h prints a summary, --help everything: the options, the examples, the exit codes.
-V, --versionPrint the version, commit and build date.
Pool

Pool #

optionvaluedefaultFEARMINER_*what it does
-o, --url<URL>FEARMINER_URLPool URL: stratum+tcp://host:port, stratum+ssl://host:port or host:port (plain TCP unless --tls). The host is resolved on every connection. Repeat or comma separate for backup pools: the first is primary, the others tried in order when it fails; back to the primary once it answers again. wss://host[:port]/path for an algorithm whose engine holds its pool session (TensorCash). Alias --pool.
-u, --user<WALLET[.WORKER]>FEARMINER_USERWallet address, worker name optional as WALLET.WORKER. All pools; one per pool (repeat or comma separate, in pool order) when a backup needs another. Alias --wallet.
-w, --worker<NAME>FEARMINER_WORKERWorker name, appended to --user as WALLET.WORKER when it has none.
-p, --pass<PASS>xFEARMINER_PASSPool password. Pools ignore it; x by convention. All pools, or one per pool like --user. A real password here shows in the process list; use --pass-file.
--pass-file<PATH>FEARMINER_PASS_FILEPool password(s) from this file instead of -p: one line for all pools, or one per pool in pool order. Wins over -p and FEARMINER_PASS. On Unix, warns when other users can read it.
--ignore-wallet-checkfalseFEARMINER_IGNORE_WALLET_CHECKSend the wallet without checking it is an address of the algorithm's chain; the banner then says UNCHECKED.
--tlsfalseFEARMINER_TLSTLS on a bare host:port (implied by a stratum+ssl:// URL).
--tls-fingerprint<SHA256>FEARMINER_TLS_FINGERPRINTPin the pool's TLS certificate by SHA-256 fingerprint (64 hex digits), for a self-signed certificate; otherwise it is checked against the public roots. All pools, or one per pool like --user (a dash, -, for a pool without one). Alias --tls-cert-sha256.
--tls-spki<sha256/BASE64>FEARMINER_TLS_SPKIPin the pool's TLS certificate by the SHA-256 of its public key (SPKI), as sha256/BASE64 (HPKP notation); it survives a certificate renewal that keeps the key. All pools, or one per pool like --user (a dash, -, for a pool without one). Wins over --tls-fingerprint for the same pool.
--pool-retries<N>3FEARMINER_POOL_RETRIESConnection attempts on a pool, on a network error, before the next pool is tried. A pool refusing the login is dropped at once. Every pool down: the miner cycles through them for ever, pausing up to 60 s between rounds.
--job-timeout<SECS>by chainFEARMINER_JOB_TIMEOUTSeconds without a new job, on an otherwise live connection, before the session counts as dead: the workers stop and the miner reconnects as after a lost connection. Per chain by default: 120 quantus, 300 randomx (one job a minute at most), 180 pearl, 300 tensorcash (its engine judges its pool). 0: guard off.
--submit-timeout<SECS>10FEARMINER_SUBMIT_TIMEOUTSeconds a submitted share waits for the pool's reply before it counts unanswered (E125). --max-no-submit-responses unanswered in a row reconnect the session.
--max-latency<MS>0FEARMINER_MAX_LATENCYLongest a pool may take to answer a submit, in milliseconds, as the median of the last twenty replies. Over it for two minutes: the session moves to a faster pool of the list, if any (E129). 0: off.
-a, --algo<ALGO>quantusFEARMINER_ALGOAlgorithm or coin to mine (--list-algorithms for names and aliases). Default: the chain read off the wallet; quantus without a wallet. Alias --coin.
--list-algorithmsList the algorithms the engine index lists (the cached or the release's copy), with their fee ceiling, and exit; with --json, one array of {name, coin, class, fee_bps, aliases, unit, hive, requirements, refused}.
--engine<ALGO=VERSION>FEARMINER_ENGINEHold an algorithm's engine at a version of the signed index, ALGO=VERSION (repeatable, or comma separated): that version runs, from the cache or downloaded, and the hourly update leaves the algorithm alone.
--engine-opt<NAME=VALUE>FEARMINER_ENGINE_OPTAn option of the algorithm's engine, NAME=VALUE (repeatable, or comma separated): --list-algorithms says which an algorithm has and the values each takes. One the algorithm does not have, or a value it does not take, is refused.
--tsc-precision<VALUE>FEARMINER_TSC_PRECISIONThe option an earlier miner had for one engine's precision: now --engine-opt precision=VALUE, which this still sets for an algorithm whose engine has it. Ignored by the others.
Configuration

Configuration #

optionvaluedefaultFEARMINER_*what it does
--config<PATH>FEARMINER_CONFIGConfiguration from this TOML file, one key per option. Default: fearminer.toml beside the binary, then the one in the configuration directory, if either exists. --config "" reads none.
--dry-runPrint the effective configuration and exit; nothing is contacted. Every key with value and origin (default, file, env, cli), password masked; then mode, algorithm, pools, cards left out; then the --check-config verdict. Exit 0 when the miner would start, 2 with the coded reason.
--check-configCheck the configuration without mining: options, device selection against the cards the driver lists, pool list, wallet against its chain. Exit 0 when the miner would start, 2 with the coded reason. Nothing is contacted.
Network

Network #

optionvaluedefaultFEARMINER_*what it does
--proxy<URL>FEARMINER_PROXYReach every pool through this SOCKS5 proxy (Tor: socks5://127.0.0.1:9050); credentials as socks5://user:pass@host:port. The proxy resolves the pool names: no DNS query for them leaves the machine, and a .onion pool works. A failed proxy is a failed connection: no direct fallback to the pool. socks5h:// means the same.
--dns<MODE>systemFEARMINER_DNSPool name resolution: system (the OS resolver), doh (DNS over HTTPS at --doh-url, the system resolver when the endpoint does not answer, never for a name it says does not exist), doh-strict (DNS over HTTPS only). DoH hides the names from the local resolver only: the TLS SNI stays visible. Moot with --proxy.
--doh-url<URL>https://cloudflare-dns.com/dns-queryFEARMINER_DOH_URLDNS-over-HTTPS resolver (RFC 8484) for --dns doh and doh-strict. Give its IP (https://1.1.1.1/dns-query) when the local DNS cannot resolve the resolver's own name.
--ip<any|4|6>anyFEARMINER_IPAddress family for reaching a pool: any (IPv6 first, IPv4 250 ms later, the first to connect wins), 4 or 6.
--ipv4-onlyfalseIPv4 only: the same as --ip 4.
--ipv6-onlyfalseIPv6 only: the same as --ip 6.
--tls-tofufalseFEARMINER_TLS_TOFUTrust a pool's TLS certificate on first use, for a node or a P2Pool on a self-signed certificate: the first handshake's fingerprint goes to tls-pins.json in the state directory; any other certificate from that pool is then refused. A pool with --tls-fingerprint or --tls-spki is checked against its pin instead.
--tls-insecurefalseFEARMINER_TLS_INSECUREAccept whatever TLS certificate a stratum+ssl:// pool without a pin presents: no chain, name or expiry check. For a TLS port forward or a proxy, where the name dialled is not the pool's. The session stays encrypted but the pool is no longer authenticated (E120 at every start). A pool with --tls-fingerprint or --tls-spki keeps its pin, and the fee rounds go the way the pools go. Refused with --tls-tofu, and when no stratum+ssl:// pool without a pin is left.
--tls-tofu-reset<HOST:PORT>Forget the certificate remembered for this pool (host:port, as the E118 line prints it) before connecting; the one presented now is trusted and remembered. Repeat for several pools.
--remote-relay<URL>FEARMINER_REMOTE_RELAYA relay of your own for the remote control, tried before the built-in one (wss://relay.fearminer.com): wss://HOST[:PORT], or ws:// for one on this machine or this network. Repeat it for several. Nothing is contacted until the rig is enrolled.
--remote-wallet-delay<MIN>0FEARMINER_REMOTE_WALLET_DELAYMinutes a new wallet from a cockpit's mining sheet waits before it applies, announced with both addresses; any cockpit or fearminer remote cancel drops it meanwhile. 0, the default, applies at once.
--no-auto-updatefalseFEARMINER_NO_AUTO_UPDATENo automatic update. A rig installed as a Linux service takes a new FearMiner by itself within two hours of first seeing it, with the same signature check and roll-back as the cockpit's Update button; with this, only the Update button or fearminer service update does. The cockpit can turn it on or off per rig or for the whole fleet.
--enroll<CODE>FEARMINER_ENROLLJoin the fleet of this code at start (fm1_..., from the cockpit's Add a rig): the same as fearminer enroll CODE, for a service, a HiveOS flight sheet or a provisioning script. Nothing happens once the rig is in that fleet.
Devices

Devices #

optionvaluedefaultFEARMINER_*what it does
-d, --devices<LIST>allFEARMINER_DEVICESGPUs to mine on, comma separated: an index (0), a PCI id (pci:0000:41:00.0, 41:00.0, or the bus alone, pci:41 in hex or bus:65 in decimal), a whole UUID (GPU-3f2a...), all as --list-devices prints them; a vendor (nvidia, amd, intel: all its cards); or an exclusion with a leading ! (!1, !pci:41:00.0, !GPU-3f2a..., !nvidia). Include and exclude lists do not mix. CPU threads come from -t. NVIDIA picks the named cards exactly; an item matching no card here is E206, exit 2, unless --device-missing first or last mines on the cards present. Vulkan and Metal take the first N cards, only 0..N-1. Excluding every card is allowed: the card shows Excluded, CPU threads mine; with no CPU thread, E301, exit 3.
--device-missing<POLICY>matchFEARMINER_DEVICE_MISSINGWhen -d names a card this machine does not have: match refuses the start (E206); first and last keep the configuration and mine on the cards present, per-card lists (--temp-limit 85,80) laid over them from the first position on, or from the last back.
--temp-limit<C[,C...]>90FEARMINER_TEMP_LIMITPause a GPU whose core holds at or over this temperature (Celsius) for --temp-hold seconds, until it cools to --temp-resume; 0: no core cut-off. All cards, or one per card in -d order (85,80,_,90: _ keeps the default, a shorter list leaves the rest at it).
--temp-resume<C[,C...]>75FEARMINER_TEMP_RESUMECore temperature at which a GPU paused by --temp-limit resumes; must be under --temp-limit. All cards, or one per card in -d order.
--temp-limit-mem<C>105FEARMINER_TEMP_LIMIT_MEMPause a GPU whose memory sensor holds at or over this temperature for --temp-hold seconds, until it cools by --temp-hysteresis; 0: no memory cut-off. A card lacking the sensor is not judged on it.
--temp-limit-hotspot<C>100FEARMINER_TEMP_LIMIT_HOTSPOTThe same for the hotspot sensor; 0: off. NVML gives no hotspot reading: on NVIDIA the sensor is absent and the card is not judged on it.
--temp-hysteresis<C>10FEARMINER_TEMP_HYSTERESISHow far under its limit the memory or hotspot sensor must cool before the GPU resumes, in Celsius. The core has its own pair, --temp-limit and --temp-resume.
--temp-hold<SECS>15FEARMINER_TEMP_HOLDSeconds a sensor must hold at or over its limit before the GPU is paused; a shorter spike changes nothing. 0 pauses at the first reading.
--temp-shutdown<C>0FEARMINER_TEMP_SHUTDOWNStop the miner (exit code 11, E319) when a paused GPU's core holds at or over this temperature for --temp-hold seconds, counted from the pause. 0 turns it off; must be over --temp-limit.
--no-nvmlfalseFEARMINER_NO_NVMLDo not open NVML: no GPU sensors (temperature, fan, power, clock, throttle, energy), every sensor null on /api/v1/devices and /stats, and mining goes on. The gpu start line says sensors off (--no-nvml): no thermal cut-off.
-t, --threads<N|N%|-N|ALGO:N,...>FEARMINER_THREADSCPU mining threads: a count (8), a percentage of the automatic choice (50%, rounded to a thread), a delta (-2, +2), or one per algorithm (randomx:16, a bare value for the others). Automatic: 0 on a rig with a GPU (the CPU earns about 0.5 % of the rate for 17 % of the power), every thread but two without one; RandomX one thread per physical core, capped by the L3 cache (2 MiB per thread). More than the machine can spare (every thread but two, one per card) is capped to that, and the cpu log line says so (asked 999 with -t, capped to 30 of 32).
--igpufalseFEARMINER_IGPUMine on integrated GPUs too, even beside a discrete one.
--skip-preflightfalseFEARMINER_SKIP_PREFLIGHTIgnore the verdict of the checks before the first connection (driver version, compute capability, free GPU memory): the report is still printed, no card is left out, nothing stops the start.
--retunefalseFEARMINER_RETUNEMeasure the GPU launch geometry again, ignoring the cached result.
--self-test[=<ALGO>]FEARMINER_SELF_TESTThe engines' known-answer test. On a mining run it forces the test at start (otherwise skipped when the same binary, driver and cards passed before). Alone, without pool or wallet: offline for the algorithm of -a (--self-test=ALGO for another, --self-test=all for every one), a verdict per device, exit 0, or 3 on failure.
--self-test-nonces<N>256FEARMINER_SELF_TEST_NONCESNonces the self-test searches on each card, each re-hashed on the CPU.
--verify-shares<on|off>onFEARMINER_VERIFY_SHARESRe-check GPU solutions on the CPU before submitting (on, default) or not (off): every one while the check stays under 1 % of a core, one in ten past that: a wrong one is dropped and counted invalid on the card's row, not rejected by the pool. CPU solutions are never re-checked.
--gpu-batch<N>1000000FEARMINER_GPU_BATCHGPU batch size, in nonces per launch: a floor, rounded up to whole passes of the card's tuned geometry (the start line gives the batch in force).
--cpu-batch<N>1000FEARMINER_CPU_BATCHCPU batch size, in hashes between cancellation checks.
--throttle<MS>0FEARMINER_THROTTLEPause between GPU batches, in milliseconds; 0: none.
--list-devicesList the GPUs this machine can mine on (index, name, PCI id, UUID) and exit; nothing else is printed. --json gives the machine-readable form.
--jsonWith --list-devices or --list-algorithms, print the listing as JSON: cards with memory, compute capability, driver, vendor and engine, plus CPU and RAM; or algorithms with name, coin, class, fee_bps, aliases, unit, hive, requirements and refused.
CPU

CPU #

optionvaluedefaultFEARMINER_*what it does
--cpu-affinity<MASK|LIST>FEARMINER_CPU_AFFINITYPin the CPU workers to these logical CPUs, in worker order: a hex mask (0xff, bit i for CPU i) or a list (0-7,16-23). Replaces the automatic placement, one per physical core, spread over the NUMA nodes.
--cpu-priority<0-5>FEARMINER_CPU_PRIORITYCPU workers' priority, 0 (idle) to 5 (highest), the XMRig scale: nice 19, 5, 0, -5, -10, -15 on Linux, the thread priority class on Windows. Above 2 needs a privilege on Linux (E613 when refused). Default: the process's own.
--msr<auto|off|PRESET|LIST>autoFEARMINER_MSRRandomX MSR tweaks (the CPU's prefetchers, XMRig's public values), applied through fearminer-helper before the first connection, restored at exit. auto picks the preset from the CPU (zen1, zen2, zen3, zen4, zen5, intel); a missing helper or a machine that cannot take them (a VM, kernel lockdown, no msr module) skips with a coded line, never refusing the start. off writes nothing. A preset name or a list addr:value:mask,... forces the values, on the preset registers only (0x1a4, 0xc0011020 to 0xc0011022, 0xc001102b).
--1gb-pagesfalseFEARMINER_1GB_PAGESRandomX: reserve 1 GiB pages for the dataset, three per NUMA node, when the CPU has them (pdpe1gb): 1 to 3 % over 2 MiB pages. Off by default, as in XMRig. Only where the kernel's default huge page size is 1 GiB (default_hugepagesz=1G on the kernel command line). huge_pages_1g in the file.
--helper<PATH>FEARMINER_HELPERPrivileged helper (fearminer-helper), run as sudo -n PATH for the MSR tweaks and the huge-page reservation. Default: the installed /usr/local/bin/fearminer-helper (the path in the sudoers line), else the copy beside the miner's binary. A PATH given is the only path tried, never the installed helper behind it; E601 when sudo refuses it or nothing is there. Nothing usable at PATH does not refuse the start: a RandomX run says E601 and mines without the tweaks, --check-config warns. Unused when the miner is root (--allow-root): it does the same in-process.
Output

Output #

optionvaluedefaultFEARMINER_*what it does
--api-bind<IP:PORT>127.0.0.1:4300FEARMINER_API_BINDAddress the stats endpoint and the API listen on. 0.0.0.0:4300 opens them to the LAN, where /api/v1/* asks for the token.
--no-apifalseFEARMINER_NO_APIDo not serve the stats endpoint and the API.
--no-tuifalseFEARMINER_NO_TUIPlain scrolling log instead of the full-screen panel (what a pipe or a dumb terminal gets anyway).
--no-colorfalseFEARMINER_NO_COLORNo colour in the log; the panel in the terminal's own colours. NO_COLOR in the environment does the same.
-v, --verbosefalseFEARMINER_VERBOSEDebug-level log.
--log-file<PATH>FEARMINER_LOG_FILEAlso write the log to this file: one line per record, UTC timestamp, no colour, pool password masked. Appended to, never truncated; rotated by size (--log-max-size, --log-keep). Written in panel mode and plain mode alike.
--log-level-file<LEVEL>info · debug with -vFEARMINER_LOG_LEVEL_FILELog file level, apart from the console's: trace, debug, info, warn or error.
--log-max-size<MB>10FEARMINER_LOG_MAX_SIZESize, in MB, at which the log file is rotated to PATH.1, .2, ...
--log-keep<N>5FEARMINER_LOG_KEEPRotated log files kept (PATH.1 to PATH.N); 0 starts the file over.
--no-telemetryfalseFEARMINER_NO_TELEMETRYSend no telemetry at all: no install id is drawn or kept, and nothing goes to telemetry.fearminer.com (what it would carry: What FearMiner collects). No feature depends on it. The signed fee terms are still fetched from cfg.fearminer.com.
--telemetry-interval<MIN>15FEARMINER_TELEMETRY_INTERVALMinutes between two telemetry beats, 5 to 1440: under 5 is raised to 5 and over a day lowered to a day, and the log says so.
History

History #

optionvaluedefaultFEARMINER_*what it does
--history<on|off>onFEARMINER_HISTORYThis rig's history in <state dir>/history.bin (on, the default) or not (off): a sample every 10 s for 24 h, then one a minute for a week, one per five minutes for a month, one an hour beyond. Read by GET /api/v1/history and fearminer history. off keeps nothing; changing it needs a restart.
--history-retention<DAYS>90FEARMINER_HISTORY_RETENTIONDays of history kept. Past a week the samples are five minutes apart, past a month an hour: ninety days weigh a few megabytes. Reloaded without a restart.
--history-max-size<MB>32FEARMINER_HISTORY_MAX_SIZEHard bound on the history file, in MB: the file is laid out to fit it from the first byte and never grows past it. It wins over --history-retention, cut back to fit. Reloaded without a restart.
Benchmark

Benchmark #

optionvaluedefaultFEARMINER_*what it does
-B, --benchmarkMeasure this machine's hashrate and power, and exit; no pool or wallet needed. With -a all, or a list (-a quantus,randomx), every algorithm in turn, then a summary; one this machine cannot run is skipped with the reason, TensorCash too (no offline benchmark: its rate is measured on a pool). The clock starts after a warm-up, one untimed search per worker, so engine setup (the RandomX dataset build) is not counted. The figures go to the state directory (bench-<algo>.json); the next run prints them beside the new.
--duration<SECS>10 · 60Benchmark length per algorithm, in seconds: 10 for one algorithm, 60 for several.
--bench-seed<N>Deterministic benchmark: the work and every worker's nonce sequence derive from this seed. The run ends after --bench-solutions solutions per worker, not --duration. Every solution is re-checked on the CPU and a checksum printed: two runs on the same hardware print the same checksum, a hardware error does not.
--bench-solutions<K>4Solutions per worker a seeded benchmark runs to.
--warmup<SECS>0Untimed hashing after the engine is ready (its setup, its autotune and its first search done), before the clock starts: a card reaches its working temperature and clocks first. 0 starts the clock as soon as every device is ready.
--report<FILE>Write the benchmark's machine-readable report (schema fearminer.benchmark/1) to FILE, written aside then renamed, on success and on failure alike.
Supervisor

Supervisor #

optionvaluedefaultFEARMINER_*what it does
--no-supervisorfalseFEARMINER_NO_SUPERVISORRun the miner as one process, without the supervisor that restarts it after a crash. For systemd, HiveOS or another watchdog that restarts it itself, and for debugging.
--stop-timeout<SECS>8FEARMINER_STOP_TIMEOUTSeconds the supervisor waits after SIGTERM or Ctrl+C before killing the mining process.
--max-restarts<N>5FEARMINER_MAX_RESTARTSRestarts allowed within --restart-window before the supervisor gives up (exit code 12) and runs --on-failure.
--restart-window<MIN>30FEARMINER_RESTART_WINDOWThe window of --max-restarts, in minutes.
--on-failure<ACTION>exitFEARMINER_ON_FAILUREWhat the supervisor does when it gives up: exit, or script:<path> to run that script first (FEARMINER_EXIT_CODE, FEARMINER_CAUSE and FEARMINER_RESTARTS in its environment), then exit.
--allow-multiplefalseFEARMINER_ALLOW_MULTIPLERun even when another fearminer runs on this account; the single-instance lock is skipped.
--allow-rootfalseFEARMINER_ALLOW_ROOTMine as root. Without it a miner started as root exits with code 3. HiveOS runs every miner as root and its package passes this option.
--reset-crashesClear the per-GPU crash counters kept across restarts, and any quarantine with them, then start as usual; alone, without a pool, clear and exit.
Watchdog

Watchdog #

optionvaluedefaultFEARMINER_*what it does
--no-watchdogfalseFEARMINER_NO_WATCHDOGTurn the watchdog off: no hang, hashrate, share or reject check, no quarantine; a lost card leaves the others mining either way.
--hang-timeout<SECS>60FEARMINER_HANG_TIMEOUTSeconds a search may run without a sign of life from the GPU before the card counts as hung and the miner exits for a restart (code 10).
--zero-hashrate-timeout<SECS>300FEARMINER_ZERO_HASHRATE_TIMEOUTSeconds a GPU may report no hashes while the other cards mine before the miner exits for a restart (code 11); 5 min grace at start and after a thermal resume.
--no-share-timeout<SECS>1800FEARMINER_NO_SHARE_TIMEOUTSeconds without an accepted share from any device, after the session connected, before moving to the next pool; a second such period on the next pool exits for a restart (code 11). 0: off. A card earning nothing while the others do is judged alone, at ten times its expected time between shares, 10 to 60 minutes.
--hashrate-min<RATE>50%FEARMINER_HASHRATE_MINFloor for a GPU's ten-minute average: a share of its reference (50%, the best ten-minute average this session, or --hashrate-reference) or an absolute rate (300M, 1.2G). Under it the card is Degraded; still under after --hashrate-grace, the miner exits for a restart (code 11). Same floor for the rig's summed average. 0: off.
--hashrate-max<RATE>0FEARMINER_HASHRATE_MAXCeiling for a GPU's ten-minute average, in the same forms; over it the figure is wrong and is reported (E314), never restarted. 0: off.
--hashrate-grace<SECS>300FEARMINER_HASHRATE_GRACESeconds a GPU may stay under --hashrate-min before the miner exits for a restart; 0 never restarts it (Degraded and the alert only).
--hashrate-reference<RATE[,RATE...]>FEARMINER_HASHRATE_REFERENCEReference for the percentages of --hashrate-min and --hashrate-max, in H/s (600M): all cards, or one per card in engine order, comma separated. Learnt when not given: the best ten-minute average this session.
--share-famine<N>5FEARMINER_SHARE_FAMINEExpected share intervals (the difficulty over the card's rate) a GPU may go without a share, never under 10 minutes, before it is Degraded and its search restarted; a second famine exits for a restart (code 11). 0: off.
--max-rejects-device<N>5FEARMINER_MAX_REJECTS_DEVICEShares of one GPU the pool may refuse in a row (stale aside) before the card is Degraded until a share is accepted; also the solutions the CPU re-check may refuse within ten minutes. 0: off.
--max-rejects<N>15FEARMINER_MAX_REJECTSShares the pool may refuse in a row, from any device, before the session reconnects; a second such run moves to the next pool. 0: off.
--max-no-submit-responses<N>10FEARMINER_MAX_NO_SUBMIT_RESPONSESSubmits left unanswered for --submit-timeout, in a row, before the session reconnects; a second such run moves to the next pool. 0: off.
--device-quarantine<N>3FEARMINER_DEVICE_QUARANTINERestarts blamed on one GPU within --restart-window before it is Quarantined at the next start: out of mining while the others carry on, until the miner is restarted. Never the last device that could mine. 0: off.
Notifications

Notifications #

optionvaluedefaultFEARMINER_*what it does
--notify-url<URL>FEARMINER_NOTIFY_URLSend alerts to this URL as JSON (POST, format version 1); repeat or comma separate for several. Retried on a 5xx or a network error, never on a 4xx.
--notify-telegram<BOT_TOKEN:CHAT_ID>FEARMINER_NOTIFY_TELEGRAMSend alerts to a Telegram chat through a bot: BOT_TOKEN:CHAT_ID, the token from @BotFather.
--notify-discord<WEBHOOK_URL>FEARMINER_NOTIFY_DISCORDSend alerts to a Discord channel through its webhook URL.
--notify-secret<SECRET>FEARMINER_NOTIFY_SECRETSign each --notify-url body with HMAC-SHA256 under this secret, in X-FearMiner-Signature: sha256=<hex>.
--notify-min-severity<LEVEL>warningFEARMINER_NOTIFY_MIN_SEVERITYThe least severity sent: info, warning, error or critical.
--notify-testSend one test message (a rig_up) to every notifier and the heartbeat's /start, print the result, exit 0 when every delivery went through, 1 otherwise.
--heartbeat-url<URL>FEARMINER_HEARTBEAT_URLPing this URL every 60 s (GET; POST with --heartbeat-post), plus URL/start at startup and URL/fail on a critical event: the healthchecks.io convention. An Uptime Kuma push URL works as is.
--heartbeat-postfalseFEARMINER_HEARTBEAT_POSTPOST the heartbeat with a small JSON body (hashrate, effective hashrate, shares, uptime, restarts) instead of a GET.
OC

OC #

optionvaluedefaultFEARMINER_*what it does
--cclock<MHZ[,MHZ...]>FEARMINER_CCLOCKCore clock offset in MHz, signed (+100, -50), applied through the driver (NVIDIA, driver 520 or later). All cards, or one per card in -d order (100,_,-50: _ skips that card). Read back after setting; refused with its code when the driver says no (E703: needs root, --allow-root). Without an OC option no clock, power limit or fan register is touched.
--lock-cclock<MHZ[,MHZ...]>FEARMINER_LOCK_CCLOCKLock the core clock at this many MHz (nvidia-smi -lgc); 0 removes the lock. All cards, or one per card in -d order. A lock cannot be read back, so at exit it is reset to the driver's default.
--mclock<MHZ[,MHZ...]>FEARMINER_MCLOCKMemory clock offset in MHz, signed (+800, -500). One value for all cards, or one per card in -d order.
--lock-mclock<MHZ[,MHZ...]>FEARMINER_LOCK_MCLOCKLock the memory clock at this many MHz (nvidia-smi -lmc); must be a step the card publishes (405, 810, 5001, 10251...; E701 lists them otherwise). 0 removes the lock. All cards, or one per card in -d order.
--pl<W|N%[,...]>FEARMINER_PLPower limit, in watts (220) or as a percentage of the card's default limit (80%), within the range the card publishes (E702 gives the minimum and maximum otherwise). All cards, or one per card in -d order.
--fan<N%|auto[,...]>FEARMINER_FANFan speed in percent (70%), or auto to give the fan back to the driver's curve. All cards, or one per card in -d order. A card without fan control (a laptop) refuses it (E704).
--oc-delay<SECS>0FEARMINER_OC_DELAYSeconds after a card starts mining (its first accepted share, or 30 s at most) before its core offset and lock are applied: for rigs that crash when the offset lands on a cold card. 0 applies them at start with the rest.
--no-ocfalseFEARMINER_NO_OCIgnore every OC option and any [oc] section of the file: no clock, power limit or fan register is touched, and the start line says so. For a rig whose OC is set outside (HiveOS, Afterburner, a script).
--oc-reset-on-startfalseFEARMINER_OC_RESET_ON_STARTPut every selected card at the driver's defaults (locks removed, offsets 0, the default power limit, the fan on its curve) before the OC options are applied.
--oc-script<PATH>FEARMINER_OC_SCRIPTRun this program once per card before mining starts, directly, never through a shell, with FEARMINER_DEVICE, FEARMINER_PCI_BUS, FEARMINER_UUID and FEARMINER_ALGO in its environment; 30 s at most, exit code logged (E707 when not 0).
Commands

Commands #

optionvaluedefaultFEARMINER_*what it does
--unrestricted-api<LEVEL>readFEARMINER_UNRESTRICTED_APICommands a running miner takes beyond the reversible ones: read (default: pause, resume, toggle, retune), operate (restart, stop too), sensitive (wallet, pools, overclocking too). A command over the level is refused with E217, valid token or not. Guards the API alone (Control a running miner).
--hook<EVENT:PATH>FEARMINER_HOOKRun this program when EVENT happens, directly, never through a shell, with FEARMINER_EVENT and the event's context in its environment; 30 s at most, exit code logged (E139 when not 0). Repeat or comma separate for several. Events: start, exit, crash, pause, resume, pool-switch, share-rejected-high, low-hashrate, temp-high, device-lost.
--watch-configfalseFEARMINER_WATCH_CONFIGWatch the configuration file and reload it on change. Off by default: SIGHUP and PUT /api/v1/config reload it either way. A value that does not validate refuses the new file whole (E220); the configuration in force is kept.
--backgroundfalseFEARMINER_BACKGROUNDRun without a console: the process detaches and keeps mining after its shell is gone. Implies --no-tui; give --log-file to keep the log. Unix only; on Windows run the miner as a service.
--priority<0-5>FEARMINER_PRIORITYScheduling priority of the whole process, 0 (idle) to 5 (highest), on the --cpu-priority scale, which covers the worker threads alone. Above 2 needs a privilege on Linux; refused by the OS it is E613 and the normal priority is kept.
Commands

Commands #

commandwhat it does
fearminer explain [CODE]Explain an error code from the log (E302, e302 or 302): its cause, its impact and what to do, offline. Without a code, list them all.
fearminer token showPrint the API token a request from another machine must carry; made when there is none.
fearminer token rotateReplace the token and print the new one; the old stops working at the miner's next start.
fearminer verify <FILE>...Verify a download offline against the built-in release key. Given SHA256SUMS (its .minisig beside it) or an archive (its SHA256SUMS beside it): check the signature, then the SHA-256 of every listed file present in the same directory, one line each, ok, MISSING or MISMATCH. Exit 0 only when the signature is good and every present file matches.
fearminer config examplePrint a complete configuration file, every key with its default and its help as a comment, in monitoring mode (no wallet, no pool), to redirect into fearminer.toml and edit.
fearminer history --from --to --stepPrint what this rig did, from its own history, offline: no miner need run. Reads <state dir>/history.bin, prints the samples between --from and --to at --step, as CSV or JSON, the data GET /api/v1/history serves (Read mining history).
fearminer oc showPer card: its readings (clocks, offsets, power limit, fan), the steps and ranges it publishes, and what a run left to put back in oc-restore.json. -d narrows the cards, as for a run.
fearminer oc reset [--defaults]Put back what a run recorded in oc-restore.json and did not restore itself (a run killed without cleanup): one line per card with what was restored and what the card reads after. --defaults resets the selected cards to the driver's defaults instead. -d narrows the cards.
fearminer cockpitShow the cockpit of the miner already running on this machine: the full-screen panel of a foreground run, read from that miner's API once a second. It starts no miner; q or Ctrl+C closes the view only. When stdout is not a terminal, it prints the miner's log lines and a text summary every 10 seconds. Exit 2 (E822) when no miner answers. Alias: watch.
fearminer service <COMMAND>Run the miner as a service, started with the machine, restarted after a crash: install, status, logs, stop, start, restart, update, rollback, uninstall (update and rollback on Linux; The service).
fearminer enroll [CODE]Join the fleet of the cockpit that gave the code; --status says which fleet, --leave takes the rig out at once. Mining is untouched either way (Manage rigs from the cockpit).
fearminer remote <COMMAND>The remote channel on this machine: off, on, status, cancel (Manage rigs from the cockpit).
fearminer telemetry showPrint the beat the running miner would send, and send nothing; the run's options go after it. It draws the install id if there is none yet (never with --no-telemetry); what only a run measures is shown as at a start. --json prints the JSON alone.
fearminer telemetry rotate-idDraw a new random install id for the telemetry: from the miner's next start, the machine counts as a new install.
fearminer guiOpen the window: pick the algorithm, the pool, the wallet and the cards, start and stop the miner, watch its cards, shares and log. The same window a double-click opens; the settings go into the same fearminer.toml.

A switch takes true or false in the file or the environment (FEARMINER_NO_TUI=1). A list option (url, user, pass, tls_fingerprint, tls_spki, hook) takes a string or an array of strings. Options without a variable are one-shot actions and cannot be set from the environment.