Docker: keep data in ~/.plm-electrumx (bind mount) instead of named volumes

db/ is the database, ssl/ the certificate; ELECTRUMX_DATADIR, PLM_UID and
PLM_GID configure it like the node's ~/.palladium. The entrypoint fails with a
clear message if a data directory is not writable.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
davideandClaude Sonnet 5.5 committed 2026-10-22 15:38:04 +02:00
1 parent c2dcff5cc8
commit 419ff90859
6 files changed
+52 -24

No files matched your search

+7 -1
View File
@@ -6,7 +6,13 @@ PLM_RPC_PASSWORD=change-me
#REPORT_SERVICES=tcp://electrum.example.com:50001 #REPORT_SERVICES=tcp://electrum.example.com:50001
#ELECTRUMX_TCP_PORT=50001 #ELECTRUMX_TCP_PORT=50001
# SSL (port 50002): on by default, self-signed certificate generated once and kept in the electrumx-ssl volume. # Data directory of the host: db/ (database) and ssl/ (certificate). Create it first: mkdir -p ~/.plm-electrumx/db ~/.plm-electrumx/ssl
#ELECTRUMX_DATADIR=~/.plm-electrumx
# owner of the data directory, if it is not user 1000
#PLM_UID=1000
#PLM_GID=1000
# SSL (port 50002): on by default, self-signed certificate generated once and kept in ssl/ of the data directory.
#SSL_ENABLED=true #SSL_ENABLED=true
# name (or IP) of the server, written in the generated certificate # name (or IP) of the server, written in the generated certificate
#SSL_HOSTNAME=electrum.example.com #SSL_HOSTNAME=electrum.example.com
+1 -1
View File
@@ -22,7 +22,7 @@ DB_ENGINE=rocksdb DB_DIRECTORY=... DAEMON_URL=http://user:pass@host:port/ electr
electrumx_rpc getinfo # talk to a running server via local RPC electrumx_rpc getinfo # talk to a running server via local RPC
``` ```
Docker: `docker compose up -d --build` (root `Dockerfile`, `docker-compose.yml`, `.env` from `.env.example`) runs the server on the external `palladium` network of the Palladium node container, daemon at `palladiumd:2332`. `docker-entrypoint.sh` sets up SSL: it uses `SSL_CERTFILE`/`SSL_KEYFILE` if given, else the self-signed certificate in the `electrumx-ssl` volume, generating it only if missing (never overwrite it: clients pin it), and sets `SERVICES`. Docker: `docker compose up -d --build` (root `Dockerfile`, `docker-compose.yml`, `.env` from `.env.example`) runs the server on the external `palladium` network of the Palladium node container, daemon at `palladiumd:2332`. `docker-entrypoint.sh` sets up SSL: it uses `SSL_CERTFILE`/`SSL_KEYFILE` if given, else the self-signed certificate in `ssl/` of the data directory (`~/.plm-electrumx`, bind-mounted), generating it only if missing (never overwrite it: clients pin it), and sets `SERVICES`.
Configuration is entirely via environment variables, parsed in `src/electrumx/server/env.py` (documented in `docs/environment.rst`). `DB_ENGINE` is mandatory in 2.0 (`leveldb` or `rocksdb`). Python >=3.10; free-threaded 3.14t is experimental. Configuration is entirely via environment variables, parsed in `src/electrumx/server/env.py` (documented in `docs/environment.rst`). `DB_ENGINE` is mandatory in 2.0 (`leveldb` or `rocksdb`). Python >=3.10; free-threaded 3.14t is experimental.
+25 -13
View File
@@ -87,7 +87,7 @@ addresses and balances unencrypted.
`docker-entrypoint.sh` (the entrypoint of the image) does this at every start: `docker-entrypoint.sh` (the entrypoint of the image) does this at every start:
1. If you gave your own certificate (`SSL_CERTFILE` and `SSL_KEYFILE`, see below), it uses that. 1. If you gave your own certificate (`SSL_CERTFILE` and `SSL_KEYFILE`, see below), it uses that.
2. Otherwise it looks for `/var/lib/electrumx-ssl/server.crt` and `server.key`, in the `electrumx-ssl` volume. 2. Otherwise it looks for `server.crt` and `server.key` in `~/.plm-electrumx/ssl` (`/var/lib/electrumx-ssl` in the container).
- **They exist: they are used as they are, never overwritten.** - **They exist: they are used as they are, never overwritten.**
- **They do not exist (first start): a self-signed certificate valid 10 years is generated** for `SSL_HOSTNAME` - **They do not exist (first start): a self-signed certificate valid 10 years is generated** for `SSL_HOSTNAME`
and saved there. If only one of the two files exists, the container stops with an error instead of overwriting it. and saved there. If only one of the two files exists, the container stops with an error instead of overwriting it.
@@ -111,15 +111,15 @@ the wallet saves the certificate, and from then on it refuses a different one (a
man-in-the-middle cannot take over later. The fields of the certificate (name, country, ...) are not checked by the man-in-the-middle cannot take over later. The fields of the certificate (name, country, ...) are not checked by the
client, only the expiry date. Consequences: client, only the expiry date. Consequences:
- **Keep the certificate.** It is in the `electrumx-ssl` volume, separate from the database on purpose: the database - **Keep the certificate.** It is in `~/.plm-electrumx/ssl`, separate from the database (`~/.plm-electrumx/db`) on
can be deleted and rebuilt at any time (`docker volume rm <project>_electrumx-db`), the certificate should not be. purpose: the database can be deleted and rebuilt at any time, the certificate should not be. If `ssl/` is deleted,
`docker compose down -v` deletes **both** volumes, and after that a new certificate is generated and every client a new certificate is generated and every client that saved the old one refuses to connect.
that saved the old one refuses to connect. - **Back it up** by copying the folder (it contains the private key: keep it private):
- **Back it up** while the container runs:
```bash ```bash
docker compose cp electrumx:/var/lib/electrumx-ssl ./ssl-backup # contains the private key: keep it private cp -a ~/.plm-electrumx/ssl /safe/place/plm-electrumx-ssl
``` ```
To restore it, put the two files somewhere on the host and use them as "your own certificate" below. To restore it, copy the two files (`server.crt`, `server.key`) back into `~/.plm-electrumx/ssl` before the first
start, or use them as "your own certificate" below.
- If it expires or is lost, clients that saved it must be told to forget it, or the server must get a new name. - If it expires or is lost, clients that saved it must be told to forget it, or the server must get a new name.
Generated certificates last 10 years, so expiry is rarely the problem. Generated certificates last 10 years, so expiry is rarely the problem.
- Whether a wallet accepts a self-signed certificate depends on the wallet. Electrum does (trust on first use); - Whether a wallet accepts a self-signed certificate depends on the wallet. Electrum does (trust on first use);
@@ -173,14 +173,25 @@ Peer discovery is on by default (`PEER_DISCOVERY`, `PEER_ANNOUNCE`). `lib/coins.
servers you know there (format: `'host s t'`, for example `'electrum.example.com s50002 t50001'`) and rebuild, or servers you know there (format: `'host s t'`, for example `'electrum.example.com s50002 t50001'`) and rebuild, or
keep the server private with `PEER_DISCOVERY=off` / `PEER_DISCOVERY=self`. keep the server private with `PEER_DISCOVERY=off` / `PEER_DISCOVERY=self`.
## Resources and first start ## Data directory and first start
Create the data directory as the user that runs Docker, before the first start (otherwise Docker creates it as root and
the container cannot write; the log then says `ERROR: ... is not writable`):
```bash
mkdir -p ~/.plm-electrumx/db ~/.plm-electrumx/ssl
```
The container runs as uid/gid 1000 (the first user of most hosts). For another user set `PLM_UID` / `PLM_GID` in `.env`.
To keep the data elsewhere, set `ELECTRUMX_DATADIR` in `.env`.
- On the first start ElectrumX builds its database from the node, from genesis. With the chain at about 542,000 blocks - On the first start ElectrumX builds its database from the node, from genesis. With the chain at about 542,000 blocks
it took roughly a minute on a development machine, ending at about 230 MB of database and 0.5 GB of RAM. it took roughly a minute on a development machine, ending at about 230 MB of database and 0.5 GB of RAM.
The database grows with the chain. The database grows with the chain.
- `CACHE_MB` in `.env` is the memory used for caching during the sync (default in `docker-compose.yml`: 1200). - `CACHE_MB` in `.env` is the memory used for caching during the sync (default in `docker-compose.yml`: 1200).
- The database is the `electrumx-db` volume. It is derived from the node, so it can be rebuilt at any time: - The data directory is `~/.plm-electrumx` (`ELECTRUMX_DATADIR`): `db/` is the database, `ssl/` the certificate.
`docker compose down -v` deletes it and the next start syncs again. A backup is optional. The database is derived from the node, so it can be rebuilt at any time: stop the container, delete `db/` and start
again (it syncs again). A backup of it is optional; keep a backup of `ssl/`.
- Disk: the node needs `txindex`, so budget for the node's own data too (see the node's README). - Disk: the node needs `txindex`, so budget for the node's own data too (see the node's README).
## Operation ## Operation
@@ -214,5 +225,6 @@ From another machine, `nc -zv <public IP> 50001` must succeed if the server is m
| `blockchain.outpoint.subscribe` or package broadcast return a daemon error | expected: Palladium Core is based on Bitcoin Core 0.19 and does not have these RPCs | | `blockchain.outpoint.subscribe` or package broadcast return a daemon error | expected: Palladium Core is based on Bitcoin Core 0.19 and does not have these RPCs |
| the server stays at an old height | the node is not synced; ElectrumX only follows the node | | the server stays at an old height | the node is not synced; ElectrumX only follows the node |
| clients cannot connect from outside | port not published/forwarded, firewall, or `SERVICES` does not list that protocol | | clients cannot connect from outside | port not published/forwarded, firewall, or `SERVICES` does not list that protocol |
| container restarts at once, log says `ERROR: ... SSL_CERTFILE` | your own certificate is not mounted or not readable by uid 1000, only one of `SSL_CERTFILE`/`SSL_KEYFILE` is set, or only one of the generated files exists in the `electrumx-ssl` volume | | container stops at once, log says `ERROR: ... is not writable` | the data directory belongs to another user (or to root, if Docker created it): `chown -R $(id -u):$(id -g) ~/.plm-electrumx`, or set `PLM_UID`/`PLM_GID` |
| a wallet refuses the server after it worked | the certificate changed (for example after `docker compose down -v`); the wallet saved the old one | | container restarts at once, log says `ERROR: ... SSL_CERTFILE` | your own certificate is not mounted or not readable by uid 1000, only one of `SSL_CERTFILE`/`SSL_KEYFILE` is set, or only one of the generated files exists in `~/.plm-electrumx/ssl` |
| a wallet refuses the server after it worked | the certificate changed (for example `ssl/` was deleted); the wallet saved the old one |
+6 -3
View File
@@ -24,12 +24,15 @@ as `palladiumd:2332`. RPC and ZMQ of the node are not published on the host, so
`server=1` and `txindex=1` (no `prune`). `server=1` and `txindex=1` (no `prune`).
2. `cp .env.example .env` and set `PLM_RPC_USER` / `PLM_RPC_PASSWORD` to the RPC credentials of that file 2. `cp .env.example .env` and set `PLM_RPC_USER` / `PLM_RPC_PASSWORD` to the RPC credentials of that file
(use a dedicated `rpcauth` user for anything public). (use a dedicated `rpcauth` user for anything public).
3. `docker compose up -d --build` 3. Create the data directory as your user: `mkdir -p ~/.plm-electrumx/db ~/.plm-electrumx/ssl`
(`ELECTRUMX_DATADIR` in `.env` changes it). The container runs as uid/gid 1000; for another user set
`PLM_UID` / `PLM_GID` in `.env`.
4. `docker compose up -d --build`
The first start builds the database from the node from genesis, which takes a while; follow it with The first start builds the database from the node from genesis, which takes a while; follow it with
`docker compose logs -f electrumx`. The database is the `electrumx-db` volume. Electrum clients connect to `docker compose logs -f electrumx`. The data directory has `db/` (the database, rebuilt from the node if deleted) and `ssl/` (the certificate). Electrum clients connect to
TCP port 50001 (`ELECTRUMX_TCP_PORT` in `.env`) and SSL port 50002 (`ELECTRUMX_SSL_PORT`). SSL is on by default: TCP port 50001 (`ELECTRUMX_TCP_PORT` in `.env`) and SSL port 50002 (`ELECTRUMX_SSL_PORT`). SSL is on by default:
a self-signed certificate is generated on the first start, kept in the `electrumx-ssl` volume and reused on every a self-signed certificate is generated on the first start, kept in `~/.plm-electrumx/ssl` and reused on every
later start (or use your own, see [DEPLOY.md](DEPLOY.md)). To announce a public server to the network, set later start (or use your own, see [DEPLOY.md](DEPLOY.md)). To announce a public server to the network, set
`REPORT_SERVICES` in `.env`. Settings are in `.env` and `docker-compose.yml`; the image defaults are in the `REPORT_SERVICES` in `.env`. Settings are in `.env` and `docker-compose.yml`; the image defaults are in the
`Dockerfile`. Ports, firewall, SSL, RPC credentials and troubleshooting are in [DEPLOY.md](DEPLOY.md). `Dockerfile`. Ports, firewall, SSL, RPC credentials and troubleshooting are in [DEPLOY.md](DEPLOY.md).
+6 -6
View File
@@ -20,16 +20,16 @@ services:
ports: ports:
- "${ELECTRUMX_TCP_PORT:-50001}:50001" - "${ELECTRUMX_TCP_PORT:-50001}:50001"
- "${ELECTRUMX_SSL_PORT:-50002}:50002" - "${ELECTRUMX_SSL_PORT:-50002}:50002"
# data directory of the host (like ~/.palladium for the node): db/ is the database (can be rebuilt from the node),
# ssl/ the certificate (keep it, clients pin it). Create it first, see README.md
volumes: volumes:
- electrumx-db:/var/lib/electrumx - ${ELECTRUMX_DATADIR:-~/.plm-electrumx}/db:/var/lib/electrumx
- electrumx-ssl:/var/lib/electrumx-ssl # the certificate: keep it, clients pin it - ${ELECTRUMX_DATADIR:-~/.plm-electrumx}/ssl:/var/lib/electrumx-ssl
# owner of the data directory: PLM_UID/PLM_GID if it is not user 1000
user: "${PLM_UID:-1000}:${PLM_GID:-1000}"
stop_grace_period: 2m # lets the server flush the db on shutdown stop_grace_period: 2m # lets the server flush the db on shutdown
networks: [palladium] networks: [palladium]
volumes:
electrumx-db:
electrumx-ssl:
networks: networks:
palladium: palladium:
name: palladium name: palladium
+7
View File
@@ -16,6 +16,13 @@ SSL_HOSTNAME="${SSL_HOSTNAME:-electrumx}"
log() { echo "entrypoint: $*"; } log() { echo "entrypoint: $*"; }
for dir in "$DB_DIRECTORY" "$SSL_DIR"; do
if [ ! -w "$dir" ]; then
log "ERROR: $dir is not writable by uid $(id -u). Create the data directory on the host as that user, or set PLM_UID/PLM_GID (see README.md)." >&2
exit 1
fi
done
case "$SSL_ENABLED" in case "$SSL_ENABLED" in
true|TRUE|True|1|yes|on) true|TRUE|True|1|yes|on)
if [ -n "${SSL_CERTFILE:-}" ] || [ -n "${SSL_KEYFILE:-}" ]; then if [ -n "${SSL_CERTFILE:-}" ] || [ -n "${SSL_KEYFILE:-}" ]; then