New 'tls' union config (disabled by default) spins up an
stunnel4 process inside the container that terminates TLS on
a configurable port (3334 by default) and forwards decrypted
stratum traffic to 127.0.0.1:${STRATUM_PORT}.
Cert is self-signed, generated once on first start with a
10-year validity and persisted at /root/.kamado/tls/ so the
fingerprint stays stable across restarts. SHA-256 fingerprint
is printed to container logs on each startup so users can
pin it on their miners. Miners must connect with
verification disabled (no CA trust chain for a private pool).
Runtime image grows by ~3MB for stunnel4 + openssl. The
supervisor loop now waits on three PIDs and tears all of them
down together if any one exits.
157 lines
5.3 KiB
Bash
Executable File
157 lines
5.3 KiB
Bash
Executable File
#!/bin/bash
|
|
# Kamado Pool StartOS entrypoint.
|
|
#
|
|
# Reads /root/.kamado/start9/config.yaml via yq, resolves the chosen
|
|
# bitcoind variant (mainnet vs testnet4), exports the env vars the
|
|
# upstream ckpool entrypoint expects, renders ckpool.conf from the
|
|
# template shipped alongside this script, and then supervises
|
|
# ckpool-solo + kamado-api as a pair.
|
|
set -euo pipefail
|
|
|
|
CONFIG_FILE="/root/.kamado/start9/config.yaml"
|
|
if [[ ! -f "${CONFIG_FILE}" ]]; then
|
|
echo "kamado-entrypoint: config file missing: ${CONFIG_FILE}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
q() { yq -r "$1" "${CONFIG_FILE}"; }
|
|
|
|
BITCOIND_VARIANT=$(q '.bitcoind.type')
|
|
case "${BITCOIND_VARIANT}" in
|
|
bitcoind)
|
|
export BITCOIN_RPC_HOST="bitcoind.embassy"
|
|
export BITCOIN_RPC_PORT=8332
|
|
;;
|
|
bitcoind-testnet)
|
|
export BITCOIN_RPC_HOST="bitcoind-testnet.embassy"
|
|
export BITCOIN_RPC_PORT=48332
|
|
;;
|
|
*)
|
|
echo "kamado-entrypoint: unknown bitcoind variant: ${BITCOIND_VARIANT}" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
export BITCOIN_RPC_USER=$(q '.bitcoind.user')
|
|
export BITCOIN_RPC_PASSWORD=$(q '.bitcoind.password')
|
|
export POOL_BTCADDRESS=$(q '.pool-address')
|
|
export POOL_BTCSIG=$(q '.pool-identifier')
|
|
export STRATUM_PORT=$(q '.stratum-port // 3333')
|
|
export STARTDIFF=$(q '.startdiff // 16384')
|
|
export MINDIFF=$(q '.mindiff // 1000')
|
|
export MAXDIFF=$(q '.maxdiff // 0')
|
|
export DROPIDLE=$(q '.dropidle // 0')
|
|
LOG_LEVEL=$(q '.log-level // "info"')
|
|
ZMQ_ENABLED=$(q '.zmq-enabled // true')
|
|
TLS_ENABLED=$(q '.tls.enabled // "disabled"')
|
|
TLS_PORT=$(q '.tls.port // 3334')
|
|
|
|
export LOGDIR=/var/log/ckpool
|
|
export SOCKET_DIR=/run/ckpool
|
|
export BITCOIN_NOTIFY=true
|
|
# ckpool itself doesn't use ZMQ in this build — zmqblock is stripped
|
|
# from the rendered conf below. kamado-api subscribes separately.
|
|
export ZMQ_BLOCK=""
|
|
export BLOCKPOLL_MS=100
|
|
export UPDATE_INTERVAL_S=30
|
|
mkdir -p "${LOGDIR}" "${SOCKET_DIR}" /etc/ckpool
|
|
|
|
# Render ckpool.conf using the same sed approach as the upstream
|
|
# KamadoPool ckpool entrypoint — the template is bundled into the
|
|
# image at build time.
|
|
TEMPLATE=/etc/ckpool/ckpool.conf.template
|
|
CONF=/etc/ckpool/ckpool.conf
|
|
sed \
|
|
-e "s|\${BITCOIN_RPC_HOST}|${BITCOIN_RPC_HOST}|g" \
|
|
-e "s|\${BITCOIN_RPC_PORT}|${BITCOIN_RPC_PORT}|g" \
|
|
-e "s|\${BITCOIN_RPC_USER}|${BITCOIN_RPC_USER}|g" \
|
|
-e "s|\${BITCOIN_RPC_PASSWORD}|${BITCOIN_RPC_PASSWORD}|g" \
|
|
-e "s|\${BITCOIN_NOTIFY}|${BITCOIN_NOTIFY}|g" \
|
|
-e "s|\${POOL_BTCADDRESS}|${POOL_BTCADDRESS}|g" \
|
|
-e "s|\${POOL_BTCSIG}|${POOL_BTCSIG}|g" \
|
|
-e "s|\${BLOCKPOLL_MS}|${BLOCKPOLL_MS}|g" \
|
|
-e "s|\${UPDATE_INTERVAL_S}|${UPDATE_INTERVAL_S}|g" \
|
|
-e "s|\${STRATUM_PORT}|${STRATUM_PORT}|g" \
|
|
-e "s|\${MINDIFF}|${MINDIFF}|g" \
|
|
-e "s|\${STARTDIFF}|${STARTDIFF}|g" \
|
|
-e "s|\${MAXDIFF}|${MAXDIFF}|g" \
|
|
-e "s|\${DROPIDLE}|${DROPIDLE}|g" \
|
|
-e "s|\${LOGDIR}|${LOGDIR}|g" \
|
|
-e "s|\${ZMQ_BLOCK}|${ZMQ_BLOCK}|g" \
|
|
"${TEMPLATE}" > "${CONF}"
|
|
sed -i '/"zmqblock":/d' "${CONF}"
|
|
|
|
echo "kamado-entrypoint: starting ckpool (solo, ${BITCOIND_VARIANT}) on port ${STRATUM_PORT}"
|
|
/usr/local/bin/ckpool --btcsolo --config "${CONF}" --sockdir "${SOCKET_DIR}" --log-shares &
|
|
CKPOOL_PID=$!
|
|
|
|
export LISTEN_ADDR=":8080"
|
|
export CKPOOL_SOCKDIR="${SOCKET_DIR}"
|
|
export CKPOOL_LOGFILE="${LOGDIR}/ckpool.log"
|
|
export BITCOIN_RPC_URL="http://${BITCOIN_RPC_HOST}:${BITCOIN_RPC_PORT}"
|
|
export POLL_INTERVAL=5s
|
|
export KAMADO_LOG_LEVEL="${LOG_LEVEL}"
|
|
if [[ "${ZMQ_ENABLED}" == "true" ]]; then
|
|
export BITCOIN_ZMQ_BLOCK="tcp://${BITCOIN_RPC_HOST}:28332"
|
|
else
|
|
export BITCOIN_ZMQ_BLOCK=""
|
|
fi
|
|
|
|
echo "kamado-entrypoint: starting kamado-api"
|
|
/usr/local/bin/kamado-api &
|
|
API_PID=$!
|
|
|
|
# Optional TLS stratum via stunnel sidecar.
|
|
STUNNEL_PID=""
|
|
if [[ "${TLS_ENABLED}" == "enabled" ]]; then
|
|
TLS_DIR=/root/.kamado/tls
|
|
CERT="${TLS_DIR}/stratum.pem"
|
|
mkdir -p "${TLS_DIR}"
|
|
if [[ ! -f "${CERT}" ]]; then
|
|
echo "kamado-entrypoint: generating self-signed stratum TLS cert"
|
|
openssl req -x509 -newkey rsa:2048 -sha256 -nodes \
|
|
-keyout "${TLS_DIR}/stratum.key" \
|
|
-out "${TLS_DIR}/stratum.crt" \
|
|
-days 3650 \
|
|
-subj "/CN=kamado-pool-stratum" >/dev/null 2>&1
|
|
cat "${TLS_DIR}/stratum.key" "${TLS_DIR}/stratum.crt" > "${CERT}"
|
|
chmod 600 "${TLS_DIR}/stratum.key" "${CERT}"
|
|
fi
|
|
FINGERPRINT=$(openssl x509 -in "${TLS_DIR}/stratum.crt" -noout -fingerprint -sha256 | cut -d= -f2)
|
|
echo "kamado-entrypoint: stratum TLS SHA256 fingerprint: ${FINGERPRINT}"
|
|
|
|
STUNNEL_CONF=/etc/stunnel/stratum.conf
|
|
mkdir -p /etc/stunnel
|
|
cat > "${STUNNEL_CONF}" <<EOF
|
|
foreground = yes
|
|
pid =
|
|
output = /dev/stdout
|
|
debug = 4
|
|
|
|
[stratum]
|
|
accept = 0.0.0.0:${TLS_PORT}
|
|
connect = 127.0.0.1:${STRATUM_PORT}
|
|
cert = ${CERT}
|
|
EOF
|
|
|
|
echo "kamado-entrypoint: starting stunnel on :${TLS_PORT} -> :${STRATUM_PORT}"
|
|
/usr/bin/stunnel4 "${STUNNEL_CONF}" &
|
|
STUNNEL_PID=$!
|
|
fi
|
|
|
|
term() {
|
|
echo "kamado-entrypoint: SIGTERM — shutting down"
|
|
kill -TERM "${API_PID}" "${CKPOOL_PID}" ${STUNNEL_PID:-} 2>/dev/null || true
|
|
wait "${API_PID}" "${CKPOOL_PID}" ${STUNNEL_PID:-} 2>/dev/null || true
|
|
exit 0
|
|
}
|
|
trap term TERM INT
|
|
|
|
# shellcheck disable=SC2086
|
|
wait -n ${CKPOOL_PID} ${API_PID} ${STUNNEL_PID:-}
|
|
EXIT_CODE=$?
|
|
echo "kamado-entrypoint: a supervised process exited (${EXIT_CODE}), stopping the rest"
|
|
kill -TERM "${API_PID}" "${CKPOOL_PID}" ${STUNNEL_PID:-} 2>/dev/null || true
|
|
wait || true
|
|
exit "${EXIT_CODE}"
|