Dont duplicate interfaces on port change 3.0

This commit is contained in:
2026-08-01 06:31:15 +03:00
parent be3bebeb5b
commit 703ca1b559
10 changed files with 106 additions and 85 deletions
+22 -32
View File
@@ -17,41 +17,40 @@ import { sdk } from './sdk'
export const uiPort = 8080
/**
* Stratum port defaults. The live values are user config (see store.json) —
* each one sets both ckpool's/stunnel's in-container bind AND the interface's
* preferred external port, so the number the user picks is the number miners
* connect to whenever the OS can grant it.
* In-container bind ports. These are FIXED and never user-configurable, which
* is load-bearing: a binding is keyed by (hostId, internalPort), so moving an
* internal port registers a *new* binding and orphans the old one — StartOS
* disables the orphan but keeps listing it, and the user sees a duplicate
* interface. Keeping these constant means each host has exactly one binding
* for the lifetime of the install, and a port change is a pure rebind that
* doesn't even restart the daemons.
*/
export const defaultStratumPort = 3333
export const defaultStratumTlsPort = 3334
export const stratumInternalPort = 3333
export const stratumTlsInternalPort = 3334
/**
* ckpool's second, loopback-only stratum bind. stunnel forwards decrypted TLS
* traffic here. ckpool tags clients by serverurl index (server == 1 -> TLS),
* which the dashboard reads to render a lock icon next to encrypted miners —
* no source-IP heuristics needed. The bind is harmless when TLS is disabled
* (nothing connects to it). Never user-visible, so it stays fixed — but it
* does occupy a port inside the container, hence validatePorts() below.
* (nothing connects to it).
*/
export const tlsInternalPort = 3437
export const ckpoolTlsLoopbackPort = 3437
/**
* Ports already taken inside the service container, mapped to what occupies
* them. A user-chosen stratum port may not collide with these.
* Defaults for the user-facing *external* ports (see store.json). These are
* what miners connect to; they are requested as each interface's
* `preferredExternalPort` and the OS grants them when free. Same numbers as
* the internal binds, so the out-of-the-box experience is unchanged.
*/
const occupiedPorts: Record<number, string> = {
[uiPort]: 'the web dashboard',
[tlsInternalPort]: "ckpool's internal TLS bind",
}
export const defaultStratumPort = 3333
export const defaultStratumTlsPort = 3334
/**
* Reject stratum port choices that cannot work: the two stratum ports would
* collide with each other, or with a port already bound inside the container.
* Returns a human-readable reason, or null when the pair is usable.
*
* All of these processes share one container (and therefore one network
* namespace), so a collision is a real bind failure at startup — better to
* refuse it in the config action than to restart-loop later.
* Reject external-port choices that cannot work. Since the user no longer
* picks any container-side port, the only real conflict left is asking for the
* same external port twice. Returns a human-readable reason, or null when the
* pair is usable.
*/
export function validatePorts(opts: {
stratumPort: number
@@ -60,16 +59,7 @@ export function validatePorts(opts: {
}): string | null {
const { stratumPort, stratumTlsPort, tlsEnabled } = opts
const clash = occupiedPorts[stratumPort]
if (clash) return `Stratum port ${stratumPort} is already used by ${clash}.`
if (!tlsEnabled) return null
const tlsClash = occupiedPorts[stratumTlsPort]
if (tlsClash)
return `Stratum TLS port ${stratumTlsPort} is already used by ${tlsClash}.`
if (stratumPort === stratumTlsPort)
if (tlsEnabled && stratumPort === stratumTlsPort)
return `The stratum port and the stratum TLS port must differ (both are ${stratumPort}).`
return null