Compare commits

...
3 Commits
Author SHA1 Message Date
satoshi 9fd8e6ec8e Prepare for publishing 2026-09-04 23:06:59 +03:00
satoshi be31a2fe58 Bump version to 0.2.8 to add upstream security hardening 2026-09-04 14:55:16 +03:00
satoshi 27f3e0e507 Add 0.2.7 version file 2026-09-04 01:03:41 +03:00
7 changed files with 361 additions and 115 deletions

No files matched your search

+113
View File
@@ -0,0 +1,113 @@
# Maintaining this package
Notes for whoever builds and ships the package. Nothing here is repeated
from `README.md`, which describes the runtime surface, or from
`instructions.md`, which is written for end users.
## Source layout
Kamado's own source is not vendored. The Makefile rsyncs `api/`, `ui/`
and `ckpool/` from a sibling checkout into `./kamado-src/`, which is
gitignored, before packing. Override the location with
`KAMADO_SRC=/path/to/KamadoPool`.
```text
startos/
manifest/ id, image, volumes, bitcoind dependency
main.ts subcontainer, config rendering, daemons, health checks
interfaces.ts dashboard and the three stratum interfaces
fileModels/ store.json
actions/ the user-facing actions
dependencies.ts bitcoind requirement and the ZMQ task
backups.ts both volumes
versions/ version graph and release notes
init/ store seeding and init ordering
i18n/ dictionaries for every user-facing string
assets/scripts/ ckpool run wrapper, TLS certificate init
Dockerfile ckpool, dashboard, API, runtime
```
## Prerequisites
Node and npm, Docker with buildx, `rsync`, and `start-cli`.
`start-cli` must be recent enough to pack `instructions.md`. Run
`start-cli s9pk list-ingredients`: if `./instructions.md` is absent from
the output, the build will silently ship without instructions and the
StartOS instructions page will be blank. Older builds also lack the
`--instructions` flag on `s9pk pack`.
`start-cli` resolves its configured StartOS host on every command,
including local ones like `s9pk pack`. The workspace config at
`.startos/config.yaml` (found by walking up from the working directory)
sets that host under `host.default`, and it must be a name that resolves
on the build machine even though packing never contacts it. The template
that `s9pk init-workspace` writes points at a Start9 development host,
which is what produces `Failed to resolve hostname` on a fresh workspace.
## Building
```sh
npm ci # once
make setup # once per boot: binfmt handlers and a multi-platform builder
make # kamado-pool.s9pk, universal, ship this
```
`make x86` and `make arm` emit single-arch packages and skip the other
architecture, which is much faster while iterating.
Only the CKPool and runtime stages are built for the target
architecture, and the aarch64 half of those runs under emulation on an
x86 host, which is why `make setup` is needed. The dashboard and API
stages pin `--platform=$BUILDPLATFORM` and cross compile instead: the
dashboard emits architecture-independent assets, and the API is
`CGO_ENABLED=0` with a pure-Go SQLite driver, so `GOARCH` cross
compilation is exact and the two slowest stages never run emulated.
`make setup` installs binfmt handlers from `tonistiigi/binfmt`. The
older `multiarch/qemu-user-static` image ships a qemu whose emulated gcc
segfaults intermittently part way through the CKPool build, which
presents as an unexplained compiler failure in bundled jansson or in the
test link step.
## Build failures worth recognising
**`Failed to resolve hostname`.** The workspace host does not resolve.
See Prerequisites above.
**A compiler crash inside the CKPool stage.** Usually emulation, not the
code. Re-run `make`; cached layers make the retry cheap. If it recurs,
confirm `make setup` installed the current binfmt handlers.
**`429 Too Many Requests` pulling base images.** Docker Hub's anonymous
pull limit, reached easily when iterating. It clears on its own, or
`docker login` raises the ceiling immediately.
## Installing
```sh
make install
```
Requires the workspace host to point at a real server. Otherwise
sideload the produced `.s9pk` through the StartOS web interface, which
accepts a reinstall of the same version.
## Release checklist
1. Add a version file under `startos/versions/` with release notes in
every locale the package already supports, and register it in
`versions/index.ts` as `current`, moving the previous version into
`other` so existing installs keep a migration path.
2. Keep `migrations` empty unless stored data actually changes shape,
and say why in a comment either way.
3. Update `README.md` if the runtime surface changed: processes,
volumes, interfaces, actions, tasks, health checks, backups or
limitations. Update `instructions.md` if operator-facing behaviour
changed.
4. Add any new user-facing string to the i18n dictionaries. The `i18n`
helper is typed against them, so a missing entry fails the typecheck
rather than shipping untranslated.
5. `npm run check` and `make`, then confirm the packed manifest reports
the intended version and that `instructions.md` is present in the
archive.
-22
View File
@@ -1,22 +0,0 @@
Kamado Pool
Copyright (C) 2026 Kamado Pool contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
---
This project is built on top of CKPool by Con Kolivas, which is itself
licensed under GPL-3.0. See https://bitbucket.org/ckolivas/ckpool for
the upstream source. The full GPL-3.0 text is available at:
https://www.gnu.org/licenses/gpl-3.0.txt
+202 -83
View File
@@ -1,95 +1,214 @@
# Kamado Pool, StartOS 0.4.0 Packaging
<p align="center">
<img src="icon.png" alt="Kamado Pool" width="160" />
</p>
StartOS **0.4.0** wrapper for [Kamado Pool](../KamadoPool), a modern solo Bitcoin mining pool built on a patched fork of CKPool-solo with a Go middleware API and Svelte real-time dashboard.
<h1 align="center">Kamado Pool</h1>
This is the 0.4.0 port of the [0.3.5.1 wrapper](../KamadoPool-StartOS-0351), rebuilt on the TypeScript `@start9labs/start-sdk` and the revised 0.4.0 service architecture.
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.
## What changed from the 0.3.5.1 package
Everything not listed in this document should behave the same as upstream.
| 0.3.5.1 | 0.4.0 |
## 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 |
|---|---|
| `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 |
| Image id | `main` |
| Source | `Dockerfile` at the repository root |
| Architectures | `x86_64`, `aarch64` |
| Base | Debian slim |
| Subcontainer | one shared instance for all processes |
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`.
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`.
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.
Processes, in start order:
## Prerequisites
| 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 |
- **Node.js + npm**
- **Docker** with buildx
- **start-cli**: from the [StartOS packaging guide](https://docs.start9.com/packaging/0.4.0.x/environment-setup.html)
- **rsync**
- **KamadoPool source**: local sibling checkout at `../KamadoPool` (override with `KAMADO_SRC=/path/to/KamadoPool`)
## Volume and Data Layout
## Building
Two volumes separate the service's own state from CKPool's, because they have different lifetimes and different restore semantics.
```sh
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)
| 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.
```yaml
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
```
`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:
```sh
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:
```sh
make install
```
Or sideload the produced `kamado-pool.s9pk` through the StartOS web UI.
### Overrides
```sh
make KAMADO_SRC=/path/to/KamadoPool
```
## Package layout
```text
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.
-8
View File
@@ -1,8 +0,0 @@
# TODO
- [ ] Replace the placeholder `packageRepo` / `upstreamRepo` / `marketingUrl` URLs in `startos/manifest/index.ts` once the repos are published.
- [ ] Make a real first commit in this repo so packed s9pks record a meaningful `gitHash` (builds currently need the `GIT_DIR` stub described in the README).
- [ ] Widen the `bitcoind` dependency floor check: the range is `>=28.4:13`, verified against Bitcoin Core 31.1 on-device.
- [ ] Test the 0.3.5.1 → 0.4.0 update path on a device that has the old package installed (config migration, DB/TLS/ckpool state carry-over).
- [ ] Consider pinning the `bitcoin-core-startos` dev dependency to `next/31.x` instead of `next/28.x`. It is a build-time type/constant dependency only, the host ids (`rpc`, `zmq`), ports (8332, 28332), action id (`autoconfig`), health-check ids (`bitcoind`, `sync-progress`) and the `zmqEnabled` field are identical in both branches, but matching the deployed 31.x package would catch upstream drift at typecheck time.
- [ ] Consider converting `icon.png` to an SVG.
+4 -2
View File
@@ -6,11 +6,13 @@ import { v0_2_3 } from './v0_2_3'
import { v0_2_4 } from './v0_2_4'
import { v0_2_5 } from './v0_2_5'
import { v0_2_6 } from './v0_2_6'
import { v0_2_7 } from './v0_2_7'
import { v0_2_8 } from './v0_2_8'
// The current version must be listed first; `other` carries the rest of the
// graph so StartOS can find a migration path from whatever version an existing
// install is currently on.
export const versionGraph = VersionGraph.of({
current: v0_2_6,
other: [v0_2_0, v0_2_1, v0_2_2, v0_2_3, v0_2_4, v0_2_5],
current: v0_2_8,
other: [v0_2_0, v0_2_1, v0_2_2, v0_2_3, v0_2_4, v0_2_5, v0_2_6, v0_2_7],
})
+21
View File
@@ -0,0 +1,21 @@
import { VersionInfo } from '@start9labs/start-sdk'
export const v0_2_7 = VersionInfo.of({
version: '0.2.7:0',
releaseNotes: {
en_US:
'Your best share and every block you find can now be shared as an image. A "Share card" button on the proof-of-work page, and on each row of the found-blocks table, opens a preview; the card can be saved as a PNG or copied straight to the clipboard, in a 9:16 story format or a 1:1 square for feed posts. The best-share card carries the difficulty, the block header hash with its leading zeros lit, and the raw 80-byte header itself, so the image is its own proof: a screenshot of a big number proves nothing, but those bytes are the share hash\'s exact preimage and anyone can hash them. A QR code carries the same header, so it can be scanned and checked without retyping 160 hex characters. The block card has a design of its own: a gold "I found a block!" headline, the block height, the reward, the difficulty of the winning share, and the chain named on a badge, so a testnet4 block is never mistaken for a mainnet one. Its QR code links to the block on an explorer, because a mined block is already public and the chain itself is the proof. Both cards carry Kamado Pool branding and the Bitcoin logo.',
es_ES:
'Su mejor participación y cada bloque que encuentre ahora se pueden compartir como imagen. Un botón «Tarjeta para compartir» en la página de prueba de trabajo, y en cada fila de la tabla de bloques encontrados, abre una vista previa; la tarjeta se puede guardar como PNG o copiar directamente al portapapeles, en formato historia 9:16 o cuadrado 1:1 para publicaciones. La tarjeta de mejor participación incluye la dificultad, el hash de la cabecera del bloque con sus ceros iniciales iluminados y la propia cabecera en bruto de 80 bytes, de modo que la imagen es su propia prueba: una captura de pantalla con un número grande no demuestra nada, pero esos bytes son la preimagen exacta del hash de la participación y cualquiera puede aplicarles el hash. Un código QR contiene la misma cabecera, así que se puede escanear y comprobar sin teclear 160 caracteres hexadecimales. La tarjeta de bloque tiene un diseño propio: un titular dorado «¡He encontrado un bloque!», la altura del bloque, la recompensa, la dificultad de la participación ganadora y la cadena indicada en una insignia, para que un bloque de testnet4 nunca se confunda con uno de mainnet. Su código QR enlaza al bloque en un explorador, porque un bloque minado ya es público y la propia cadena es la prueba. Ambas tarjetas llevan la marca de Kamado Pool y el logotipo de Bitcoin.',
de_DE:
'Ihr bester Share und jeder gefundene Block lassen sich jetzt als Bild teilen. Eine Schaltfläche „Share-Karte“ auf der Arbeitsnachweis-Seite und in jeder Zeile der Tabelle gefundener Blöcke öffnet eine Vorschau; die Karte lässt sich als PNG speichern oder direkt in die Zwischenablage kopieren, im Story-Format 9:16 oder quadratisch 1:1 für Feed-Beiträge. Die Bestwert-Karte enthält die Schwierigkeit, den Blockheader-Hash mit hervorgehobenen führenden Nullen und den rohen 80-Byte-Header selbst, sodass das Bild sein eigener Beweis ist: Ein Screenshot mit einer großen Zahl beweist nichts, aber diese Bytes sind das exakte Urbild des Share-Hashes, und jeder kann sie hashen. Ein QR-Code trägt denselben Header, sodass er gescannt und geprüft werden kann, ohne 160 Hexzeichen abzutippen. Die Block-Karte hat ein eigenes Design: eine goldene Überschrift „Ich habe einen Block gefunden!“, die Blockhöhe, die Belohnung, die Schwierigkeit des entscheidenden Shares und die Chain auf einem Abzeichen, damit ein testnet4-Block nie mit einem Mainnet-Block verwechselt wird. Sein QR-Code verweist auf den Block in einem Explorer, denn ein geschürfter Block ist bereits öffentlich und die Chain selbst ist der Beweis. Beide Karten tragen das Kamado-Pool-Branding und das Bitcoin-Logo.',
pl_PL:
'Twój najlepszy udział i każdy znaleziony blok można teraz udostępnić jako obraz. Przycisk „Karta do udostępnienia” na stronie dowodu pracy oraz w każdym wierszu tabeli znalezionych bloków otwiera podgląd; kartę można zapisać jako PNG lub skopiować wprost do schowka, w formacie story 9:16 albo kwadratowym 1:1 do wpisów w kanale. Karta najlepszego udziału zawiera trudność, hasz nagłówka bloku z podświetlonymi wiodącymi zerami oraz sam surowy 80-bajtowy nagłówek, dzięki czemu obraz jest własnym dowodem: zrzut ekranu z dużą liczbą niczego nie dowodzi, ale te bajty to dokładny przeciwobraz hasza udziału i każdy może je zahaszować. Kod QR zawiera ten sam nagłówek, więc można go zeskanować i sprawdzić bez przepisywania 160 znaków szesnastkowych. Karta bloku ma własny projekt: złoty nagłówek „Znalazłem blok!”, wysokość bloku, nagrodę, trudność zwycięskiego udziału oraz nazwę łańcucha na odznace, aby bloku z testnet4 nigdy nie pomylić z blokiem z mainnetu. Jej kod QR prowadzi do bloku w eksploratorze, ponieważ wykopany blok jest już publiczny, a sam łańcuch jest dowodem. Obie karty niosą oznaczenia Kamado Pool i logo Bitcoina.',
fr_FR:
'Votre meilleure part et chaque bloc trouvé peuvent désormais être partagés sous forme d’image. Un bouton « Carte à partager », sur la page de preuve de travail comme sur chaque ligne du tableau des blocs trouvés, ouvre un aperçu ; la carte peut être enregistrée en PNG ou copiée directement dans le presse-papiers, au format story 9:16 ou carré 1:1 pour les publications. La carte de meilleure part porte la difficulté, le hachage de l’en-tête de bloc avec ses zéros de tête mis en lumière et l’en-tête brut de 80 octets lui-même, si bien que l’image est sa propre preuve : une capture d’écran affichant un grand nombre ne prouve rien, mais ces octets sont la préimage exacte du hachage de la part et n’importe qui peut les hacher. Un code QR contient le même en-tête, ce qui permet de le scanner et de le vérifier sans retaper 160 caractères hexadécimaux. La carte de bloc a son propre design : un titre doré « J’ai trouvé un bloc ! », la hauteur du bloc, la récompense, la difficulté de la part gagnante et la chaîne nommée sur un badge, afin qu’un bloc testnet4 ne soit jamais pris pour un bloc du réseau principal. Son code QR renvoie au bloc dans un explorateur, car un bloc miné est déjà public et la chaîne elle-même est la preuve. Les deux cartes portent l’identité de Kamado Pool et le logo Bitcoin.',
},
// No data migration in either direction. Presentation only: the cards are
// drawn in the browser from data the dashboard already receives, and
// nothing stored changes shape.
migrations: {},
})
+21
View File
@@ -0,0 +1,21 @@
import { VersionInfo } from '@start9labs/start-sdk'
export const v0_2_8 = VersionInfo.of({
version: '0.2.8:0',
releaseNotes: {
en_US:
'Security hardening for the dashboard API. The WebSocket that feeds the dashboard, and every request that changes state, now verify that they came from the dashboard itself rather than from another site. Without that check, a web page you happened to visit while signed in to StartOS could have used your browser session to read pool data, including payout addresses, per-worker hashrates and block history, or to trigger admin actions such as zeroing the latency counters or starting a rebuild of the share statistics. Requests that are not browser-driven, such as the Pool Status action or a health probe, are unaffected. Responses now also tell browsers not to sniff content types and not to allow the dashboard to be embedded in a frame, and the share statistics rebuild refuses to start a second run while one is already going. The transaction accelerator was reviewed as part of this and needed no change: it already rejects anything that is not a 64 character transaction id, caps the fee rate at 2000 sat/vB, and passes values to Bitcoin Core as typed parameters.',
es_ES:
'Refuerzo de seguridad de la API del panel. El WebSocket que alimenta el panel, y toda petición que cambie el estado, ahora comprueban que proceden del propio panel y no de otro sitio web. Sin esa comprobación, una página que usted visitara mientras tenía la sesión iniciada en StartOS podría haber usado su navegador para leer datos del pool, incluidas las direcciones de pago, el hashrate por trabajador y el historial de bloques, o para activar acciones de administración como poner a cero los contadores de latencia o iniciar una reconstrucción de las estadísticas de participaciones. Las peticiones que no proceden de un navegador, como la acción Estado del pool o una comprobación de salud, no se ven afectadas. Las respuestas indican además a los navegadores que no deduzcan el tipo de contenido y que no permitan incrustar el panel en un marco, y la reconstrucción de estadísticas se niega a iniciar una segunda ejecución mientras ya hay una en curso. El acelerador de transacciones se revisó como parte de este trabajo y no necesitó cambios: ya rechaza todo lo que no sea un identificador de transacción de 64 caracteres, limita la tarifa a 2000 sat/vB y pasa los valores a Bitcoin Core como parámetros tipados.',
de_DE:
'Sicherheitshärtung der Dashboard-API. Der WebSocket, der das Dashboard versorgt, und jede zustandsändernde Anfrage prüfen jetzt, ob sie vom Dashboard selbst stammen und nicht von einer anderen Website. Ohne diese Prüfung hätte eine Webseite, die Sie bei angemeldeter StartOS-Sitzung besuchen, Ihre Browsersitzung nutzen können, um Pool-Daten auszulesen, darunter Auszahlungsadressen, Hashrate je Worker und Blockhistorie, oder um Admin-Aktionen auszulösen, etwa das Nullsetzen der Latenzzähler oder den Neuaufbau der Share-Statistiken. Nicht browsergesteuerte Anfragen, etwa die Aktion „Pool-Status“ oder eine Health-Prüfung, sind nicht betroffen. Antworten weisen Browser zudem an, Inhaltstypen nicht zu erraten und das Dashboard nicht in einem Frame einzubetten, und der Neuaufbau der Share-Statistiken verweigert einen zweiten Lauf, solange bereits einer läuft. Der Transaktionsbeschleuniger wurde dabei überprüft und benötigte keine Änderung: Er weist alles zurück, was keine 64 Zeichen lange Transaktions-ID ist, begrenzt die Gebühr auf 2000 sat/vB und übergibt Werte typisiert an Bitcoin Core.',
pl_PL:
'Wzmocnienie bezpieczeństwa API pulpitu. WebSocket zasilający pulpit oraz każde żądanie zmieniające stan sprawdzają teraz, czy pochodzą z samego pulpitu, a nie z innej witryny. Bez tej kontroli strona internetowa odwiedzona podczas zalogowania do StartOS mogła wykorzystać sesję przeglądarki do odczytania danych puli, w tym adresów wypłat, hashrate poszczególnych koparek i historii bloków, albo do uruchomienia akcji administracyjnych, takich jak wyzerowanie liczników opóźnień czy rozpoczęcie odbudowy statystyk udziałów. Żądania niepochodzące z przeglądarki, na przykład akcja Stan puli lub kontrola stanu zdrowia, pozostają bez zmian. Odpowiedzi informują ponadto przeglądarki, aby nie zgadywały typu treści i nie pozwalały osadzać pulpitu w ramce, a odbudowa statystyk odmawia uruchomienia drugiego przebiegu, gdy jeden już trwa. Akcelerator transakcji został przy tej okazji sprawdzony i nie wymagał zmian: już wcześniej odrzucał wszystko, co nie jest 64-znakowym identyfikatorem transakcji, ogranicza stawkę do 2000 sat/vB i przekazuje wartości do Bitcoin Core jako parametry typowane.',
fr_FR:
'Renforcement de la sécurité de l’API du tableau de bord. Le WebSocket qui alimente le tableau de bord, ainsi que toute requête modifiant l’état, vérifient désormais qu’ils proviennent bien du tableau de bord et non d’un autre site. Sans cette vérification, une page web visitée pendant que vous étiez connecté à StartOS aurait pu utiliser votre session de navigateur pour lire les données du pool, notamment les adresses de paiement, le hashrate par mineur et l’historique des blocs, ou pour déclencher des actions d’administration comme la remise à zéro des compteurs de latence ou le lancement d’une reconstruction des statistiques de parts. Les requêtes qui ne viennent pas d’un navigateur, comme l’action État du pool ou une sonde de santé, ne sont pas affectées. Les réponses indiquent en outre aux navigateurs de ne pas deviner les types de contenu et de ne pas autoriser l’intégration du tableau de bord dans un cadre, et la reconstruction des statistiques refuse de démarrer une seconde exécution tant qu’une autre est en cours. L’accélérateur de transactions a été revu à cette occasion et n’a nécessité aucune modification : il rejette déjà tout ce qui n’est pas un identifiant de transaction de 64 caractères, plafonne le tarif à 2000 sat/vB et transmet les valeurs à Bitcoin Core sous forme de paramètres typés.',
},
// No data migration in either direction. The change is confined to how
// the service decides whether to answer a request; nothing stored
// changes shape, and a downgrade simply removes the checks again.
migrations: {},
})