Expose config options for cleartext stratum port

This commit is contained in:
2026-08-01 06:31:15 +03:00
commit a2ae800a19
36 changed files with 4585 additions and 0 deletions
+73
View File
@@ -0,0 +1,73 @@
#!/bin/bash
# Kamado Pool — ckpool daemon wrapper for StartOS 0.4.0.
#
# main.ts renders /etc/ckpool/ckpool.conf.template into the subcontainer
# rootfs with everything resolved except the coinbase-builder self-test
# address, which depends on the active network. This script:
#
# 1. Blocks until bitcoind answers getblockchaininfo, so ckpool is never
# launched into a wall. When kamado-api kills ckpool on bitcoind
# failure (letting miners fail over to a backup pool), StartOS
# restarts this daemon and the wait re-arms until bitcoind recovers —
# the 0.3.x supervised-restart loop, expressed as a daemon.
# 2. Detects the chain and substitutes a network-valid self-test address.
# CKPool-solo uses the worker's stratum username as the payout address;
# the conf `btcaddress` is only consulted once at startup to build and
# validate a sample coinbase transaction against bitcoind. Since no
# worker has connected yet at that point, we hand it the genesis block
# coinbase address for the active network — always valid, and solo
# mode never credits it a satoshi.
# 3. Renders the final conf and execs ckpool.
#
# Env (set by main.ts): BITCOIN_RPC_URL, BITCOIN_RPC_USER,
# BITCOIN_RPC_PASSWORD, CKPOOL_SOCKDIR.
set -euo pipefail
TEMPLATE=/etc/ckpool/ckpool.conf.template
CONF=/etc/ckpool/ckpool.conf
SOCKDIR="${CKPOOL_SOCKDIR:-/run/ckpool}"
# CKPool loglevel: 6 = LOG_INFO, required for share-level logging
# (Accepted/Rejected client lines) used by the stats feature.
CKPOOL_LOGLEVEL="${CKPOOL_LOGLEVEL:-6}"
rpc() {
curl -sf --max-time 5 \
-u "${BITCOIN_RPC_USER}:${BITCOIN_RPC_PASSWORD}" \
-d "{\"jsonrpc\":\"1.0\",\"method\":\"$1\",\"params\":[]}" \
-H 'Content-Type: application/json' \
"${BITCOIN_RPC_URL}"
}
echo "kamado-ckpool: waiting for bitcoind at ${BITCOIN_RPC_URL}..."
backoff=2
until CHAIN_INFO=$(rpc getblockchaininfo); do
echo "kamado-ckpool: bitcoind not reachable (retry in ${backoff}s)"
sleep "${backoff}"
backoff=$(( backoff < 30 ? backoff * 2 : 30 ))
done
CHAIN=$(printf '%s' "${CHAIN_INFO}" | jq -r '.result.chain // "main"')
case "${CHAIN}" in
main)
# Satoshi's genesis block coinbase address.
SELFTEST_ADDRESS="1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"
;;
test|testnet4|signet|regtest)
# Testnet genesis coinbase address — valid P2PKH on testnet-family
# networks (testnet3/testnet4/signet/regtest share address prefixes).
SELFTEST_ADDRESS="mipcBbFg9gMiCh81Kj8tqqdgoZub1ZJRfn"
;;
*)
echo "kamado-ckpool: unknown chain '${CHAIN}', assuming mainnet" >&2
SELFTEST_ADDRESS="1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"
;;
esac
sed "s|@SELFTEST_ADDRESS@|${SELFTEST_ADDRESS}|g" "${TEMPLATE}" > "${CONF}"
mkdir -p "${SOCKDIR}"
echo "kamado-ckpool: starting ckpool (solo, chain=${CHAIN}), loglevel ${CKPOOL_LOGLEVEL}"
exec /usr/local/bin/ckpool --btcsolo --config "${CONF}" \
--sockdir "${SOCKDIR}" --log-shares -l "${CKPOOL_LOGLEVEL}"
+114
View File
@@ -0,0 +1,114 @@
#!/bin/bash
# Kamado Pool — stratum TLS certificate init (oneshot, idempotent).
#
# Generates the persisted self-signed stratum certificate the stunnel
# daemon serves. Regenerates only when files are missing or the cert-format
# version marker is outdated, so miners' pinned fingerprints survive
# restarts and updates. Run the "Regenerate TLS Certificate" action to
# force a fresh one.
#
# Env (set by main.ts): TLS_DIR (defaults to /root/.kamado/tls).
set -euo pipefail
TLS_DIR="${TLS_DIR:-/root/.kamado/tls}"
CRT="${TLS_DIR}/stratum.crt"
KEY="${TLS_DIR}/stratum.key"
CERT="${TLS_DIR}/stratum.pem"
MARKER="${TLS_DIR}/cert_version"
mkdir -p "${TLS_DIR}"
# Bump TLS_CERT_VERSION any time the cert format/extensions change.
# The startup check regenerates whenever the marker file is missing
# or doesn't match this version. This is more reliable than poking
# at the existing cert's extensions — we know *exactly* when a new
# shape is required and the upgrade self-heals on next boot.
# v4: broaden subjectAltName to cover mDNS / LAN / Tor hostnames
# so miner firmwares that verify the SAN against the hostname
# they were pointed at (e.g. AxeOS connecting to host.local)
# stop failing with MBEDTLS_ERR_X509_CERT_VERIFY_FAILED.
TLS_CERT_VERSION=4
NEEDS_REGEN=false
if [[ ! -f "${CERT}" || ! -f "${CRT}" || ! -f "${KEY}" ]]; then
NEEDS_REGEN=true
elif [[ ! -f "${MARKER}" ]] \
|| [[ "$(cat "${MARKER}" 2>/dev/null)" != "${TLS_CERT_VERSION}" ]]; then
echo "kamado-tls: TLS cert is older format (want v${TLS_CERT_VERSION}); regenerating"
NEEDS_REGEN=true
fi
if [[ "${NEEDS_REGEN}" == "true" ]]; then
echo "kamado-tls: generating self-signed stratum TLS cert v${TLS_CERT_VERSION}"
# Write the extensions to a config file rather than rely on
# `-addext`: some openssl builds emit them into unpredictable
# locations (e.g. CSR instead of the cert), and this is the
# documented, cross-version way to pin the full extension set.
CONF=$(mktemp)
cat > "${CONF}" <<'OPENSSL_CONF'
[ req ]
default_bits = 2048
default_md = sha256
prompt = no
distinguished_name = req_dn
x509_extensions = v3_cert
[ req_dn ]
CN = kamado-pool
[ v3_cert ]
basicConstraints = critical, CA:FALSE
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectKeyIdentifier = hash
subjectAltName = @alt_names
[ alt_names ]
# Specific StartOS / local names the pool might be reached through.
DNS.1 = kamado-pool.embassy
DNS.2 = kamado-pool
DNS.3 = localhost
# Wildcard SANs covering the TLDs miners typically use:
# *.local -> mDNS / Bonjour (e.g. obese-admirer.local on AxeOS)
# *.embassy -> StartOS inter-service hostnames
# *.onion -> Tor hidden services
# *.home.arpa -> RFC 8375 home network namespace
# *.lan -> common consumer router default TLD
# *.internal -> some LAN setups
# Strictly leftmost-label wildcards per RFC 6125; libraries that
# enforce this (mbedtls, OpenSSL, BoringSSL, Go crypto/tls) all
# accept them.
DNS.4 = *.local
DNS.5 = *.embassy
DNS.6 = *.onion
DNS.7 = *.home.arpa
DNS.8 = *.lan
DNS.9 = *.internal
IP.1 = 127.0.0.1
OPENSSL_CONF
openssl req -x509 -newkey rsa:2048 -nodes \
-keyout "${KEY}" \
-out "${CRT}" \
-days 3650 \
-config "${CONF}" \
>/dev/null 2>&1
rm -f "${CONF}"
# stunnel reads cert+key in either order, but cert-first is the
# convention openssl and most tooling expect.
cat "${CRT}" "${KEY}" > "${CERT}"
chmod 600 "${KEY}" "${CERT}"
printf '%s\n' "${TLS_CERT_VERSION}" > "${MARKER}"
# Log the extensions so operators can verify the cert is sane
# from the service logs without needing to exec into the
# container.
echo "kamado-tls: cert extensions:"
openssl x509 -in "${CRT}" -noout -ext subjectAltName,extendedKeyUsage,keyUsage 2>&1 \
| sed 's/^/ /'
fi
FINGERPRINT=$(openssl x509 -in "${CRT}" -noout -fingerprint -sha256 | cut -d= -f2)
printf '%s\n' "${FINGERPRINT}" > "${TLS_DIR}/fingerprint.txt"
echo "kamado-tls: stratum TLS SHA256 fingerprint: ${FINGERPRINT}"