Skip to content

Run an Electrum server

An Electrum server is an index over a full node that lets Electrum-compatible wallets synchronize without downloading the full blockchain. Operating your own endpoint reduces reliance on a third-party server, but the wallet and server implementations still require careful review.

This page covers standing up the BTCGPU fork of ElectrumX for Bitcoin Gold. The fork is old, so review and test it carefully before exposing a public service.

Who this is for

You already have a synced full node and you want to expose a public Electrum endpoint, or a private one for your own wallet(s).

What you'll build

  • A cloned ElectrumX repository with the BTCGPU-specific patches applied.
  • A systemd unit running ElectrumX as a dedicated electrumx user.
  • A self-signed or publicly trusted TLS certificate on TCP/50002.
  • TLS on TCP/50002 and optional secure WebSocket service on TCP/50003.
  • Verification with electrumx_rpc.py and the official ElectrumG client.

Requirements

Resource Minimum Recommended (public server)
OS Ubuntu 22.04 LTS Ubuntu 22.04 / 24.04 LTS
CPU 2 cores 4+ cores
RAM 4 GB 8 GB
Disk 50 GB (leveldb) + chain 100 GB SSD
Backend A synced bgoldd (v0.17.3) Same host as your node, or LAN-local
Ports 50002 (TLS) 50002 (TLS), optionally 50003 (WSS) inbound

Pin and test the complete stack

The BTCGPU ElectrumX fork and current bgoldd releases evolve independently. Pin both revisions, build a test index, and exercise wallet synchronization and transaction broadcast before exposing the service.

1. Install dependencies

ElectrumX is Python 3.

sudo apt update
sudo apt install -y python3 python3-pip python3-venv libssl-dev

2. Create a dedicated user

sudo useradd --system --home /var/lib/electrumx --shell /usr/sbin/nologin electrumx
sudo mkdir -p /var/lib/electrumx /var/log/electrumx
sudo chown -R electrumx:electrumx /var/lib/electrumx /var/log/electrumx

3. Set up Python venv

sudo -u electrumx -H bash -c '
  cd /var/lib/electrumx
  python3 -m venv venv
  source venv/bin/activate
  pip install --upgrade pip
  pip install aiohttp pylru
  git clone https://github.com/BTCGPU/electrumx.git
  cd electrumx
  pip install -e .
'

The BTCGPU/electrumx repository contains the Bitcoin Gold coin class and network constants. Pin the tested commit in your deployment notes; do not assume configuration examples for newer ElectrumX releases apply unchanged to this fork.

4. Generate a self-signed TLS cert (or use Let's Encrypt)

For private use, a self-signed cert is fine.

sudo openssl req -x509 -nodes -newkey ec -pkeyopt ec_paramgen_curve:secp256k1 \
  -keyout /var/lib/electrumx/electrumx.key \
  -out /var/lib/electrumx/electrumx.crt \
  -days 3650 \
  -subj "/CN=electrum.example.com" \
  -addext "subjectAltName=DNS:electrum.example.com"
sudo chown electrumx:electrumx /var/lib/electrumx/electrumx.{key,crt}
sudo chmod 600 /var/lib/electrumx/electrumx.key

For public use, get a real cert from Let's Encrypt. Certbot needs a port-80 open challenge or DNS-01 challenge.

DNS-01 works without opening an HTTP challenge port

sudo certbot certonly --dns-cloudflare \
  --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
  -d electrum.example.com

5. Configure ElectrumX

sudo tee /etc/electrumx.conf > /dev/null <<'EOF'
# /etc/electrumx.conf
# ----------------------------------------
# Network identity
COIN = BitcoinGold
NET = mainnet

# Backend RPC (your local bgoldd)
DAEMON_URL = http://RPC_USER:CHANGE_ME_LONG_RANDOM@127.0.0.1:8332/
#  ^ replace RPC_USER / CHANGE_ME_LONG_RANDOM with your real rpcuser / rpcpassword

# DB
DB_DIRECTORY = /var/lib/electrumx/db
DB_ENGINE = leveldb

# Services
SERVICES = tcp://127.0.0.1:50001,ssl://0.0.0.0:50002,wss://0.0.0.0:50003

# TLS
SSL_CERTFILE = /var/lib/electrumx/electrumx.crt
SSL_KEYFILE = /var/lib/electrumx/electrumx.key

# Cost
PEER_ANNOUNCE = self
REPORT_SERVICES = ssl://50002,wss://50003
EOF

sudo chmod 600 /etc/electrumx.conf
sudo chown electrumx:electrumx /etc/electrumx.conf

Lock down the RPC password

The DAEMON_URL contains the bgoldd RPC password. Anyone who can read /etc/electrumx.conf can drain the wallet if disablewallet=0. Set chmod 600 and run the service as the dedicated user.

6. systemd unit

sudo tee /etc/systemd/system/electrumx.service > /dev/null <<'EOF'
[Unit]
Description=ElectrumX server (Bitcoin Gold)
After=network-online.target btgd.service
Wants=network-online.target btgd.service

[Service]
User=electrumx
Group=electrumx
EnvironmentFile=/etc/electrumx.conf
ExecStart=/var/lib/electrumx/venv/bin/electrumx_server
Restart=on-failure
RestartSec=10

# Hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=true
ReadWritePaths=/var/lib/electrumx /var/log/electrumx
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now electrumx.service
sudo journalctl -u electrumx.service -f

7. Firewall

Expose only encrypted services. Port 50001 remains available on loopback for local diagnostics.

sudo ufw allow 50002/tcp comment "ElectrumX SSL"
sudo ufw allow 50003/tcp comment "ElectrumX WebSocket"

8. Verification

Local

# Is the process up?
systemctl status electrumx.service

# Are the ports listening?
ss -lntp | grep -E '50001|50002|50003'

# Query the server version over the local plaintext endpoint
echo '{"id":1,"method":"server.version","params":["electrum-test","1.4"]}' | \
  timeout 5 nc -q1 127.0.0.1 50001

With ElectrumG

In ElectrumG, Tools → Network → Server, add a new server:

  • Name: my-electrum
  • Host: electrum.example.com
  • Port: 50002
  • Protocol: SSL

Then right-click the server in the network dialog → "Check connection". A successful connection confirms reachability; independently inspect certificate validation and the reported protocol version.

Over TLS

printf '%s\n' '{"id":1,"method":"server.version","params":["electrum-test","1.4"]}' | \
  timeout 10 openssl s_client -quiet \
    -connect 127.0.0.1:50002 \
    -servername electrum.example.com \
    -CAfile /var/lib/electrumx/electrumx.crt

Electrum uses newline-delimited JSON-RPC over TLS, not HTTP. A valid server.version response confirms the protocol endpoint is responding.

9. Operating

Initial sync

ElectrumX's first run builds the LevelDB index. Completion time varies widely with storage latency, CPU performance, and chain size; monitor the logs and database directory instead of relying on a fixed estimate.

watch -n 60 'ls -la /var/lib/electrumx/db && du -sh /var/lib/electrumx/db'

The db/ size grows monotonically until the node catches up to the tip.

Monitoring

Add a healthcheck (e.g. on a 60-second cron) that hits server.ping over TCP. If it fails three times in a row, restart:

#!/bin/bash
# /usr/local/bin/electrumx-healthcheck
if ! timeout 5 bash -c 'echo > /dev/tcp/127.0.0.1/50001' ; then
    systemctl restart electrumx.service
fi

Logrotate

/var/log/electrumx/*.log is verbose. Cap it.

sudo tee /etc/logrotate.d/electrumx > /dev/null <<'EOF'
/var/log/electrumx/*.log {
    daily
    rotate 7
    compress
    missingok
    notifempty
    copytruncate
}
EOF

Troubleshooting

"Cannot connect to daemon" at startup

The DAEMON_URL is wrong, the bgoldd isn't running, or its bitcoingold.conf doesn't permit the connection. Test with curl:

curl -u RPC_USER:CHANGE_ME_LONG_RANDOM http://127.0.0.1:8332 \
  -H 'Content-Type: application/json' \
  -d '{"id":1,"method":"getblockchaininfo","params":[]}' | jq .

"Address version byte mismatch"

Confirm that COIN=BitcoinGold and NET=mainnet select the BitcoinGold class in the checked-out electrumx/lib/coins.py. That class must use P2PKH version byte 0x26 and P2SH version byte 0x17.

"DB_LOCK: Another instance is using the DB"

Two ElectrumX instances pointing at the same DB_DIRECTORY. Check ps -ef | grep electrumx_server.

"Mempool is full" / "Too many mempool txs"

Inspect both the ElectrumX log and bgold-cli getmempoolinfo. Do not raise memory limits blindly: first confirm that the backend is synchronized, responsive, and compatible with the pinned ElectrumX revision.

"SSL handshake error" from clients

Self-signed cert needs to be added to the client's trust store, OR replace with a Let's Encrypt cert. Don't ship a self-signed cert on a public server.

What to do next

  • Expose a public banner so the official ElectrumG client can auto-discover you. See the BTCGPU ElectrumG docs.
  • Stand up a second instance in a different region (e.g. electrum-eu.example.com and electrum-us.example.com) so wallets can pick the closer one.
  • Combine with Blockbook for a full explorer + Electrum stack.
  • Harden the host following Hardening.