Run an Electrum server¶
An Electrum server is a thin index over a full node that lets Electrum (and ElectrumG) wallets sync instantly without downloading the blockchain. It's the right layer to operate if you want users to be able to use Bitcoin Gold (BTG) on phones and lightweight wallets without trusting a third-party server.
This page covers standing up ElectrumX for Bitcoin Gold (BTG). ElectrumX is the most widely deployed Electrum server family on Bitcoin-fork networks and is what electrumx-eu.btgofficial.org:50002 / electrumx-us.btgofficial.org:50002 run.
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
systemdunit running ElectrumX as a dedicatedelectrumxuser. - A self-signed or Let's Encrypt TLS certificate on TCP/50002.
- TCP/50001 (plaintext) and TCP/50003 (WebSocket) optionally exposed.
- Verification with
electrumx_rpc.pyand 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 | 50001 (tcp), 50002 (ssl) | 50001, 50002, 50003 (ws) inbound |
Backend compatibility
ElectrumX expects a Bitcoin Core-compatible RPC. The BTCGPU fork of bgoldd (v0.17.3) is fully compatible at the RPC level — the relevant calls (getblock, getblockhash, getblockheader, getrawtransaction, getmempool, decoderawtransaction) are unchanged.
1. Install dependencies¶
ElectrumX is Python 3.
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/Electrum-Coin/ElectrumX-Bitcoin Gold (BTG).git
cd ElectrumX-Bitcoin Gold (BTG)
pip install -e .
'
The ElectrumX-Bitcoin Gold (BTG) repository is a community-maintained fork of ElectrumX with the Bitcoin Gold (BTG)-specific constants pre-configured (genesis hash, address prefix, default ports, coincurve-based address verification). Pin the commit in your deployment notes.
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 challenge is cleaner for a server with only 50001/50002 open
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://explorer:SWbeR6SkQ4cP3BVPNetr@127.0.0.1:8332/
# ^ replace explorer / SWbeR6SkQ4cP3BVPNetr with your real rpcuser / rpcpassword
# DB
DB_DIRECTORY = /var/lib/electrumx/db
DB_ENGINE = leveldb
# Services
SERVICES = tcp://0.0.0.0: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 = tcp://50001,ssl://50002
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¶
Open the three ports you advertised in SERVICES.
sudo ufw allow 50001/tcp comment "ElectrumX TCP"
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'
# Banner (always returns the same JSON on first connect)
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(SSL) or50001(TCP) - Protocol:
SSLorTCP
Then right-click the server in the network dialog → "Check connection". A green light + version banner confirms the server is reachable and the TLS chain is valid.
With curl over SSL¶
curl --cacert /var/lib/electrumx/electrumx.crt --resolve electrum.example.com:50002:127.0.0.1 \
-s https://electrum.example.com:50002 \
-H 'Content-Type: application/json' \
-d '{"id":1,"method":"server.ping","params":[]}'
The ElectrumX 1.16.0 JSON-RPC over TCP/SSL is the same protocol regardless of coin.
9. Operating¶
Initial sync¶
ElectrumX's first run builds the leveldb index. On 165 GB of blocks, expect 12–24 hours of catch-up.
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 explorer:SWbeR6SkQ4cP3BVPNetr http://127.0.0.1:8332 \
-H 'Content-Type: application/json' \
-d '{"id":1,"method":"getblockchaininfo","params":[]}' | jq .
"Address version byte mismatch"¶
The NET = mainnet and COIN = BitcoinGold constants are wrong. Confirm the address prefix in /var/lib/electrumx/venv/lib/python3.10/site-packages/electrumx_btg/lib/coins.py (or wherever the fork defines them) matches Bitcoin Gold (BTG)'s G (P2PKH) / A (P2SH).
"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"¶
bgoldd's mempool is filling up. ElectrumX asks for the full mempool on every poll. Either:
- Increase
maxmempoolinbitcoingold.conf(default 300 MB). - Set
MAX_SEND=1000000inelectrumx.confto limit what ElectrumX forwards.
"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.comandelectrum-us.example.com) so wallets can pick the closer one. - Combine with Blockbook for a full explorer + Electrum stack.
- Harden the host following Hardening.