Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ per the process in [`docs/dev/releasing.md`](docs/dev/releasing.md).

### Added

- **Node LAN exposure switches (#760)** — the serving side of the remote-node modes. `monero.zmq_lan_access`
publishes monerod's ZMQ feed on the LAN (with the existing `rpc_lan_access`, everything a remote
P2Pool needs), and `tari.grpc_lan_access` publishes the bundled Tari base node's gRPC, so one
stack's synced nodes can serve other stacks running `monero.mode`/`tari.mode: remote` (#103).
Both default off, publish loopback-only otherwise, and flipping either to the LAN is a
host-confirmed destructive change. The Tari gRPC and ZMQ feeds carry no authentication —
trusted networks only (see the remote-node sections in `docs/configuration.md`).

- **Remote Tari node (#103).** `tari.mode: remote` merge-mines against a Tari base node running
elsewhere instead of the bundled one: set `tari.remote.host` (required) and
`tari.remote.grpc_port` (default `18142`). Remote mode skips the bundled `tari` container, its
Expand Down
2 changes: 2 additions & 0 deletions build/dashboard/mining_dashboard/web/static/configlogic.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,11 @@ export const LOGICAL_GROUPS = [
"monero.prune",
"monero.remote",
"monero.rpc_lan_access",
"monero.zmq_lan_access",
"monero.clearnet_initial_sync",
"tari.mode",
"tari.remote",
"tari.grpc_lan_access",
"tari.clearnet_initial_sync",
],
},
Expand Down
2 changes: 2 additions & 0 deletions config.reference.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"prep_blocks_threads": "auto",
"out_peers": 48,
"rpc_lan_access": false,
"zmq_lan_access": false,
"data_dir": "auto",
"mem_limit": "auto",

Expand All @@ -30,6 +31,7 @@
"view_key": "",
"spend_public_key": "",
"payout_scan_birthday": "auto",
"grpc_lan_access": false,
"clearnet_initial_sync": false,
"data_dir": "auto",
"mem_limit": "auto",
Expand Down
10 changes: 10 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ services:
# the internal Docker network regardless. Set monero.rpc_lan_access:true in config.json
# to publish on the LAN (0.0.0.0) for wallets on other machines.
- "${MONERO_RPC_BIND:-127.0.0.1}:18081:18081"
# ZMQ block-notification feed (#760): loopback by default; set monero.zmq_lan_access:true to
# publish on the LAN — with rpc_lan_access, the serving side of monero.mode:remote (a remote
# p2pool needs both RPC and ZMQ). No auth on ZMQ pub: trusted LAN only.
- "${MONERO_ZMQ_BIND:-127.0.0.1}:18083:18083"
networks:
mining_net:
ipv4_address: ${NETWORK_PREFIX:-172.28.0}.26
Expand Down Expand Up @@ -262,6 +266,12 @@ services:
command:
- --disable-splash-screen
- --non-interactive
ports:
# Tari base-node gRPC for other machines (#760): loopback by default (host tools only; the
# same trust boundary as the console-wallet's loopback gRPC publish). Set
# tari.grpc_lan_access:true in config.json to publish on the LAN (0.0.0.0) — the serving
# side of tari.mode:remote (#103). Plaintext, unauthenticated: trusted LAN only (#754).
- "${TARI_GRPC_BIND:-127.0.0.1}:18142:18142"
networks:
mining_net:
ipv4_address: ${NETWORK_PREFIX:-172.28.0}.27
Expand Down
9 changes: 9 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ control channel will commit, are unaffected either way.
| `monero.prep_blocks_threads` | `auto` | Block-verification threads during sync. `auto` = host cores − 2, clamped to 4–8. |
| `monero.out_peers` | `48` | monerod's outbound peer target (8–1024). Over Tor each outbound peer is roughly one long-lived circuit, so this is the main steady-state lever on Tor's CPU (#595). Keep the default while syncing (more peers = more download bandwidth over Tor); once synced, `32` — the count P2Pool recommends for clearnet — cuts monerod's circuit maintenance by a third. |
| `monero.rpc_lan_access` | `false` | `true` publishes the node's RPC on the LAN (`0.0.0.0`) for wallets on other machines; default is localhost-only. |
| `monero.zmq_lan_access` | `false` | `true` publishes the node's ZMQ block-notification feed (`18083`) on the LAN. With `rpc_lan_access`, this is the serving side of `monero.mode: remote` — a remote P2Pool needs both RPC and ZMQ. ZMQ has no authentication: trusted networks only. |
| `monero.remote.host` / `rpc_port` / `zmq_port` | — / `18081` / `18083` | Remote node connection details (used when `mode` is `remote`). |
| `monero.data_dir` | `auto` | Where the Monero blockchain lives on the host. `auto` = `./data/monero`. Point this at an existing `.bitmonero` directory to reuse a synced node. See [Reusing an existing node](#reusing-an-existing-node). |
| `monero.mem_limit` | `auto` | Upper limit on the monerod container's memory, so a leak/runaway OOM-restarts monerod alone instead of the host's OOM-killer picking a victim. `auto` is a generous ceiling (6 GB) that won't trip during normal operation or initial sync. monerod's OOM-triggering memory is small (~0.1 GiB at rest, ~1–3 GiB during sync) while its multi-GB blockchain DB is reclaimable, memory-mapped page cache that the kernel evicts under pressure rather than OOM-killing. Lower it only to free RAM. Raise it for a full (unpruned) node doing a heavy initial sync on a fast disk, or if a low-RAM host ever OOMs monerod during IBD (it restarts and resumes; the on-disk chain is transactional, no data loss). Accepts any Docker memory value, e.g. `"8g"`. (Tari has its own `tari.mem_limit`; the dashboard, P2Pool, Tor, and the proxies are small and carry fixed conservative ceilings in `docker-compose.yml`.) |
Expand All @@ -115,6 +116,7 @@ control channel will commit, are unaffected either way.
| `tari.payout_scan_birthday` | `auto` | Where the view-only Tari wallet starts scanning on first creation (#462). Unlike Monero's block-height restore point, a Tari birthday is **days since the Unix epoch** (a u16, 0–65535). `auto` = today when the wallet is first made, so it tracks payouts forward without rescanning from genesis. Set an earlier day to backfill older payouts (slower first scan). Only affects the first wallet creation; ignored once the wallet exists. |
| `tari.clearnet_initial_sync` | `false` | Privacy-relevant, default off. `true` makes the Tari base node sync over clearnet instead of Tor: it switches the P2P transport to TCP, re-enables the `seeds.tari.com` DNS seed (the bundled onion `peer_seeds` are unreachable without Tor), and stops advertising its onion. Your node's IP becomes visible to the Tari P2P network while it's on, plus one DNS lookup of `seeds.tari.com`. `pithead` warns loudly (apply/status/doctor/up). The dashboard switches Tari back to Tor automatically once it's synced (#234), so you can leave this `true`. Full threat model: [Privacy › Optional clearnet initial sync](privacy.md#optional-clearnet-initial-sync-off-by-default). |
| `tari.remote.host` / `grpc_port` | — / `18142` | Remote Tari base node connection details (used when `tari.mode` is `remote`). See [Remote Tari node](#remote-tari-node). |
| `tari.grpc_lan_access` | `false` | `true` publishes the local Tari base node's gRPC (`18142`) on the LAN — the serving side of `tari.mode: remote`, so other stacks can merge-mine against this node. The gRPC is plaintext and unauthenticated: trusted networks only (see [Remote Tari node](#remote-tari-node)). Ignored in `remote` mode (no bundled node runs). |
| `tari.data_dir` | `auto` | Where the Tari node data lives on the host. `auto` = `./data/tari`. |
| `tari.mem_limit` | `auto` | Upper limit on the Tari container's memory, so a runaway Tari restarts cleanly on its own instead of dragging down the whole host. `auto` picks a safe size for your machine. Leave it unless you want to give Tari less RAM (to free it for other apps) or more (if it ever restarts too often). Accepts any Docker memory value, e.g. `"8g"`. |
| `p2pool.pool` | `mini` | Which P2Pool sidechain to mine: `main`, `mini`, or `nano`. `mini` (the default) has a lower share difficulty than `main`, so a typical home rig finds shares far more often: smoother, more frequent PPLNS payouts instead of long dry spells. Raise to `main` for high hashrate (large farms); drop to `nano` for a single low-power rig. |
Expand Down Expand Up @@ -448,6 +450,9 @@ To connect to an external Monero node instead of running one locally, set `moner
control; general-purpose public "open node" endpoints do not work, since they don't expose ZMQ.
- If the remote node requires RPC authentication, set `monero.node_username` / `node_password`
to match it; otherwise leave them out.
- If the remote node is another Pithead stack, the serving side is two switches on that stack:
`monero.rpc_lan_access: true` (RPC, digest-auth'd with its `node_username`/`node_password`)
and `monero.zmq_lan_access: true` (the ZMQ feed).

Switching between `local` and `remote` is a disruptive change, so `apply` will confirm before
applying it.
Expand Down Expand Up @@ -481,6 +486,10 @@ To merge-mine against a Tari base node running elsewhere instead of the bundled
exactly this
(`c_base_node_b_mining_allow_methods.toml`) so `get_new_block_template_with_coinbases` and
`submit_block` are reachable.
- If the remote node is another Pithead stack, that is one switch on the serving side:
`tari.grpc_lan_access: true` publishes its bundled node's gRPC on the LAN. (For the Monero
half of the same arrangement, the serving stack sets `monero.rpc_lan_access` and
`monero.zmq_lan_access`.)
- Leave `grpc_authentication` and `grpc_tls_enabled` off on the remote node. p2pool's Tari
merge-mine client dials plaintext, unauthenticated gRPC and has no way to speak either — turning
them on there just breaks the connection.
Expand Down
36 changes: 36 additions & 0 deletions pithead
Original file line number Diff line number Diff line change
Expand Up @@ -3713,6 +3713,15 @@ render_env() {
tari_grpc_addr="${TARI_REMOTE_HOST}:${TARI_REMOTE_GRPC_PORT}"
fi

# Tari gRPC LAN exposure (#760), mirroring monerod's rpc_lan_access above. Default
# localhost-only: in-stack consumers reach the node over the internal Docker network
# regardless, so the published port only serves other machines — the serving side of the
# remote mode (#103). The gRPC is plaintext and unauthenticated: trusted LAN only (#754
# trust model). N/A in remote mode (the tari service is profile-gated off; nothing binds).
local tari_grpc_bind tari_grpc_lan
tari_grpc_lan=$(jq -r '.tari.grpc_lan_access // false' "$CONFIG_FILE")
if [ "$tari_grpc_lan" == "true" ]; then tari_grpc_bind="0.0.0.0"; else tari_grpc_bind="127.0.0.1"; fi

# On-chain payout confirmation (#381): the view-only wallet-rpc service only starts when its
# compose profile is active, which is only when a view key is set on a local node. Off = no
# container, dashboard unchanged. PAYOUT_CONFIRM_ENABLED is set by parse_and_validate_config
Expand Down Expand Up @@ -3773,6 +3782,15 @@ render_env() {
rpc_lan=$(jq -r '.monero.rpc_lan_access // false' "$CONFIG_FILE")
if [ "$rpc_lan" == "true" ]; then rpc_bind="0.0.0.0"; else rpc_bind="127.0.0.1"; fi

# monerod ZMQ LAN exposure (#760). A separate key from rpc_lan_access on purpose: that key's
# documented use is wallets (RPC only), and widening it to also open ZMQ would change the
# exposure of existing deployments. A node SERVING remote stacks (#103's other half) needs
# both: rpc_lan_access for the RPC, zmq_lan_access for the block-notification feed p2pool
# requires. ZMQ pub has no auth — trusted LAN only.
local zmq_bind zmq_lan
zmq_lan=$(jq -r '.monero.zmq_lan_access // false' "$CONFIG_FILE")
if [ "$zmq_lan" == "true" ]; then zmq_bind="0.0.0.0"; else zmq_bind="127.0.0.1"; fi

# P2Pool pool type → flags + p2p port
local pool_type p2pool_flags p2pool_port
pool_type=$(jq -r '.p2pool.pool // "mini"' "$CONFIG_FILE")
Expand Down Expand Up @@ -4123,10 +4141,12 @@ CLEARNET_STATE_DIR=$CLEARNET_STATE_DIR
MONERO_PREP_THREADS=$prep_threads
MONERO_OUT_PEERS=$out_peers
MONERO_RPC_BIND=$rpc_bind
MONERO_ZMQ_BIND=$zmq_bind
MONERO_NODE_HOST=$mono_host
MONERO_RPC_PORT=$rpc_port
MONERO_ZMQ_PORT=$zmq_port
TARI_GRPC_ADDRESS=$tari_grpc_addr
TARI_GRPC_BIND=$tari_grpc_bind
COMPOSE_PROFILES=$profiles
DASHBOARD_SECURE=$DASHBOARD_SECURE
DASHBOARD_ONION_ENABLED=$DASHBOARD_ONION_ENABLED
Expand Down Expand Up @@ -4661,6 +4681,22 @@ describe_change() {
msg="Monero RPC bind address: $old → $new."
fi
;;
MONERO_ZMQ_BIND)
if [ "$new" == "0.0.0.0" ]; then
flag=DEST
msg="Monero ZMQ will be EXPOSED on your LAN ($old → $new) — it has no auth, trusted networks only."
else
msg="Monero ZMQ bind address: $old → $new."
fi
;;
TARI_GRPC_BIND)
if [ "$new" == "0.0.0.0" ]; then
flag=DEST
msg="Tari gRPC will be EXPOSED on your LAN ($old → $new) — it is plaintext and unauthenticated, trusted networks only."
else
msg="Tari gRPC bind address: $old → $new."
fi
;;
STRATUM_BIND)
if [ "$new" == "0.0.0.0" ]; then
flag=DEST
Expand Down
12 changes: 11 additions & 1 deletion tests/stack/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,11 @@ echo "== unit: describe_change =="
assert_contains "prune disable is DEST" "$(run_sourced "$SANDBOX" describe_change MONERO_PRUNE 1 0)" "DEST"
assert_contains "prune enable is CONFIRM" "$(run_sourced "$SANDBOX" describe_change MONERO_PRUNE 0 1)" "CONFIRM"
assert_contains "rpc lan is DEST" "$(run_sourced "$SANDBOX" describe_change MONERO_RPC_BIND 127.0.0.1 0.0.0.0)" "DEST"
# LAN exposure of the no-auth node feeds (#760): opening to 0.0.0.0 is DEST in that direction only.
assert_contains "zmq lan is DEST" "$(run_sourced "$SANDBOX" describe_change MONERO_ZMQ_BIND 127.0.0.1 0.0.0.0)" "DEST"
assert_contains "zmq close is INFO" "$(run_sourced "$SANDBOX" describe_change MONERO_ZMQ_BIND 0.0.0.0 127.0.0.1)" "INFO"
assert_contains "tari grpc lan is DEST" "$(run_sourced "$SANDBOX" describe_change TARI_GRPC_BIND 127.0.0.1 0.0.0.0)" "DEST"
assert_contains "tari grpc close is INFO" "$(run_sourced "$SANDBOX" describe_change TARI_GRPC_BIND 0.0.0.0 127.0.0.1)" "INFO"
assert_contains "stratum open is DEST" "$(run_sourced "$SANDBOX" describe_change STRATUM_BIND 127.0.0.1 0.0.0.0)" "DEST"
assert_contains "stratum lan is INFO" "$(run_sourced "$SANDBOX" describe_change STRATUM_BIND 0.0.0.0 127.0.0.1)" "INFO"
# Stratum port (#172/#719): changing it disconnects every rig until repointed — an operator-intent
Expand Down Expand Up @@ -3387,10 +3392,15 @@ seed_env
printf '{ "monero": {"mode":"local","wallet_address":"%s","node_username":"u","node_password":"p"}, "tari":{"wallet_address":"T"}, "p2pool":{"pool":"main"}, "dashboard":{"secure":true,"host":"box.lan"} }\n' "$WALLET" >"$V/config.json"
out="$(cd "$V" && PATH="$V/bin:$PATH" ./pithead apply -y 2>&1)"
assert_eq "rpc_lan_access default binds monerod RPC to localhost" "$(run_sourced "$V" env_get_file "$V/.env" MONERO_RPC_BIND)" "127.0.0.1"
# The #760 siblings default localhost-only the same way: ZMQ and the Tari gRPC publish.
assert_eq "zmq_lan_access default binds monerod ZMQ to localhost" "$(run_sourced "$V" env_get_file "$V/.env" MONERO_ZMQ_BIND)" "127.0.0.1"
assert_eq "grpc_lan_access default binds tari gRPC to localhost" "$(run_sourced "$V" env_get_file "$V/.env" TARI_GRPC_BIND)" "127.0.0.1"
seed_env
printf '{ "monero": {"mode":"local","wallet_address":"%s","node_username":"u","node_password":"p","rpc_lan_access":true,"prep_blocks_threads":6}, "tari":{"wallet_address":"T"}, "p2pool":{"pool":"main"}, "dashboard":{"secure":true,"host":"box.lan"} }\n' "$WALLET" >"$V/config.json"
printf '{ "monero": {"mode":"local","wallet_address":"%s","node_username":"u","node_password":"p","rpc_lan_access":true,"zmq_lan_access":true,"prep_blocks_threads":6}, "tari":{"wallet_address":"T","grpc_lan_access":true}, "p2pool":{"pool":"main"}, "dashboard":{"secure":true,"host":"box.lan"} }\n' "$WALLET" >"$V/config.json"
out="$(cd "$V" && PATH="$V/bin:$PATH" ./pithead apply -y 2>&1)"
assert_eq "rpc_lan_access true binds monerod RPC to all interfaces" "$(run_sourced "$V" env_get_file "$V/.env" MONERO_RPC_BIND)" "0.0.0.0"
assert_eq "zmq_lan_access true binds monerod ZMQ to all interfaces" "$(run_sourced "$V" env_get_file "$V/.env" MONERO_ZMQ_BIND)" "0.0.0.0"
assert_eq "grpc_lan_access true binds tari gRPC to all interfaces" "$(run_sourced "$V" env_get_file "$V/.env" TARI_GRPC_BIND)" "0.0.0.0"
assert_eq "prep_blocks_threads override reflected verbatim" "$(run_sourced "$V" env_get_file "$V/.env" MONERO_PREP_THREADS)" "6"

echo "== black-box: monero.out_peers renders to .env, bounds enforced (#595) =="
Expand Down
2 changes: 2 additions & 0 deletions tests/stack/test_compose.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,12 @@ PROXY_DONATE_LEVEL=1
MONERO_PRUNE=1
MONERO_PREP_THREADS=4
MONERO_RPC_BIND=127.0.0.1
MONERO_ZMQ_BIND=127.0.0.1
MONERO_NODE_HOST=172.28.0.26
MONERO_RPC_PORT=18081
MONERO_ZMQ_PORT=18083
TARI_GRPC_ADDRESS=172.28.0.27:18142
TARI_GRPC_BIND=127.0.0.1
COMPOSE_PROFILES=local_node,local_tari
DASHBOARD_SECURE=true
HOST_IP=box.lan
Expand Down