Files
electrumx/README.md
T
bitdeals 7a7ecfb303
Build docker image and push to registry.bitdeals.org / build (push) Failing after 4m25s
ci: build and publish the image on every push to main
The registry account available on the testnet hosts is pull-only (403 on a
blob upload even for an existing repository), so publishing goes the same way
every other BitDeals image does: the Gitea runner builds and pushes with the
CI credentials. Tags mirror the family — an immutable <version>.<sha7>, a
moving <version>, and :latest for compose and Watchtower.

The version is read out of the Dockerfile ARG rather than repeated here: a tag
that can disagree with the code inside is worse than no tag.
2026-08-06 12:01:13 +00:00

6.3 KiB

Intro

Русская версия: README.ru-RU.md

ElectrumX is a server for the Electrum protocol. It indexes the chain from a full node and answers the queries a light client cannot answer for itself: the history and the UTXOs of an arbitrary address, and transaction broadcast.

ElectrumX running in a docker container, configured by environment variables.

This repository covers the docker deployment only. ElectrumX itself is installed from a pinned upstream git tag.

Usage

ElectrumX needs a bitcoind it can reach over RPC, on the same network, not pruned. DAEMON_URL is the only required variable; NET must name the same chain the daemon runs.

The container serves the Electrum protocol on 50001 (plaintext TCP) and, if SERVICES asks for it, on 50002 (TLS). There is no authentication of any kind, so keep both inside the docker network or on loopback. The RPC service on localhost:8000 is administrative and never leaves the container — the health check is what uses it.

docker-compose

services:
  electrumx:
    build:
      context: https://git.bitdeals.org/private/electrumx.git
      dockerfile: ./docker/Dockerfile
    image: registry.bitdeals.org/electrumx
    environment:
      - COIN=Bitcoin
      - NET=regtest
      - DAEMON_URL=http://CHANGE_ME:CHANGE_ME@bitcoind:18443
      - CACHE_MB=400
    ports:
      - 127.0.0.1:50001:50001   # no auth — loopback only
    volumes:
      - electrumxdata:/data

volumes:
  electrumxdata:

docker cli

docker run -d \
  -e COIN=Bitcoin \
  -e NET=regtest \
  -e DAEMON_URL=http://CHANGE_ME:CHANGE_ME@bitcoind:18443 \
  -e CACHE_MB=400 \
  -p 127.0.0.1:50001:50001 \
  -v electrumxdata:/data \
  registry.bitdeals.org/electrumx

Anything after the image name is passed on to electrumx_server.

build and publish

A push to main builds and publishes the image (.gitea/workflows/build.yaml), tagging it three ways: <version>.<sha7> to deploy by, <version> to read, and latest for compose and Watchtower. By hand, when the registry credentials are at hand:

docker build . --file docker/Dockerfile --tag registry.bitdeals.org/electrumx
docker push registry.bitdeals.org/electrumx

A different ElectrumX release is a build argument — use a tag from the upstream repository:

docker build . --file docker/Dockerfile \
  --build-arg ELECTRUMX_VERSION=2.0.0 \
  --tag registry.bitdeals.org/electrumx:2.0.0

Parameters

Container images are configured using parameters passed at runtime. Every variable is ElectrumX's own, so the upstream environment reference applies unchanged; the table lists the ones this image gives a default to.

Parameter Function
-p 127.0.0.1:50001 Electrum protocol over plaintext TCP. No authentication — see "Notes"
-p 127.0.0.1:50002 Electrum protocol over TLS. Served only when SERVICES includes ssl://
-v /data Data directory: the index, and the self-signed certificate if one was generated. Losing it means indexing the chain again
-e DAEMON_URL Required. The daemon's RPC, e.g. http://user:password@bitcoind:8332. Several may be given, comma-separated
-e COIN Coin class. Default: Bitcoin
-e NET Network: mainnet, testnet, testnet4, signet, regtest or mutinynet. Must match the daemon's chain. Default: mainnet
-e DB_ENGINE Index storage. Default: rocksdb, the only engine whose libraries this image carries
-e DB_DIRECTORY Where the index lives. Default: /data
-e SERVICES What to serve, comma-separated. Default: tcp://:50001,rpc://localhost:8000. Keep an rpc:// entry — the health check needs it
-e SSL_CERTFILE, -e SSL_KEYFILE TLS certificate and key. Default: generated as a self-signed pair in the data directory when SERVICES includes ssl://
-e PEER_DISCOVERY Whether to learn other public servers. Default: off — this image is meant for a private indexer
-e PEER_ANNOUNCE Whether to announce this server to the peer network. Default: false
-e CACHE_MB Indexing cache. Default: 1200 (ElectrumX's own). Lower it for a small chain, raise it to speed up an initial mainnet index

Notes

  • There is no authentication. Anyone who reaches 50001 or 50002 can query any address and broadcast transactions. Publish to loopback, or not at all when the clients are containers on the same network.
  • An index from another image is not readable. This one runs rocksdb; lukechilds/electrumx, which it replaces in BitDeals, wrote leveldb. Point the container at an empty volume and let it index — for regtest and testnet this is quick, for mainnet it is a matter of days.
  • The daemon needs txindex=1 and txospenderindex=1. ElectrumX 2.x checks getindexinfo before it serves anything and exits with a RuntimeError naming the missing index — one at a time, so fixing txindex earns you the same message about txospenderindex. With the sibling bitcoind image that is BITCOIND_TXINDEX=1 and BITCOIND_TXOSPENDERINDEX=1; on an existing datadir turning them on means a reindex of the daemon.
  • The daemon must not be pruned. Indexing reads every block; a pruned node fails partway through with an error about a missing block rather than about the configuration.
  • NET is ElectrumX's spelling, not bitcoind's. The daemon calls the networks main, test and regtest; ElectrumX calls them mainnet, testnet and regtest. The entrypoint rejects an unknown value, because the pair is usually configured from one .env and NET=test would otherwise fail deep inside a coin lookup.
  • The container turns healthy only once it is serving, which is after it has caught up with the daemon. An initial mainnet index takes days and the container will be unhealthy for all of it — watch the logs instead; on regtest it is a matter of seconds.
  • A self-signed certificate is generated only if SERVICES asks for TLS and no files are supplied. Clients then have to trust it explicitly. That is the price of ElectrumX refusing to start when ssl:// is requested without a certificate, which is a surprising way to learn you added a port.