Mac: bundle renamed Igneum Miner.app (network.igneum.miner, 0.1.0, LSMinimumSystemVersion 11.0, igneum.icns), Terminal title Igneum Miner, seed line in the first-run text, branded DMG (volume icon, background, icon slots via dmgbuild), dist/Igneum-Miner-0.1.0.dmg at 16.2 MB, tested synced against the live node on 27400/27401. Windows: packaging/windows with windres .rc files and embed-resources.sh (relink commands for the next cross-build), Igneum-Miner.iss (Program Files, Start Menu group, firewall rule, uninstall stops the processes, licence, seed line), BUILD-INSTALLER.bat and build-installer.ps1 for the project lead's PC (winget Inno Setup 6, rcedit fallback for the exe icon). Icons: brand/icons/make-icons.py makes igneum.icns, igneum.ico, the Inno wizard art and the DMG background. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
8.8 KiB
Igneum Miner for Mac (packaging/mac)
A DMG a miner can open on an Apple silicon Mac to run a node and the Metal miner, and show up on igneum.network/live. Built 3 October 2026 from the binaries already compiled in this repo; nothing is compiled here. Renamed from "Igneum Devnet" to "Igneum Miner" the same evening (bundle id network.igneum.miner, version 0.1.0); the devnet is still the only network and its name appears in the status lines, never in a window title.
Build
packaging/mac/build-dmg.sh
Output: packaging/mac/dist/Igneum-Miner-0.1.0.dmg (about 16 MB, lzfse). The script takes
vendor/igneum-node/target-rename/release/igneumd (falls back to target/release/kaspad renamed, and says so),
vendor/igneum-node/target/release/igneum-miner and proto-metal/igneum-bench (the plain build, the one whose
--serve protocol matches that miner), copies them into the bundle, strips the copies and signs them ad hoc again
(strip invalidates the linker signature and arm64 macOS refuses an unsigned binary), and checks that each copy still
runs. The originals are untouched. The icon is brand/icons/igneum.icns and the DMG art brand/icons/dmg-background.tiff
(both from python3 brand/icons/make-icons.py). The image is laid out by dmgbuild (pip3 install dmgbuild, settings in
dmg/settings.py: volume "Igneum Miner", hidden .VolumeIcon.icns with the custom-icon flag, background, icon slots app
(165,130), Applications (495,130), README and Stop command on the row below, no Finder scripting needed). Without dmgbuild
the script builds a plain hdiutil image and says so. build/ and dist/ are ignored by git.
What is on the DMG
| Item | What it is |
|---|---|
Igneum Miner.app |
the launcher bundle (below) |
README.txt |
10 lines for the miner (dmg/README.txt), with the seed line |
Stop Igneum Miner.command |
stops a copy whose window was closed without Ctrl+C (app/Stop Igneum Miner.command) |
Applications |
symlink, for the drag |
The app bundle
Igneum Miner.app/Contents/MacOS/Igneum Miner app/launcher.sh: removes quarantine from Resources, opens the script in Terminal
Igneum Miner.app/Contents/Resources/igneum-miner.sh the run script (app/igneum-miner.sh); sets the Terminal title "Igneum Miner"
Igneum Miner.app/Contents/Resources/bin/igneumd, igneum-miner, igneum-bench
Igneum Miner.app/Contents/Resources/igneum.icns
Igneum Miner.app/Contents/Info.plist app/Info.plist (CFBundleVersion = build stamp, LSMinimumSystemVersion 11.0)
Why a shell launcher and not an AppleScript applet: open -a Terminal <script> needs no Automation consent;
tell application "Terminal" to do script would prompt "Igneum Miner wants to control Terminal" on first run.
The launcher strips com.apple.quarantine from its own Resources first, because after Gatekeeper lets the app
through, every binary inside would still be checked on its first exec and refused as unidentified. That only works on
a writable volume, so the app refuses (with a dialog) to run straight from the DMG.
The run script (settings at the top)
| Variable | Default | Meaning |
|---|---|---|
SEED_PEERS |
192.168.68.64:26611 |
the Mac node on the project lead's LAN; a public seed node replaces it; comma list allowed |
MINERS |
1 |
miner identities; 0 = node only. One is right: one worker owns the whole GPU |
STATUS_SECS, UPLOAD_SECS |
30, 60 | status line and log upload periods |
IGNEUM_RPC_PORT, IGNEUM_P2P_PORT |
26610, 26611 | environment overrides (tests) |
IGNEUM_DATA, IGNEUM_LOGS |
~/Library/Application Support/Igneum/devnet, ~/Library/Logs/Igneum |
the only places written outside the bundle |
Order: checks (arm64, binaries, ports, no second copy via the pid file) > caffeinate -dims -w <launcher> >
igneumd --devnet --appdir ... --rpclisten 127.0.0.1:26610 --listen 0.0.0.0:26611 --addpeer <each seed> --nodnsseed --disable-upnp --nologfiles > every 5 s igneum-miner watch 1 until synced (peers > 0, blocks >= headers > 1 and
the count moving between readings, or stable for 60 s; this build's watch line has no synced= field) > igneum-miner mine grpc://127.0.0.1:26610 1 100000000 mac-<hostname> --worker igneum-bench --status-secs 30 --exit-on-seed-change --payout-label mac-<hostname> > loop: status every 30 s, uploads every 60 s (labels mac-<host>, nodelog-mac-<host>,
miner-mac-<host>, run id mac-<host>-<stamp>), node crash restarted after 5 to 60 s with the miners stopped until it
is synced again, miner exit 42 (hourly program change) restarted at once, other miner exits after 5 to 60 s.
Stopping: Ctrl+C (SIGINT), the window closing (SIGHUP) or SIGTERM set a flag; the loop then stops the miners and their
workers (TERM, 8 s, KILL), the node (TERM, 30 s, KILL), caffeinate, uploads the logs once more and prints a summary.
Children are started with SIGHUP ignored (bash already makes background children of a script ignore SIGINT), so the
launcher controls the order. igneum-miner.sh --stop and Stop Igneum Miner.command signal the launcher from the pid file
and fall back to pkill -f 'Igneum Miner.app/Contents/Resources/bin/' (the bundle path only, never a bare name).
The miner identity shows on igneum.network/live as the first 8 hex of its vote key hash; the window prints it.
Gatekeeper (expected on macOS 15 and 26)
The app is unsigned and not notarized. Double-click gives "Apple could not verify ... is free of malware" with no
Open button (unsigned and not notarized until the foundation has an Apple developer account). Right-click > Open offers Open on older systems; on macOS 15 and later the route is System Settings >
Privacy & Security > "Open Anyway" (the button appears after the first refusal), then open the app again. Both are in
README.txt. Removing the flag by hand also works: xattr -dr com.apple.quarantine "/Applications/Igneum Miner.app".
The first time igneumd listens on 0.0.0.0:26611 the macOS firewall (if on) asks to allow incoming connections; Allow.
Test (3 October 2026, this Mac, macOS 26.6.2, M5 Max)
Mounted the DMG and ran the script from the mounted bundle with SEED_PEERS=127.0.0.1:26611 MINERS=1 IGNEUM_RPC_PORT=27310 IGNEUM_P2P_PORT=27311 IGNEUM_DATA=/tmp/igneum-mac-test/data IGNEUM_LOGS=/tmp/igneum-mac-test/logs
(the live node as the seed, own node on 27300+, the Metal miner against that node).
| Check | Result |
|---|---|
| fresh database to synced | 22 s (0 blocks, 5,017 headers at 5 s; 9,988 blocks at 22 s); existing database 12 to 13 s |
| miner | started at sync, id 0aa660fe printed, first block 6 to 11 s later, 24 accepted blocks in 3 min 17 s, 0 rejected, 0 mismatched |
| rate | 16 to 18 MH/s wall, 40 MH/s inside jobs (the Mac was running two cargo builds and a census) |
| status line | every 30 s: status: accepted 22 blocks, 17.76 MH/s, template 0.89 s old | node 10205 blocks, 1 peers, synced | up 00:03:02 |
| uploads | 12 uploads in the intake under run id mac-MacBook-Pro-20261003-224420 (node tools/logs.mjs) |
| live page | 0aa660fe listed in igneum.network/api/live miners within a minute |
| Ctrl+C (SIGINT) | miners, worker, node gone in 5 s, summary printed, no stray process, pid and run files removed, ports free |
| SIGTERM | same, 4 s |
| Stop Igneum.command | node-only run stopped in 2 s; a second run says "Igneum is not running" |
Two things the test caught and fixed: an unquoted $NODE_EXE in the version line (the bundle path has a space), and
uname -m as the Apple silicon check (an x86_64 process, Rosetta, reports x86_64; now sysctl hw.optional.arm64).
Note for harness tests: a script started as a background job of a non-interactive shell has SIGINT ignored at entry
and cannot trap it; run it in the foreground or through perl -e '$SIG{INT}="DEFAULT"; exec ...'.
Test of the renamed bundle (3 October 2026, 23:20, this Mac)
Mounted Igneum-Miner-0.1.0.dmg (16,994,318 bytes): volume "Igneum Miner", .VolumeIcon.icns present and the custom-icon
flag set on the root (xattr -px com.apple.FinderInfo), .DS_Store with the four icon slots, .background.tiff. Copied the
app out and ran its script in a real Terminal window (open -a Terminal, as the launcher does) with MINERS=0 SEED_PEERS=127.0.0.1:26611 IGNEUM_RPC_PORT=27400 IGNEUM_P2P_PORT=27401 and scratch data and log folders: the window title
read "joshm, Igneum Miner, sleep, igneum-miner.sh, 80x24" (Terminal joins those with its own dashes), the first two log lines are the version line and the seed
line, synced in 77 s (11,995 blocks, the Mac was under load 25+), igneum-miner.sh --stop stopped it in 4 s through the
pid file, no leftover process, ports free. The live node on 26610/26611 was only a peer. Note: proto-metal/igneum-bench
carries minos 16.0 in its load command (built without a -target), so on a Mac older than macOS 26 the worker may refuse
to load even though the bundle says 11.0; a rebuild with -target arm64-apple-macos11 fixes that.