Files
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

137 lines
6.3 KiB
Markdown

# Intro
> Русская версия: [README.ru-RU.md](README.ru-RU.md)
[ElectrumX](https://github.com/spesmilo/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
```yaml
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
```sh
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:
```sh
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](https://github.com/spesmilo/electrumx/tags):
```sh
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](https://electrumx-spesmilo.readthedocs.io/en/latest/environment.html)
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](https://git.bitdeals.org/private/bitcoind) 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.