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:
1 parent
6624403688
commit
3e5d005efe
8 files changed
+174
-13
No files matched your search
@@ -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.
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,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
|
||||
|
||||
|
||||
Reference in new issue
Block a user