diff --git a/docker_entrypoint.sh b/docker_entrypoint.sh index 1906771..22e3f7a 100755 --- a/docker_entrypoint.sh +++ b/docker_entrypoint.sh @@ -134,6 +134,7 @@ if [[ "${TLS_ENABLED}" == "enabled" ]]; then chmod 600 "${TLS_DIR}/stratum.key" "${CERT}" fi FINGERPRINT=$(openssl x509 -in "${TLS_DIR}/stratum.crt" -noout -fingerprint -sha256 | cut -d= -f2) + printf '%s\n' "${FINGERPRINT}" > "${TLS_DIR}/fingerprint.txt" echo "kamado-entrypoint: stratum TLS SHA256 fingerprint: ${FINGERPRINT}" STUNNEL_CONF=/etc/stunnel/stratum.conf diff --git a/scripts/procedures/properties.ts b/scripts/procedures/properties.ts index 623ff70..40e0560 100644 --- a/scripts/procedures/properties.ts +++ b/scripts/procedures/properties.ts @@ -1,22 +1,91 @@ import { types as T, YAML } from "../deps.ts"; -const noProps: T.ExpectedExports.properties = async () => { +// StartOS does not forward raw TCP on the LAN interface, so stratum is +// reached via a router forward or a simpleproxy on another host. We +// can't know that external IP from inside the container, but we can +// publish the ports, the variant, and the TLS cert fingerprint so the +// user has everything they need to configure their miner. +export const properties: T.ExpectedExports.properties = async (effects) => { + const cfg = (await effects + .readFile({ volumeId: "main", path: "start9/config.yaml" }) + .then((s: string) => YAML.parse(s)) + .catch(() => ({}))) as any; + + const stratumPort = cfg?.["stratum-port"] ?? 3333; + const tlsEnabled = cfg?.tls?.enabled === "enabled"; + const tlsPort = cfg?.tls?.port ?? 3334; + const variant = cfg?.bitcoind?.type ?? "bitcoind"; + const network = variant === "bitcoind-testnet" ? "testnet4" : "mainnet"; + + let fingerprint = ""; + if (tlsEnabled) { + try { + fingerprint = ( + await effects.readFile({ + volumeId: "main", + path: "tls/fingerprint.txt", + }) + ).trim(); + } catch { + fingerprint = "(not yet generated — start the service once)"; + } + } + + const data: Record = { + "Network": { + type: "string", + value: network, + description: "Bitcoin network Kamado is mining on.", + copyable: false, + qr: false, + masked: false, + }, + "Stratum Port (plaintext)": { + type: "string", + value: String(stratumPort), + description: + "TCP port ckpool-solo listens on. Forward this from your router, or run simpleproxy on a LAN host, and point miners at stratum+tcp://:.", + copyable: true, + qr: false, + masked: false, + }, + }; + + if (tlsEnabled) { + data["Stratum Port (TLS)"] = { + type: "string", + value: String(tlsPort), + description: + "TCP port stunnel listens on for TLS stratum. Miners must disable cert verification (self-signed cert) and connect with stratum+ssl://:.", + copyable: true, + qr: false, + masked: false, + }; + data["TLS Cert Fingerprint (SHA-256)"] = { + type: "string", + value: fingerprint, + description: + "Pin this fingerprint on your miner if its firmware supports it. The certificate is self-signed and regenerated only if you delete tls/stratum.* in the data volume.", + copyable: true, + qr: false, + masked: false, + }; + } + + data["Worker Username"] = { + type: "string", + value: "[.]", + description: + "Configure each miner's stratum username as the Bitcoin address that should receive the block reward on a solve, optionally followed by .workername for dashboard labelling. Kamado refuses to authenticate workers whose username is not a valid address on the active network.", + copyable: false, + qr: false, + masked: false, + }; + return { result: { version: 2, - data: { - "Dashboard": { - type: "string", - value: - "Open the Kamado web UI from the Services page for live stats.", - description: "Kamado exposes everything through the web dashboard.", - copyable: false, - qr: false, - masked: false, - }, - }, + data, }, }; }; - -export const properties = noProps;