ElectrumX takes no command line arguments, instead its behaviour is controlled by environment variables. Only a few are required to be given, the rest will have sensible defaults if not specified. Many of the defaults around resource usage are conservative; I encourage you to review them.
These environment variables are always required:
The path to the database directory. Relative paths should be relative to the parent process working directory. This is the directory of the run script if you use it.
A comma-separated list of daemon URLs. If more than one is provided ElectrumX will initially connect to the first, and failover to subsequent ones round-robin style if one stops working.
The generic form of a daemon URL is:
The following are required if you use the
The path to the electrumx_server script. Relative paths should be relative to the directory of the
The username the server will run as.
These two environment variables are comma-separated lists of individual services.
A service has the general form:
protocol is case-insensitive. The recognised protocols are:
tcp Plaintext TCP sockets ssl SSL-encrypted TCP sockets ws Plaintext websockets wss SSL-encrypted websockets rpc Plaintext RPC
In a services list, a protocol can be specified multiple times, with different hosts or ports. This might be useful for multi-homed hosts, or if you offer both Tor and clearnet services.
host can be a hostname, an IPv4 address, or an IPv6 address enclosed in square brackets.
port is an integer from
Where documented, one or more of protocol, host and port can be omitted, in which case a default value will be assumed.
Here are some examples of valid services:
tcp://host.domain.tld:50001 # Hostname, lowercase protocol, port SSL://188.8.131.52:50002 # An IPv4 address, upper-case protocol, port rpC://localhost # Host as a string, mixed-case protocol, default port ws://[1234:5678:abcd::5601]:8000 # Host as an IPv6 address wss://h3ubaasdlkheryasd.onion:50001 # Host as a Tor ".onion" address rpc://:8000 # Default host, port given host.domain.tld:5151 # Default protocol, hostname, port rpc:// # RPC protocol, default host and port
ElectrumX will not serve any incoming connections until it has fully caught up with your bitcoin daemon. The only exception is local RPC connections, which are served at any time after the server has initialized.
A comma-separated list of services ElectrumX will accept incoming connections for.
This environment variable determines what interfaces and ports the server listens on, so must be set correctly for any connection to the server to succeed. If unset or empty, ElectrumX will not listen for any incoming connections.
protocol can be any recognised protocol.
host defaults to all of the machine’s interfaces, except if the protocol is rpc, when it defaults to
port can only be defaulted for rpc where the default is
On most Unix systems ports below 1024 require elevated privileges so choosing a higher port is advisable. On Debian for example, this can be achieved by installing libcap2-bin package:
sudo apt-get update && sudo apt-get -y install libcap2-bin sudo setcap cap_net_bind_service=+ep /path/to/electrumx_server
Tor onion addresses are invalid in
Here is an example value of the
This serves tcp, ssl, wss on all interfaces on ports 50001, 50002 and 50004 respectively. rpc is served on its default host
localhostand default port
A comma-separated list of services ElectrumX will advertize and other servers in the server network (if peer discovery is enabled), and any successful connection.
This environment variable must be set correctly, taking account of your network, firewall and router setup, for clients and other servers to see how to connect to your server. If not set or empty, no services are advertized.
The rpc protocol, special IP addresses (including private ones if peer discovery is enabled), and
localhostare invalid in
Here is an example value of the
This advertizes tcp, ssl, wss services at
sv.usebsv.comon ports 50001, 50002 and 50004 respectively.
Certificate Authority-signed certificates don’t work over Tor, so you should
only have Tor services` in
REPORT_SERVICES if yours is self-signed.
The filesystem path to your SSL certificate file.
These environment variables are optional:
The Python logging format string to use. Defaults to
The default Python logging level, a case-insensitive string. Useful values are ‘debug’, ‘info’, ‘warning’ and ‘error’.
Set this environment variable to anything non-empty to allow running ElectrumX as root.
Database engine for the UTXO and history database. The default is
leveldb. The other alternative is
rocksdb. You will need to install the appropriate python package for your engine. The value is not case sensitive.
The server donation address reported to Electrum clients. Defaults to empty, which Electrum interprets as meaning there is none.
The path to a banner file to serve to clients in Electrum’s “Console” tab. Relative file paths must be relative to
DB_DIRECTORY. The banner file is re-read for each new client.
You can place several meta-variables in your banner file, which will be replaced before serving to a client.
$SERVER_VERSIONis replaced with the ElectrumX version you are running, such as
$SERVER_SUBVERSIONis replaced with the ElectrumX user agent string. For example,
$DAEMON_VERSIONis replaced with the daemon’s version as a dot-separated string. For example
$DAEMON_SUBVERSIONis replaced with the daemon’s user agent string. For example,
$DONATION_ADDRESSis replaced with the address from the
See here for a script that updates a banner file periodically with useful statistics about fees, last block time and height, etc.
BANNER_FILE(which is also the default) but shown to incoming connections believed to be to your Tor hidden service.
Set to anything non-empty to replace IP addresses in logs with redacted text like
xx.xx.xx.xx:xxx. By default IP addresses will be written to logs.
The number of seconds between printing session statistics to the log. The output is identical to the sessions RPC command except that
ANON_LOGSis honoured. Defaults to 3600. Set to zero to suppress this logging.
The maximum number of blocks to be able to handle in a chain reorganisation. ElectrumX retains some fairly compact undo information for this many blocks in levelDB. The default is a function of
NET; for Bitcoin mainnet it is 200.
The name of an event loop policy to replace the default asyncio policy, if any. At present only
uvloopis accepted, in which case you must have installed the uvloop Python package.
If you are not sure what this means leave it unset.
Set a regular expression to disconnect any client based on their version string. For example to drop versions from 1.0 to 1.2 use the regex
Set to anything non-empty to deny serving clients which do not identify themselves first by issuing the server.version method call with a non-empty client identifier. The connection is dropped on first actual method call. This might help to filter out simple robots. This behavior is off by default.
Resource Usage Limits¶
The following environment variables are all optional and help to limit server resource consumption and prevent simple DoS.
Address subscriptions in ElectrumX are very cheap - they consume about 160 bytes of memory each and are processed efficiently. I feel the two subscription-related defaults below are low and encourage you to raise them.
The maximum number of incoming connections. Once reached, TCP and SSL listening sockets are closed until the session count drops naturally to 95% of the limit. Defaults to 1,000.
The maximum size of an incoming message in bytes, the default is 1,000,000 bytes. Note that the smallest sane/safe value for Bitcoin is ~800,100 bytes, as the largest standard tx can have a weight of 400K but the protocol hex-encodes that, plus there is a few bytes of protocol overhead. Setting this to lower than that would preclude clients from broadcasting txs that could propagate over the network.
The maximum size of a response message to send over the wire, in bytes. Defaults to 1,000,000 (except for AuxPoW coins, which default to 10,000,000). Values smaller than 350,000 are taken as 350,000 because standard Electrum protocol header “chunk” requests are almost that large.
The Electrum protocol has a flaw in that address histories must be served all at once or not at all, an obvious avenue for abuse.
MAX_SENDis a stop-gap until the protocol is improved to admit incremental history requests. Each history entry is approximately 100 bytes, so the default is equivalent to a history limit of around 10,000 entries, which should be ample for most legitimate users. If you use a higher default, bear in mind one client can request history for multiple addresses. Also note that the largest raw transaction you will be able to serve to a client is just under half of
MAX_SEND, as each raw byte becomes 2 hexadecimal ASCII characters on the wire. Very few transactions on Bitcoin mainnet are over 500KB in size.
The server prices each request made to it based upon an estimate of the resources needed to process it. Factors include whether the request uses bitcoind, how much bandwidth it uses, and how hard it hits the databases.
To set a base for the units, a
blockchain.scripthash.subscribe()subscription to an address with a history of 2 or fewer transactions is costed at
1.0before considering the bandwidth consumed.
server.ping()is costed at
As the total cost of a session goes over the soft limit, its requests start to be throttled in two ways. First, the number of requests for that session that the server will process concurrently is reduced. Second, each request starts to sleep a little before being handled.
Before throttling starts, the server will process up to
INITIAL_CONCURRENTrequests concurrently without sleeping. As the session cost ranges from
COST_HARD_LIMIT, concurrency drops linearly to zero and each request’s sleep time increases linearly up to
REQUEST_SLEEPmilliseconds. Once the hard limit is reached, the session is disconnected.
In order that non-abusive sessions can continue to be served, a session’s cost gradually decays over time. Subscriptions have an ongoing servicing cost, so the decay is slower as the number of subscriptions increases.
If a session disconnects, ElectrumX continues to associate its cost with its IP address, so if it immediately reconnects it will re-acquire its previous cost allocation. Moreover, sessions are also grouped together based on their IP address subnets, and cost is accrued for the whole group. What subnet sizes to use can be configured via
SESSION_GROUP_BY_SUBNET_IPV4(by default /24) and
SESSION_GROUP_BY_SUBNET_IPV6(by default /48).
A server operator should experiment with different values according to server loads. It is not necessarily true that e.g. having a low soft limit, decreasing concurrency and increasing sleep will help handling heavy loads, as it will also increase the backlog of requests the server has to manage in memory. It will also give a much worse experience for genuine connections.
The number of bytes, sent and received, by a session that is deemed to cost
The default value
5,000bytes, meaning the bandwidth cost assigned to a response of 100KB is 20. If your bandwidth is cheap you should probably raise this.
An integer number of seconds defaulting to
30. If a request takes longer than this to respond to, either because of request limiting or because the request is expensive, the server rejects it and returns a timeout error to the client indicating that the server is busy.
This can help prevent large backlogs of unprocessed requests building up under heavy load.
An integer number of seconds defaulting to
600. Sessions that have not sent a request for longer than this are disconnected. Properly functioning clients should send a
server.ping()request once roughly 450 seconds have passed since the previous request, in order to avoid disconnection.
In response to the
server.peers.subscribe() RPC call, ElectrumX
will only return peer servers that it has recently connected to and
verified basic functionality.
If you are not running a Tor proxy ElectrumX will be unable to connect to onion server peers, in which case rather than returning no onion peers it will fall back to a hard-coded list.
To give incoming clients a full range of onion servers, you will need to be running a Tor proxy for ElectrumX to use.
ElectrumX will perform peer-discovery by default and announce itself to other peers. If your server is private you may wish to disable some of this.
This environment variable is case-insensitive and defaults to
on, ElectrumX will occasionally connect to and verify its network of peer servers.
off, peer discovery is disabled and a hard-coded default list of servers will be read in and served. If set to
selfthen peer discovery is disabled and the server will only return itself in the peers list.
Set this environment variable to empty to disable announcing itself. If not defined, or non-empty, ElectrumX will announce itself to peers.
If peer discovery is disabled this environment variable has no effect, because ElectrumX only announces itself to peers when doing peer discovery if it notices it is not present in the peer’s returned list.
By default peer discovery happens over the clear internet. Set this to non-empty to force peer discovery to be done via the proxy. This might be useful if you are running a Tor service exclusively and wish to keep your IP address private.
The host where your Tor proxy is running. Defaults to
If you are not running a Tor proxy just leave this environment variable undefined.
The port on which the Tor proxy is running. If not set, ElectrumX will autodetect any proxy running on the usual ports 9050 (Tor), 9150 (Tor browser bundle) and 1080 (socks).
URL to retrieve a list of blacklisted peers. If not set, a coin- specific default is used.
If synchronizing from the Genesis block your performance might change by tweaking the cache size. Cache size is only checked roughly every minute, so the cache can grow beyond the specified size. Moreover, the Python process is often quite a bit fatter than the cache size, because of Python overhead and also because leveldb consumes a lot of memory when flushing. So I recommend you do not set this over 60% of your available physical RAM:
The amount of cache, in MB, to use. The default is 1,200.
A portion of the cache is reserved for unflushed history, which is written out frequently. The bulk is used to cache UTXOs.
Larger caches probably increase performance a little as there is significant searching of the UTXO cache during indexing. However, I don’t see much benefit in my tests pushing this too high, and in fact performance begins to fall, probably because LevelDB already caches, and also because of Python GC.
I do not recommend raising this above 2000.