Groundwork for the app gate (item 1): before anything can enforce authentication on app ports, the node has to know which ports are *supposed* to be reachable without it. `PortMapping` grows `auth` (PortAuth::Session | None, defaulting to Session) and `auth_rationale`. The default is deliberately the protected one. Every app port on this node answered with no credential at all over LAN, Tailscale, Tor and the FIPS mesh alike — reproduced 2026-08-03 — precisely because exposure was what you got by saying nothing. Inverting the default means a new app is protected unless its manifest argues for an exemption. Validation makes the argument mandatory: `auth: none` without a rationale is rejected, and so is a rationale without `auth: none` (that combination means the author wrote an exemption and did not get one — shipping it silently would leave them believing otherwise). 17 ports across 12 apps are declared exempt, each with its reason. They are the ports that cannot sit behind an HTTP login page at all: Lightning p2p (BOLT-8 noise), LND gRPC/REST and CLN gRPC (macaroon / mutual TLS — Zeus and remote wallets dial these directly), Bitcoin p2p gossip, electrum wire protocol, Wyoming voice streams, git-over-SSH, and the UDP discovery protocols (mDNS, SSDP, STUN). Everything else — 39 published ports — now defaults to gated. Bitcoin's RPC 8332 is deliberately NOT exempted: it is already `bind: 127.0.0.1`, so the gate never sees it, and claiming an exemption it does not need would put a line in the audit list that means nothing. If the loopback bind is ever dropped, it fails closed. Two corpus tests keep this honest: every shipped manifest must parse under the new rules, and the exempt set is pinned at 17 so any change to the node's unauthenticated surface has to be a deliberate edit. Tests: 73/73 archipelago-container, workspace builds clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
91 lines
2.6 KiB
YAML
91 lines
2.6 KiB
YAML
app:
|
|
id: electrumx
|
|
name: ElectrumX
|
|
version: 1.18.0
|
|
description: Electrum server indexing Bitcoin chain data for lightweight wallet queries.
|
|
|
|
container:
|
|
image: 146.59.87.168:3000/lfg2025/electrumx:v1.18.0
|
|
pull_policy: if-not-present
|
|
network: archy-net
|
|
data_uid: "1000:1000"
|
|
entrypoint: ["sh", "-lc"]
|
|
# The bitcoin backend container is bitcoin-knots OR bitcoin-core depending
|
|
# on which version the node runs (multi-version switch) — probe which name
|
|
# resolves on archy-net instead of hardcoding knots, which left electrumx
|
|
# permanently disconnected (block index 0) on core nodes.
|
|
custom_args:
|
|
- >-
|
|
for h in bitcoin-knots bitcoin-core; do
|
|
if getent hosts "$h" >/dev/null 2>&1; then BTC_HOST="$h"; break; fi;
|
|
done;
|
|
export DAEMON_URL="http://archipelago:$(printenv BITCOIN_RPC_PASS)@${BTC_HOST:-bitcoin-knots}:8332/";
|
|
exec electrumx_server
|
|
secret_env:
|
|
- key: BITCOIN_RPC_PASS
|
|
secret_file: bitcoin-rpc-password
|
|
|
|
dependencies:
|
|
- app_id: bitcoin-knots
|
|
version: ">=26.0"
|
|
- storage: 50Gi
|
|
- bitcoin:archival
|
|
|
|
resources:
|
|
cpu_limit: 0
|
|
memory_limit: 6Gi
|
|
disk_limit: 50Gi
|
|
|
|
security:
|
|
capabilities: [DAC_OVERRIDE]
|
|
readonly_root: false
|
|
network_policy: isolated
|
|
|
|
ports:
|
|
- host: 50001
|
|
container: 50001
|
|
protocol: tcp
|
|
auth: none
|
|
auth_rationale: >-
|
|
Electrum wire protocol over TCP. Electrum wallets speak it directly and cannot hold a session cookie.
|
|
|
|
volumes:
|
|
- type: bind
|
|
source: /var/lib/archipelago/electrumx
|
|
target: /data
|
|
options: [rw]
|
|
|
|
environment:
|
|
- COIN=Bitcoin
|
|
- DB_DIRECTORY=/data
|
|
- SERVICES=tcp://:50001,rpc://0.0.0.0:8000
|
|
- CACHE_MB=1024
|
|
- MAX_SEND=10000000
|
|
|
|
# The ElectrumX dashboard tile is served by the host-networked companion UI
|
|
# (archy-electrs-ui) on port 50002, NOT by this container. Declaring it here
|
|
# lets the catalog generator emit electrumx -> 50002 into GENERATED_APP_PORTS
|
|
# so the tile resolves a launch URL without relying on the hand-maintained
|
|
# override in appSessionConfig.ts (which the generator can clobber). The
|
|
# backend only validates this block — it does not proxy/health-check it.
|
|
interfaces:
|
|
main:
|
|
name: Web UI
|
|
description: ElectrumX server status and connection details
|
|
type: ui
|
|
port: 50002
|
|
protocol: http
|
|
|
|
health_check:
|
|
type: tcp
|
|
endpoint: localhost:50001
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 3
|
|
start_period: 10m
|
|
|
|
bitcoin_integration:
|
|
rpc_access: read-only
|
|
sync_required: true
|
|
pruning_support: false
|