Files
KamadoPool-StartOS-040/README.md
T
2026-09-04 23:06:59 +03:00

15 KiB

Kamado Pool

Kamado Pool

Kamado Pool is a solo Bitcoin mining pool: a patched CKPool-solo stratum server, a Go middleware API, and a Svelte dashboard, packaged as one StartOS service. Block rewards are paid by the coinbase directly to the address each miner connects with, so the service holds no balances and performs no payouts.

Everything not listed in this document should behave the same as upstream.

Image and Container Runtime

The package builds a single image from the repository Dockerfile and runs every process inside one shared subcontainer, so the API can reach CKPool's Unix socket and tail its log file without cross-container plumbing.

Property Value
Image id main
Source Dockerfile at the repository root
Architectures x86_64, aarch64
Base Debian slim
Subcontainer one shared instance for all processes

The image is assembled in four stages: CKPool compiled from upstream source with the Kamado patch series applied, the dashboard built to static assets, the Go API cross compiled with those assets embedded in the binary, and a runtime stage carrying the two binaries plus curl, jq, stunnel4 and openssl.

Processes, in start order:

Name Kind Purpose
dirs oneshot Creates the data, TLS, log and socket directories on the volumes
api daemon Serves the dashboard, REST API and WebSocket feed; aggregates CKPool and Bitcoin Core state
ckpool daemon Stratum server; waits for Bitcoin Core, detects the active chain, then execs CKPool
tls-cert oneshot Generates the self-signed stratum certificate when absent or outdated
stunnel daemon Terminates stratum TLS and forwards to CKPool's loopback bind

Volume and Data Layout

Two volumes separate the service's own state from CKPool's, because they have different lifetimes and different restore semantics.

Volume Mount point Contents
main /root/.kamado SQLite database (found blocks, share statistics, accelerated transactions, log cursor), persisted stratum TLS certificate and key
ckpool /root/.ckpool CKPool's own state directory and its log files

Bitcoin Core's data directory is mounted read only at /mnt/bitcoind, solely to read the RPC cookie. Nothing is written there.

The rendered CKPool configuration and the stunnel configuration live on the subcontainer root filesystem rather than on a volume. Both are regenerated on every start, because both depend on values that are not known until the service runs: the active chain and the ports the OS actually assigned.

File Models

The package owns one persisted settings file, and everything else it writes is regenerated from that file plus runtime state.

File Location Seeded Rewritten by
store.json main volume Defaults on first start, or migrated from the previous package format The Configure action
CKPool configuration subcontainer rootfs Rendered on every start Service start, from store.json and the detected chain
stunnel configuration subcontainer rootfs Rendered on every start Service start, from store.json and the assigned ports
TLS certificate and key main volume Generated on first start The Regenerate TLS Certificate action, or automatically when the certificate format changes

Hand edits do not survive. The two rendered configurations are overwritten on every start, and store.json is owned by the Configure action. Change settings through Configure rather than by editing files.

Dependencies

Bitcoin Core is required. Kamado builds block templates from it, validates miner payout addresses against it, and submits solved blocks to it, so the service cannot mine without it.

Dependency Requirement Health checks required Mounts
Bitcoin Core Required, must be running Its own health check and its sync progress Its data directory, read only, for the RPC cookie

Sync progress is required deliberately. Mining against an unsynced node produces work on a stale chain tip, so an unsynced node is surfaced as an unsatisfied dependency rather than as a warning.

Network Access and Interfaces

Four interfaces are published. The dashboard is a web interface; the three stratum interfaces are raw TCP endpoints that miners connect to directly, with no proxy in front of them.

Interface Type Protocol Purpose
Web Dashboard ui http Dashboard, REST API and WebSocket feed
Stratum api tcp Plaintext stratum, the default for miners on a trusted network
Stratum (TLS, Local Network) api tcp Stratum over TLS using the package's self-signed certificate
Stratum (TLS, Public Domain) api tcp Stratum over TLS using a certificate StartOS issues for an attached domain

All three stratum endpoints run at the same time on separate ports. The stratum ports are configurable, but the numbers set in Configure are requests rather than guarantees: the OS assigns a different port when the requested one is already claimed, and the Pool Status action reports the ports actually in use.

The two TLS interfaces exist because they are secured differently. The local-network one serves a self-signed certificate that miners must be told to trust, since no public certificate authority will sign a bare LAN address. The public-domain one relies on StartOS issuing and renewing a publicly trusted certificate for a domain attached to that interface, which requires that domain to be reachable for the issuance challenge.

The dashboard's API refuses cross-origin browser requests on its WebSocket and on every request that changes state, so another site cannot drive it using a signed-in browser session.

Installation and First-Run Flow

Installation differs from upstream mainly in that there is no payout address to configure and no pool account to create.

  1. Install and start Bitcoin Core and let it finish syncing. The dependency stays unsatisfied until it does.
  2. Accept the suggested task to enable ZMQ on Bitcoin Core. It is recommended rather than required; without it the service falls back to RPC polling.
  3. Start Kamado Pool. On first start it creates its directories, generates a self-signed stratum certificate, detects which chain Bitcoin Core is running, and renders the CKPool configuration for that chain.
  4. Open the Web Dashboard and point miners at the stratum port.

Miners authenticate with a Bitcoin address as the stratum username, optionally followed by a worker name for labelling. The service validates that username against Bitcoin Core and refuses to authorise a worker whose username is not a valid address on the active chain, so a misconfigured miner fails loudly instead of mining to nowhere.

Actions

Every action is user-facing; none are hidden. Configure is the only one that changes settings, and the rest are diagnostic or maintenance operations.

Action Run it when What it changes Cost Safe to repeat
Configure Changing ports, vardiff, the coinbase tag, ZMQ, local TLS, log level or the explorer URL Writes store.json Rebinds interfaces; a port change does not restart the pool Yes
Pool Status Diagnosing anything Nothing One pass of internal queries Yes
Stratum TLS Certificate Setting up a miner that must trust the self-signed certificate Nothing Reads the stored certificate Yes
Regenerate TLS Certificate Rotating an expired or distrusted certificate Deletes the stored certificate and key A fresh certificate is generated on the next start Yes, but miners pinning the old fingerprint must be updated
Reset Block Latency After tuning ZMQ or the node, to start fresh measurements Zeroes the block-update latency counters Immediate Yes
Rebuild Share Statistics The all-time difficulty distribution or rejection reasons look wrong Replaces the stored totals, but only when the log accounts for more shares than they hold Reads the entire CKPool log, which can run to millions of lines Yes; a second run is refused while one is in progress

Pool Status returns a full text report: dependency and sync state, pool health, connected miners, hashrate, found blocks, the gap between attempted and confirmed block submissions, the endpoints and any domains actually in use, and the state of proof-of-work header capture. Stratum TLS Certificate returns both the SHA-256 fingerprint, for firmware that pins fingerprints, and the full PEM, for firmware that accepts a custom root. Rebuild Share Statistics reports how many shares the log accounted for and whether the stored totals were replaced.

Tasks

One task is raised, and only when the operator has asked for ZMQ.

Task Raised when Severity Cleared when
Enable ZMQ on Bitcoin Core ZMQ is enabled in Configure and Bitcoin Core does not have its ZMQ publishers on Important Bitcoin Core's configuration matches, or ZMQ is turned off in Configure

It is important rather than critical because the service degrades gracefully. Without ZMQ it polls the RPC for new blocks instead, at the cost of slower stale-work detection.

Health Checks

Six checks cover the two daemons, the dependency, and three failure modes that process state alone cannot reveal.

Check Probes Grace period Failure means Remediation
Web Dashboard The dashboard port is accepting connections 15 seconds The API is not serving Check the service logs
Stratum Server The stratum port is accepting connections 30 seconds Miners cannot connect Check the service logs; CKPool waits for Bitcoin Core before it binds
Bitcoin Core RPC The API can reach Bitcoin Core and it reports itself synced Startup only No usable templates, so no useful work is served Check that Bitcoin Core is running and synced
Block Submission Every attempted block submission reached confirmation Startup only A solved block was submitted but never confirmed Check the Bitcoin Core logs; of these checks this is the one worth investigating immediately
ZMQ Block Feed Block notifications are still arriving, when ZMQ is enabled Startup only Notifications have gone stale and detection has fallen back to polling Re-run the ZMQ task, or check Bitcoin Core's publishers
Stratum TLS The TLS stratum port is accepting connections, when local TLS is enabled Startup only Miners using TLS cannot connect Confirm the certificate exists; regenerate it if not

Backups and Restore

Both volumes are backed up in full, because the service's history has no other source.

The main volume carries the SQLite database and the stratum TLS certificate, so a restore preserves found blocks, share statistics, best-share records, and the certificate that miners may have pinned. The ckpool volume carries CKPool's state and its logs. The logs are included deliberately rather than treated as disposable: the database holds a read cursor into them and the share statistics can be rebuilt from them, so restoring one without the other leaves the two inconsistent.

Nothing is excluded. There is no wallet, no key material beyond the stratum certificate, and no accounting state to rebuild, because rewards are paid by the coinbase directly to miners.

Limitations and Differences

These are the places where the packaged service is narrower than upstream, or where the OS rather than the package has the final say. None of them prevent normal solo mining.

  1. Only the chain Bitcoin Core is already running is supported. The service detects it at start; there is no chain selector.
  2. The stratum ports set in Configure are requests, not guarantees. The OS assigns a different port when the requested one is taken.
  3. The domain used for public-domain TLS is not a package setting. It follows whatever domain is attached to that interface, and only its port is configurable.
  4. Certificates for a public domain are issued by StartOS rather than by the package. If issuance fails, that endpoint serves the self-signed certificate instead, which public clients reject.
  5. The dashboard's read-only endpoints are not individually authenticated. Anything that can reach the dashboard port on the network can read pool data, including payout addresses and per-worker hashrates.
  6. Proof-of-work header capture covers only shares accepted after that feature was introduced. Earlier best shares cannot be reconstructed, because CKPool discards job data once work moves on.
  7. Share statistics can only be rebuilt as far back as the current CKPool log reaches.
  8. The service kills CKPool when Bitcoin Core becomes unreachable, so miners fail over to a backup pool instead of mining stale work. CKPool restarts automatically once Bitcoin Core recovers.

Quick Reference for AI Consumers

The block below summarises the operable surface in one place, for tooling and support agents that need the shape of the service without reading the sections above.

service:
  purpose: solo Bitcoin mining pool; rewards paid by coinbase directly to the miner
  holds_funds: false
  payout_address: supplied by each miner as its stratum username

image:
  id: main
  architectures: [x86_64, aarch64]
  subcontainer: single, shared by all processes

processes:
  oneshots: [dirs, tls-cert]
  daemons: [api, ckpool, stunnel]

volumes:
  main: {mount: /root/.kamado, holds: [sqlite database, tls certificate]}
  ckpool: {mount: /root/.ckpool, holds: [ckpool state, logs]}
  bitcoind: {mount: /mnt/bitcoind, mode: read-only, purpose: rpc cookie}

dependencies:
  bitcoind: {required: true, must_be: [running, synced]}

interfaces:
  ui: {name: Web Dashboard, protocol: http}
  stratum: {protocol: tcp, tls: false}
  stratum-tls: {protocol: tcp, tls: self-signed}
  stratum-tls-public: {protocol: tcp, tls: issued-by-startos}

actions:
  configure: {mutates: settings}
  pool-status: {mutates: nothing, use_for: diagnosis}
  stratum-tls-certificate: {mutates: nothing, returns: [fingerprint, pem]}
  regenerate-tls-certificate: {mutates: tls certificate}
  reset-block-latency: {mutates: latency counters}
  rebuild-share-statistics: {mutates: all-time share statistics, cost: full log scan}

health_checks:
  [web dashboard, stratum server, bitcoin core rpc, block submission,
   zmq block feed, stratum tls]

tasks:
  enable-zmq: {target: bitcoind, severity: important, optional: true}

backups:
  volumes: [main, ckpool]
  excluded: none

first_run:
  requires: bitcoin core running and synced
  generates: self-signed stratum certificate
  configuration_needed: none for mining; miners supply their own payout address