Files
bitdeals a5f9d13ca4 feat: docker image for ElectrumX, configured by environment
Replaces lukechilds/electrumx, unmaintained for years. ElectrumX 2.0.0 from the
upstream tag, rocksdb, built in a venv so only the runtime library follows into
the final image.

Every variable is ElectrumX's own — the entrypoint only fills defaults and
rejects the one mistake that is expensive to diagnose: NET spelled the way
bitcoind spells it ("test" for "testnet"), which otherwise fails deep inside a
coin-class lookup. DB_ENGINE defaults to rocksdb because 2.0 made the variable
required, and peer discovery is off because this image is for private indexers.

Verified on testnet2 against the sibling bitcoind image: coin BitcoinRegtest,
db height matching daemon height at 101, Electrum protocol answering on 50001.
That run also found what the README now states — 2.x refuses to serve unless
the daemon runs with both txindex=1 and txospenderindex=1.
2026-08-06 11:56:56 +00:00

76 lines
3.1 KiB
Bash
Executable File

#!/bin/sh
set -eu
# ElectrumX reads its own configuration from the environment, so this script
# only fills in defaults and checks the two mistakes that are expensive to
# diagnose later. Every variable below is ElectrumX's own name, not ours —
# anything documented upstream works here unchanged.
export COIN="${COIN:-Bitcoin}"
export NET="${NET:-mainnet}"
export DB_DIRECTORY="${DB_DIRECTORY:-/data}"
# Required by ElectrumX 2.0 (it refuses to start without it). rocksdb is what
# the image ships the libraries for.
export DB_ENGINE="${DB_ENGINE:-rocksdb}"
# Plaintext Electrum protocol plus the local RPC the health check talks to.
# Add ssl://:50002 to serve TLS (see the certificate section below).
export SERVICES="${SERVICES:-tcp://:50001,rpc://localhost:8000}"
# Off by default: this image is meant for private indexers behind a known
# daemon. A node that announces itself to the public server network is a
# deliberate act — set PEER_DISCOVERY=on and PEER_ANNOUNCE=true for it.
export PEER_DISCOVERY="${PEER_DISCOVERY:-off}"
export PEER_ANNOUNCE="${PEER_ANNOUNCE:-false}"
if [ -z "${DAEMON_URL:-}" ]
then
echo "DAEMON_URL is required, e.g. http://user:password@bitcoind:8332" >&2
exit 1
fi
# NET names the coin class ElectrumX looks up, and a wrong one is not a
# harmless mismatch: the class carries the genesis hash, so a testnet index
# pointed at a regtest daemon fails at the first block with a message about
# hashes rather than about configuration. The check exists mostly for one
# specific typo — bitcoind calls these networks `main` and `test`, ElectrumX
# calls them `mainnet` and `testnet`, and the pair is usually configured from
# the same .env.
case "$NET" in
mainnet | testnet | testnet4 | signet | regtest | mutinynet) ;;
*)
echo "NET must be one of mainnet, testnet, testnet4, signet, regtest, mutinynet (got '$NET')" >&2
exit 1
;;
esac
# A named volume starts out owned by root. Non-recursive: only the empty case
# needs fixing, and a mainnet index is hundreds of gigabytes.
mkdir -p "$DB_DIRECTORY"
if [ "$(stat -c %u "$DB_DIRECTORY")" != "$USER_UID" ]
then
chown "$USER_UID:$USER_GID" "$DB_DIRECTORY"
fi
# TLS on demand. ElectrumX requires both files as soon as SERVICES mentions
# ssl://, and refuses to start when they are missing — generating a self-signed
# pair is the difference between "works out of the box" and a startup error
# nobody expects from adding a port. Clients must trust it explicitly; a real
# certificate is supplied by pointing SSL_CERTFILE/SSL_KEYFILE elsewhere.
case "$SERVICES" in
*ssl://*)
export SSL_CERTFILE="${SSL_CERTFILE:-${DB_DIRECTORY}/electrumx.crt}"
export SSL_KEYFILE="${SSL_KEYFILE:-${DB_DIRECTORY}/electrumx.key}"
if [ ! -f "$SSL_CERTFILE" ] || [ ! -f "$SSL_KEYFILE" ]
then
echo "generating a self-signed certificate for $SSL_CERTFILE"
openssl req -x509 -newkey rsa:2048 -nodes -days 3650 \
-subj "/CN=electrumx" \
-keyout "$SSL_KEYFILE" -out "$SSL_CERTFILE" 2>/dev/null
chown "$USER_UID:$USER_GID" "$SSL_CERTFILE" "$SSL_KEYFILE"
chmod 600 "$SSL_KEYFILE"
fi
;;
esac
exec gosu electrumx electrumx_server "$@"