Add DEPLOY.md: ports, firewall, RPC credentials, SSL, operation

Also fix the COIN default in docs/environment.rst, and refer to the Palladium
node setup by concept instead of by paths of its repository.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
davideandClaude Sonnet 5.5 committed 2026-10-22 15:15:13 +02:00
1 parent 6624403688
commit 3e5d005efe
8 files changed
+174 -13

No files matched your search

+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
```
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 node in palladiumcore/docker, daemon at `palladiumd:2332`.
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`.
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.
+162
View File
@@ -0,0 +1,162 @@
# Deploying plm-electrumx
What to set up to run a Palladium Electrum server with Docker, next to the Palladium node
running in Docker (service `palladiumd` on the Docker network `palladium`).
Quick start is in [README.md](README.md); this file covers ports, security and operation.
## Overview
```
Electrum clients ──50001 (tcp) / 50002 (ssl)──▶ electrumx ──palladiumd:2332 (RPC)──▶ palladiumd ◀── 2333 ──▶ Palladium network
container private "palladium" network container
```
The node and ElectrumX talk over the private Docker network `palladium`. The only things that must be
reachable from outside are the node's P2P port and the Electrum port(s) of this server.
## Node requirements
In `~/.palladium/palladium.conf` (restart the node container after a change):
```ini
server=1
txindex=1 # required: ElectrumX looks up any transaction by id
# prune must NOT be set: ElectrumX reads the whole chain
```
Start the node **before** ElectrumX: it creates the `palladium` network, which `docker-compose.yml` declares
as `external`. If the network is missing, `docker compose up` fails with `network palladium declared as external,
but could not be found`.
## RPC credentials
ElectrumX logs in to the node with `PLM_RPC_USER` / `PLM_RPC_PASSWORD` from `.env`. The defaults written by the node
(`rpcuser=username`) are only fine to try it. For a real server create a user of its own with
the `rpcauth.py` helper that comes with Bitcoin Core-based nodes (Palladium Core included):
```bash
python3 rpcauth.py electrumx # prints the rpcauth= line and the password (shown once)
```
Put the `rpcauth=...` line in `palladium.conf` (and remove `rpcuser`/`rpcpassword`), restart the node, and put the
user and password in `.env`. Anything on the `palladium` network can try to log in, so use a long password.
Keep `.env` private (`chmod 600 .env`); it is ignored by git.
## Ports
| Port | What | Open to | Notes |
| --- | --- | --- | --- |
| **50001/tcp** | Electrum protocol, plain | clients (internet, if the server is public) | published by `docker-compose.yml` |
| **50002/tcp** | Electrum protocol over SSL | clients | optional, needs a certificate (see below); not published by default |
| **2333/tcp** | Palladium P2P (the node) | the internet, inbound | published by the node's compose file |
| 2332/tcp | node RPC | **only the `palladium` network** | never publish or forward it: it can spend wallet funds |
| 28332, 28334, 28335/tcp | node ZMQ | only the `palladium` network | never publish or forward them |
Changing the published port: `ELECTRUMX_TCP_PORT` in `.env` (host side only; the container always listens on 50001).
A server only for yourself (or for other containers) needs no open port: connect to `127.0.0.1:50001`, or join the
`palladium` network and use `electrumx:50001`.
### Firewall
- Docker publishes `ports:` by writing its own firewall rules, which **bypass `ufw` and `firewalld`**. A published
port is open to the internet even if `ufw` denies it. To keep a port private, bind it to an address, for example
`"127.0.0.1:50001:50001"` in `docker-compose.yml`.
- For a public server, allow what you want reachable: `sudo ufw allow 2333/tcp` (node) and the Electrum port(s).
Since Docker bypasses ufw for published ports, this matters mostly for services not run by Docker.
### Router (server behind NAT)
Give the server a fixed LAN address (DHCP reservation) and forward to it:
| External port | Protocol | To | Needed for |
| --- | --- | --- | --- |
| 2333 | TCP | `<server LAN IP>:2333` | the node (optional but recommended: more peers) |
| 50001 | TCP | `<server LAN IP>:50001` | a public Electrum server |
| 50002 | TCP | `<server LAN IP>:50002` | a public Electrum server with SSL |
Never forward 2332 or 28332/28334/28335. A server on a VPS with a public IP opens the ports in the provider's firewall instead.
## SSL (port 50002)
Most Electrum wallets prefer SSL. You need a certificate and key for the host name of the server.
1. Get a certificate, for example with Let's Encrypt (`certbot certonly --standalone -d electrum.example.com`),
or a self-signed one for tests:
```bash
openssl req -x509 -newkey rsa:4096 -nodes -days 3650 -subj "/CN=electrum.example.com" \
-keyout privkey.pem -out fullchain.pem
```
2. Create `docker-compose.override.yml` next to `docker-compose.yml` (compose reads it automatically):
```yaml
services:
electrumx:
environment:
SERVICES: tcp://:50001,ssl://:50002
SSL_CERTFILE: /certs/fullchain.pem
SSL_KEYFILE: /certs/privkey.pem
ports:
- "50002:50002"
volumes:
- /path/to/certs:/certs:ro
```
The container runs as uid 1000: the key must be readable by it (`chown 1000 privkey.pem; chmod 600 privkey.pem`).
With Let's Encrypt, copy the files out of `/etc/letsencrypt/live/...` (they are symlinks into `archive/`), and
copy them again after each renewal.
3. `docker compose up -d`, and open 50002 as in "Ports".
## Announcing a public server
`REPORT_SERVICES` in `.env` is the address other servers and clients are told to use. Set it only for a server that is
reachable from outside, with its public host name (not an IP on a private network, not `localhost`):
```ini
REPORT_SERVICES=tcp://electrum.example.com:50001,ssl://electrum.example.com:50002
```
Peer discovery is on by default (`PEER_DISCOVERY`, `PEER_ANNOUNCE`). `lib/coins.py` has no known Palladium servers yet
(`PEERS = []` in the `Palladium` class), so a new server has nobody to learn the network from. Add the
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`.
## Resources and first start
- 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.
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).
- The database is the `electrumx-db` volume. It is derived from the node, so it can be rebuilt at any time:
`docker compose down -v` deletes it and the next start syncs again. A backup is optional.
- Disk: the node needs `txindex`, so budget for the node's own data too (see the node's README).
## Operation
```bash
docker compose up -d --build # start / update after pulling changes
docker compose logs -f electrumx # follow the log
docker compose ps
docker compose stop # clean shutdown (up to 2 minutes to flush the db)
```
Is it up and synced? The log should end with `synced to height <N>` and the same height as the node
(`docker compose exec palladiumd palladium-cli getblockcount` in the node's compose project).
From the host, a protocol check:
```bash
printf '{"id":1,"method":"server.version","params":["test","1.4"]}\n' | nc -q1 127.0.0.1 50001
```
From another machine, `nc -zv <public IP> 50001` must succeed if the server is meant to be public, and
`nc -zv <public IP> 2332` must fail.
## Troubleshooting
| Symptom | Cause |
| --- | --- |
| `network palladium declared as external, but could not be found` | the node is not running (or its compose file was not started yet) |
| log: connection refused / cannot connect to `palladiumd:2332` | the node is stopped or still starting; check that the node container is running |
| log: `401`/authorization errors | wrong `PLM_RPC_USER` / `PLM_RPC_PASSWORD` in `.env`; the credentials must be the ones in the node's `palladium.conf` |
| errors mentioning `txindex` | `txindex=1` is missing in `palladium.conf` (an index added later is built while the node runs, which takes time) |
| `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 |
| clients cannot connect from outside | port not published/forwarded, firewall, or `SERVICES` does not list that protocol |
+1 -1
View File
@@ -2,7 +2,7 @@
#
# docker compose up -d --build (see docker-compose.yml and README.md)
#
# Runs on the "palladium" network of the node in palladiumcore/docker and reaches it as palladiumd:2332.
# Runs on the "palladium" network of the Palladium node container and reaches it as palladiumd:2332.
FROM python:3.14-trixie AS builder
+6 -7
View File
@@ -8,20 +8,19 @@ Language: Python (>= 3.10)
```
`plm-electrumx` is an [Electrum](https://electrum.org) protocol server for Palladium (PLM), the coin of
[palladiumcore](https://github.com/palladium-coin/palladiumcore). It is a fork of
Palladium Core. It is a fork of
[spesmilo/electrumx](https://github.com/spesmilo/electrumx) that supports Palladium only.
It connects to your Palladium full node and indexes the blockchain, allowing efficient querying of
the history of arbitrary addresses.
## Running
### With Docker (next to the node of palladiumcore)
### With Docker (next to the Palladium node)
ElectrumX joins the `palladium` network created by the node in
[palladiumcore/docker](https://github.com/palladium-coin/palladiumcore/tree/docker-node/docker) and reaches it
ElectrumX joins the Docker network `palladium`, created by the node's compose project, and reaches the node
as `palladiumd:2332`. RPC and ZMQ of the node are not published on the host, so nothing else is exposed.
1. Start the node (`docker compose up -d` in `palladiumcore/docker`). Its `~/.palladium/palladium.conf` needs
1. Start the node (a compose service named `palladiumd` on the network `palladium`). Its `~/.palladium/palladium.conf` needs
`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
(use a dedicated `rpcauth` user for anything public).
@@ -31,7 +30,7 @@ The first start builds the database from the node from genesis, which takes a wh
`docker compose logs -f electrumx`. The database is the `electrumx-db` volume. Electrum clients connect to
TCP port 50001 (`ELECTRUMX_TCP_PORT` in `.env`). 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
`Dockerfile`.
`Dockerfile`. Ports, firewall, SSL, RPC credentials and troubleshooting are in [DEPLOY.md](DEPLOY.md).
### Without Docker
@@ -87,7 +86,7 @@ When merging upstream, resolve modify/delete conflicts on these files by keeping
error to clients.
- The daemon must run with `txindex=1`.
- Same genesis blocks as Bitcoin (mainnet, testnet3, regtest), 80-byte headers, sha256d PoW, segwit.
- Parameters were taken from `src/chainparams.cpp` and `src/chainparamsbase.cpp` of palladiumcore.
- Parameters (address prefixes, ports, genesis hashes) were taken from the Palladium Core chain parameters.
## License
+1 -1
View File
@@ -1,4 +1,4 @@
# ElectrumX for Palladium, next to the node of palladiumcore/docker.
# ElectrumX for Palladium, next to the Palladium node container.
# Start the node first: it creates the "palladium" network. Setup and usage: README.md
services:
electrumx:
+1 -1
View File
@@ -192,7 +192,7 @@ These environment variables are optional:
.. envvar:: COIN
Must be a :attr:`NAME` from one of the :class:`Coin` classes in
`lib/coins.py`_. Defaults to ``Bitcoin``.
`lib/coins.py`_. Defaults to ``Palladium``.
.. envvar:: NET
+1 -1
View File
@@ -29,7 +29,7 @@ import pytest
import electrumx.lib.coins as coins
addresses = [
# addresses and scripts from palladiumcore src/test/data/key_io_valid.json
# valid addresses and their scripts, from the Palladium Core test vectors
(coins.Palladium, "PHrYiyUQTSekTWvVBNMEnSzV1DCB9TGR2P",
"65a16059864a2fdbc7c99a4723a8395bc6f188eb", "0fae27c959f6b69f711a9e"),
(coins.Palladium, "3CMNFxN1oHBc4R1EpboAL5yzHGgE611Xou",
+1 -1
View File
@@ -1,4 +1,4 @@
# Tests of the Palladium coin classes (parameters from palladiumcore src/chainparams.cpp)
# Tests of the Palladium coin classes (parameters of the Palladium Core chain params)
import pytest