Run an Antminer Worker
Start an MDK Worker for a Bitmain Antminer device.
Overview
Antminer support ships as the external antminer-mdk-worker contract plugin, maintained by
Bitmain. It's a plain mdk-contract.json plus handler files, with no startAntminerWorker export, no provisioning
store, no alerts/stats templates, and no model allowlist: compatibility comes from the firmware capabilities each miner
reports. You host it yourself on WorkerRuntimeV2 through a small adapter; this repo ships a
working one to copy from (examples/mvp-site/backend/antminer-adapter.js).
Prerequisites
Review the common deployment prerequisites before you start.
Deployment-specific requirements:
- The
antminer-mdk-workerpackage added as a dependency (it's distributed as a git dependency, not on the npm registry — see its own README for the exact version/ref to pin) - A Node.js service or script in your deployment that constructs the adapter below and registers the resulting Worker
- An Antminer running stock firmware, reachable from the machine or container running the Worker
- The miner's HTTP CGI API reachable, port
80by default - HTTP Digest credentials for the miner. The factory default is
root/root; use your site's configured credentials
Development
Run against a mock
The plugin ships its own stateful mock at antminer-mdk-worker/mock/cgi-server. It enforces real digest
authentication, serves every CGI endpoint the Worker uses, and applies command writes to its state:
const amMock = require('antminer-mdk-worker/mock/cgi-server')
const mock = amMock.createServer({ port: 14080, host: '127.0.0.1', username: 'root', password: 'root' })
await mock.ready
// ...
await mock.close()examples/mvp-site boots one mock per seed device listed under antminers in
config/devices.json and points the adapter's devices at them. Read startAntminerMocks alongside
bootAntminerWorker in that example's backend/site.js for the full wiring. cd examples/mvp-site && npm run setup:example && npm start boots the whole stack — Kernel, mocks, and the Antminer Worker included.
Connect a miner
2.1 Write the adapter
antminer-mdk-worker has no boot helper of its own. Construct a WorkerRuntimeV2 pointed at
the package directory, translating your seed device list into the { deviceId, config } shape it expects:
const path = require('path')
const { WorkerRuntimeV2 } = require('@tetherto/mdk-worker')
const PKG_DIR = path.dirname(require.resolve('antminer-mdk-worker/package.json'))
async function startAntminerWorker (opts) {
const devices = (opts.seedDevices || []).map((seed) => ({
deviceId: seed.info?.serialNum || seed.id,
config: { ...(opts.type ? { type: opts.type } : {}), ...seed.opts }
}))
const runtime = new WorkerRuntimeV2(PKG_DIR, {
workerId: opts.workerId,
kernelTopic: opts.kernelTopic || null,
storeDir: opts.storeDir,
devices
})
await runtime.start()
return { runtime, seeded: devices.length, stop: () => runtime.stop() }
}
module.exports = { startAntminerWorker }This is the adapter examples/mvp-site/backend/antminer-adapter.js ships, trimmed of its input
validation and debug logging — copy the real file rather than this excerpt for a production deployment.
2.2 Register your miner
Add this to the Node.js service or script that runs your Worker. The snippet seeds one Antminer device; replace the example IP address and credentials with your miner's values:
const { getKernel } = require('@tetherto/mdk-core')
const { startAntminerWorker } = require('./antminer-adapter')
const kernel = await getKernel()
const worker = await startAntminerWorker({
workerId: 'antminer-rack-1',
storeDir: './store/antminer-rack-1',
type: 'miner-am-s21',
seedDevices: [{
info: { serialNum: 'AM-001' },
opts: { address: '192.168.1.10', port: 80, username: 'root', password: process.env.ANTMINER_PASSWORD }
}]
})
await kernel.registerWorker(worker.runtime.getPublicKey())Device config fields the plugin reads:
| Field | Required | Description |
|---|---|---|
address | Yes | Miner IPv4 address or hostname. host is accepted as an alias |
username | No | HTTP Digest username. Defaults to root |
password | No | HTTP Digest password. Defaults to root — override with the real credentials |
port | No | HTTP API port. Defaults to 80 |
timeout | No | Per-request timeout in milliseconds. Defaults to 10000 |
type | No | Device type tag such as miner-am-s21xp_hyd. Resolves the rated J/TH reported in snap |
nominalEfficiencyWThs | No | Overrides the nominal efficiency table for snap |
conf | No | Configured pools (conf.pools, max 3), timeouts and size limits |
Make sure each miner's IP is reachable from the machine or container running the Worker before registering. Commands act on physical hardware. Prioritize thermal safety.
The device list is fixed at construction — there is no registerThing/updateThing/forgetThings equivalent.
Adding, updating, or removing a device means editing seedDevices and restarting the Worker.
The antminer-mdk-worker README and USAGE document the plugin's telemetry channels, commands,
failure semantics, and live-device test scripts in full; the shared install pattern covers the
broader deployment mechanics.
Troubleshooting
The reference deployment is examples/mvp-site's full stack: npm start prints
MDK_READY worker-antminer devices=<n> once the Antminer Worker is up.
An unreachable miner doesn't fail at load time: the Worker reports the device online and the failure surfaces inside the telemetry channel or command response that touched the network. If the Worker doesn't come up, or a mock port is already in use, follow miner troubleshooting.
Next steps
- Understand the deployment topologies for running the Worker service
- Review
antminer-mdk-worker's ownmdk-contract.jsonfor telemetry units, command shapes, and error codes — it isn't vendored into this repo