Kamado Pool — StartOS 0.4.0 Packaging
StartOS 0.4.0 wrapper for Kamado Pool, a modern solo Bitcoin mining pool built on a patched fork of CKPool-solo with a Go middleware API and Svelte real-time dashboard.
This is the 0.4.0 port of the 0.3.5.1 wrapper, rebuilt on the TypeScript @start9labs/start-sdk and the revised 0.4.0 service architecture.
What changed from the 0.3.5.1 package
| 0.3.5.1 | 0.4.0 |
|---|---|
manifest.yaml + Deno embassy.js procedures |
startos/ TypeScript package on @start9labs/start-sdk (npm), bundled with ncc |
Single container, docker_entrypoint.sh supervises ckpool + kamado-api + stunnel |
One shared subcontainer, three daemons (api, ckpool, stunnel) + oneshots, individually health-checked and ordered by the SDK daemon runtime |
Config form (getConfig/setConfig) writing start9/config.yaml |
store.json file model + Configure action with input spec; settings changes restart daemons reactively |
RPC credentials via config pointers to bitcoind/bitcoind-testnet |
bitcoind cookie auth read from a read-only dependency mount; RPC/ZMQ reached over the LXC bridge address resolved reactively (no .embassy DNS) |
Two dependency variants (bitcoind, bitcoind-testnet) |
Single bitcoind dependency; the active chain is detected at runtime from getblockchaininfo (the coinbase self-test address is chosen accordingly) |
| No LAN TCP forwarding — users needed router forwards / simpleproxy for stratum | Stratum (and TLS stratum) exposed as raw TCP host bindings, directly reachable on the LAN. In-container ports are fixed constants; the configured value sets only the interface's preferredExternalPort, so a port change is a pure rebind that neither orphans a binding nor restarts the pool |
properties for TLS fingerprint/PEM |
Stratum TLS Certificate action (fingerprint + PEM, copyable) |
| Health checks: web / ckpool / bitcoin / submit-gap | Same four, plus an optional ZMQ Block Feed check, as daemon ready checks + standalone health checks |
| duplicity backup of both volumes | sdk.setupBackups of both volumes (main, ckpool) |
| compat migrations | VersionGraph with an up migration that converts a 0.3.5.1 config.yaml into store.json and preserves the SQLite DB, TLS cert, and ckpool state |
| — | i18n (en, es, de, pl, fr) for all user-facing strings |
Retained behavior: the ckpool restart loop gated on bitcoind reachability (now a daemon wrapper script), dual block-detection (ZMQ + 100 ms blockpoll), loopback stratum binds for TLS tagging (now one per certificate, declared to kamado-api via STRATUM_SERVERS so the dashboard names the certificate on hover), the v4 self-signed certificate with broad SANs, and ckpool loglevel 6 with --log-shares.
Stratum is exposed on three endpoints, each a separate interface and port. Plaintext, and two TLS paths that differ in who terminates them: Stratum (TLS, Public Domain) declares addSsl, so StartOS terminates it and issues/renews a Let's Encrypt certificate for any domain attached to it — this is the only way to get a publicly trusted certificate, because StartOS provisions ACME only for endpoints it terminates TLS for, and a raw TCP binding is offered no certificate authority at all. Stratum (TLS, Local Network) stays raw TCP terminated in-container by stunnel with the persisted self-signed certificate, for LAN miners that pin it — public CAs cannot sign a bare IP or .local name. Each forwards to its own ckpool bind, so serverurl index identifies the path and the dashboard padlock names the certificate in use.
Prerequisites
- Node.js + npm
- Docker with buildx
- start-cli — from the StartOS packaging guide
- rsync
- KamadoPool source — local sibling checkout at
../KamadoPool(override withKAMADO_SRC=/path/to/KamadoPool)
Building
npm ci # once — installs the SDK and bitcoin-core-startos (for typed dependency wiring)
make setup # once per boot — qemu binfmt + a multi-platform buildx builder
make # kamado-pool.s9pk — the universal package (ship this)
make produces a universal kamado-pool.s9pk carrying both the x86_64 and aarch64 images, so a single file installs on any StartOS machine. For faster iteration during development, make x86 and make arm emit single-arch packages (kamado-pool_x86_64.s9pk / kamado-pool_aarch64.s9pk) and skip the other architecture entirely.
The Makefile syncs ../KamadoPool's api/, ui/, and ckpool/ into ./kamado-src/ (gitignored) before packing; start-cli s9pk pack then builds the Docker image per architecture from the local Dockerfile (ckpool is cloned from the pinned upstream commit and patched with Kamado's patch series, the Svelte UI is embedded into the Go binary).
Only the ckpool stage and the runtime stage are built for the target architecture — the aarch64 half of those runs under qemu emulation on an x86 host, which is why make setup is required. The UI and API stages pin --platform=$BUILDPLATFORM and cross-compile instead: the Svelte build emits architecture-independent static assets, and kamado-api is CGO_ENABLED=0 with a pure-Go SQLite driver, so GOARCH cross-compilation is exact and avoids emulating the two slowest stages.
Note: start-cli s9pk pack records a gitHash in the manifest and therefore requires this directory to be a git repository with at least one commit. Until you make one, you can point git at a throwaway repo just for the pack step:
git init /tmp/stub && cd /tmp/stub && touch .stub && git add .stub && git commit -m stub
GIT_DIR=/tmp/stub/.git make
Troubleshooting: if the Docker build fails with DNS errors like lookup registry-1.docker.io … connection refused from inside buildkit, your buildx builder container cannot resolve DNS (common with systemd-resolved hosts). The network=host driver option in make setup is what avoids this.
Install to your server
Configure ~/.startos/config.yaml with your server, then:
make install
Or sideload the produced kamado-pool.s9pk through the StartOS web UI.
Overrides
make KAMADO_SRC=/path/to/KamadoPool
Package layout
startos/
manifest/ id, images (local Dockerfile build), volumes, bitcoind dependency
main.ts subcontainer, ckpool.conf + stunnel.conf rendering, daemons + health checks (fixed internal ports)
interfaces.ts Web UI (http 8080), Stratum (raw TCP), Stratum TLS Local (raw TCP, stunnel/self-signed), Stratum TLS Public (addSsl, OS-terminated/Let's Encrypt)
fileModels/ store.json (service settings, incl. stratum ports)
actions/ Configure, Pool Status, Stratum TLS Certificate, Regenerate TLS Certificate, Reset Block Latency
dependencies.ts bitcoind (running, synced) + ZMQ autoconfig task
backups.ts volumes: main, ckpool
versions/ 0.2.2:0, graph back to 0.2.0 with migration from the 0.3.5.1 wrapper
init/ store seeding, init ordering
i18n/ dictionaries (en, es, de, pl, fr)
assets/
scripts/ kamado-ckpool-run.sh (bitcoind wait + chain detect + exec ckpool), kamado-tls-init.sh (cert v4)
Dockerfile ckpool (patched) + Svelte UI + Go API + runtime stage
License
GPL-3.0 — matches upstream Kamado and CKPool.