MDK Logo

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-worker package 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 80 by 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:

FieldRequiredDescription
addressYesMiner IPv4 address or hostname. host is accepted as an alias
usernameNoHTTP Digest username. Defaults to root
passwordNoHTTP Digest password. Defaults to root — override with the real credentials
portNoHTTP API port. Defaults to 80
timeoutNoPer-request timeout in milliseconds. Defaults to 10000
typeNoDevice type tag such as miner-am-s21xp_hyd. Resolves the rated J/TH reported in snap
nominalEfficiencyWThsNoOverrides the nominal efficiency table for snap
confNoConfigured 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

On this page