igneum/packaging/mac
igneum-labs 381061a077 Mac app: dial the public seed node first, the home node second
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-03 22:28:58 +00:00
..
app Mac app: dial the public seed node first, the home node second 2026-10-03 22:28:58 +00:00
dmg Packaging: Igneum Miner for Mac and Windows, one-tap installs with the coin on every file and window 2026-10-03 22:26:57 +00:00
.gitignore Mac packaging: Igneum Devnet.app and DMG for Apple silicon miners 2026-10-03 21:54:22 +00:00
build-dmg.sh Packaging: Igneum Miner for Mac and Windows, one-tap installs with the coin on every file and window 2026-10-03 22:26:57 +00:00
README.md Packaging: Igneum Miner for Mac and Windows, one-tap installs with the coin on every file and window 2026-10-03 22:26:57 +00:00

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.