Why run your own Electrum server
Sparrow, Electrum, BlueWallet and most hardware-wallet companions talk the Electrum protocol: the wallet sends the server its script hashes and the server answers with balances and history. A public server therefore learns every address in your wallet, when you open it, and from which IP. Running Bitcoin Core yourself does not fix that unless the wallet also talks to your own index, which is what electrs or Fulcrum provide.
A VPS makes sense when several wallets or people need the server, when you want it reachable as an onion service from anywhere, or when your home connection cannot hold an archival node. It comes with one large caveat, which is the next section.
Disk sizing: an Electrum server needs the whole chain
Neither electrs nor Fulcrum works against a pruned node. Both build their index by reading every block, and both keep answering history queries from the full block files. Here is where the space goes, in October 2026.
| Component | Disk | Notes |
|---|---|---|
| Bitcoin Core block files | about 800 GB | blk*.dat and rev*.dat; the electrs documentation measured 802 GB in July 2026. Grows 60 to 80 GB a year. |
| Chainstate and indexes | 15 GB | UTXO set plus block index. txindex is not required by either server; leave it off to save another 60 GB or so. |
| electrs 0.12 index | 56 GB, 110 GB peak | About 7 percent of the block files after compaction, up to 14 percent during it. The upgrade notes ask for 120 GB free. |
| Fulcrum database | about 130 GB | Faster for busy wallets and public use, but more than twice the disk of electrs. |
| OS, logs, headroom | 10 GB plus | Ubuntu 24.04 base image, journald, Tor state. |
That is roughly 900 GB with electrs and more than a terabyte with Fulcrum. The 160 GB, 240 GB and 360 GB plans cannot hold an unpruned chain, full stop. The only plan that fits mainnet with electrs is BVG63 (48 dedicated vCPU, 192 GB RAM, 960 GB NVMe, from $1,550/mo in Europe), and even there the headroom is thin: about 60 GB after the index settles, which the chain eats in under a year. Fulcrum does not fit with any margin.
Be clear-eyed about whether you need this. If the goal is privacy for your own two or three wallets, a pruned Bitcoin Core on an 80 GB plan with Sparrow connected directly to Core RPC over an SSH tunnel gets you most of the way for a fraction of the price; it is not an Electrum server, but it keeps your addresses off public servers. If you need the Electrum protocol for many wallets, a shop, or a mempool explorer, the rest of this guide assumes the 960 GB plan and electrs. Because terms are prepaid in days, you can also rent it for a week to build and test before committing to a month.
Prepare the server
Everything below assumes a fresh Ubuntu 24.04 image and a root shell (prefix sudo if you created a user). Patch first, then lock down SSH and the firewall before anything else is listening.
apt update && apt full-upgrade -y
apt install -y ufw unattended-upgrades curl gnupg
# SSH: keys only. Put your public key in /root/.ssh/authorized_keys first and
# confirm you can log in with it before disabling passwords.
cat > /etc/ssh/sshd_config.d/00-keys-only.conf <<'EOF'
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password
EOF
sshd -t && systemctl restart ssh
# Firewall: deny everything inbound except SSH for now.
ufw default deny incoming
ufw default allow outgoing
ufw allow OpenSSH
ufw --force enableBitcoin Core: unpruned, with the REST interface on
Install Bitcoin Core as described in the Bitcoin node guide on this site (verify SHA256SUMS against the guix.sigs builder keys, install, create the bitcoin user and unit), using 31.1 or newer: electrs 0.12 requires Bitcoin Core 31 or later because it reads blocks through new REST endpoints instead of the P2P port. With 192 GB of RAM you can give initial sync a very large dbcache and lower it afterwards.
# /etc/bitcoin/bitcoin.conf
server=1
rest=1
prune=0
txindex=0
dbcache=16000 # for initial sync on 192 GB RAM; lower to 2000 afterwards
maxconnections=60
listen=1
rpcbind=127.0.0.1
rpcallowip=127.0.0.1
rpccookieperms=group # lets the electrs user read .cookiesystemctl restart bitcoind
# Wait for verificationprogress to reach 1.0 before starting electrs.
watch -n 60 "sudo -u bitcoin bitcoin-cli -conf=/etc/bitcoin/bitcoin.conf -datadir=/var/lib/bitcoind getblockchaininfo | grep -E '\"(blocks|headers|verificationprogress|size_on_disk)\"'"On dedicated cores with NVMe the initial sync takes well under a day. size_on_disk at the end is your real number for the block files; compare it against the table above before you start the index.
Build and run electrs
electrs is distributed as source. Ubuntu 24.04’s packaged cargo is too old for the 1.85 minimum, so install the toolchain with rustup for a build user, build the tagged release with --locked, and copy the single resulting binary into /usr/local/bin. The build pulls in RocksDB and takes ten to twenty minutes.
apt install -y build-essential libclang-dev git
useradd --system --home-dir /var/lib/electrs --shell /usr/sbin/nologin electrs
install -d -m 0750 -o electrs -g electrs /var/lib/electrs
usermod -aG bitcoin electrs
# Build as an unprivileged user with its own Rust toolchain.
useradd -m build
su - build -c 'curl --proto "=https" --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y'
su - build -c 'git clone https://github.com/romanz/electrs && cd electrs && git checkout v0.12.0 && git verify-tag v0.12.0 || true'
su - build -c 'cd electrs && ~/.cargo/bin/cargo build --locked --release'
install -m 0755 -o root -g root /home/build/electrs/target/release/electrs /usr/local/bin/electrs
electrs --versionThe maintainer signs release tags; import the key listed in the repository’s documentation first if you want git verify-tag to pass rather than merely print a warning. Then write the config file and a unit. electrs listens on localhost only; TLS and Tor come from nginx and tor in the next section.
cat > /etc/electrs.toml <<'EOF'
network = "bitcoin"
daemon_dir = "/var/lib/bitcoind"
daemon_rpc_addr = "127.0.0.1:8332"
cookie_file = "/var/lib/bitcoind/.cookie"
db_dir = "/var/lib/electrs/db"
electrum_rpc_addr = "127.0.0.1:50001"
monitoring_addr = "127.0.0.1:4224"
log_filters = "INFO"
EOF
chown root:electrs /etc/electrs.toml && chmod 0640 /etc/electrs.toml
cat > /etc/systemd/system/electrs.service <<'EOF'
[Unit]
Description=electrs Electrum server
Requires=bitcoind.service
After=bitcoind.service
[Service]
Type=simple
User=electrs
Group=electrs
ExecStart=/usr/local/bin/electrs --conf /etc/electrs.toml
Restart=on-failure
RestartSec=30
TimeoutStopSec=600
LimitNOFILE=65536
PrivateTmp=true
ProtectSystem=full
ProtectHome=true
NoNewPrivileges=true
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now electrs
journalctl -u electrs -f # "indexed N blocks" lines until it reaches the tipThe initial index took about two hours on a six-core desktop in the project’s own measurements; expect similar on dedicated vCPUs. If you would rather run Fulcrum, download the Linux tarball and the shasums.txt plus its .asc signature from the Fulcrum releases page, import Calin Culianu’s key from the Electron-Cash keys-n-hashes repository (fingerprint D465 135F 97D0 047E 18E9 9DC3 2181 0A54 2031 C02C), verify, and use a config with datadir, bitcoind = 127.0.0.1:8332, rpccookie, tcp = 127.0.0.1:50001 and peering = false. Fulcrum can serve TLS itself; electrs cannot, hence nginx below.
TLS with nginx and a Tor onion service
Wallets expect either TLS on port 50002 or an onion address. nginx’s stream module terminates TLS and forwards to electrs on localhost; a self-signed certificate is fine because Sparrow and Electrum pin the certificate on first connect. For Tor there is no need for TLS at all: the hidden service points straight at the plaintext port.
apt install -y nginx libnginx-mod-stream tor
install -d -m 0750 -o root -g root /etc/nginx/certs
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes -days 3650 \
-subj "/CN=electrs" -keyout /etc/nginx/certs/electrs.key -out /etc/nginx/certs/electrs.crt
cat > /etc/nginx/modules-enabled/60-electrs-stream.conf <<'EOF'
stream {
upstream electrs { server 127.0.0.1:50001; }
server {
listen 50002 ssl;
listen [::]:50002 ssl;
proxy_pass electrs;
ssl_certificate /etc/nginx/certs/electrs.crt;
ssl_certificate_key /etc/nginx/certs/electrs.key;
ssl_protocols TLSv1.2 TLSv1.3;
}
}
EOF
nginx -t && systemctl reload nginx
cat >> /etc/tor/torrc <<'EOF'
HiddenServiceDir /var/lib/tor/electrs/
HiddenServiceVersion 3
HiddenServicePort 50001 127.0.0.1:50001
EOF
systemctl restart tor
cat /var/lib/tor/electrs/hostname
# Clearnet TLS port: open it only to the addresses that will use it.
ufw allow from YOUR.HOME.IP.ADDR to any port 50002 proto tcpConnect Sparrow and Electrum
In Sparrow, open Preferences, Server, choose Private Electrum, and enter ssl://YOUR.SERVER.IP:50002 (accept the certificate when prompted) or the onion address with port 50001 and no SSL; Sparrow uses its bundled Tor when it sees an onion address and no proxy is configured. Electrum from the command line works the same way.
# Electrum, clearnet TLS, pinned to this one server:
electrum --oneserver --server YOUR.SERVER.IP:50002:s
# Electrum over Tor to the onion service (Tor running locally on 9050):
electrum --oneserver --server YOURONIONADDRESS.onion:50001:t --proxy socks5:127.0.0.1:9050The first history query for a large, old wallet can take tens of seconds on electrs because it scans the block files; subsequent queries are fast. If that matters to you, that is the argument for Fulcrum and its larger index.
Operate: disk, upgrades, backups
df -h /var/lib/bitcoind /var/lib/electrs
curl -s http://127.0.0.1:4224/metrics | grep -v '^#' | head -40 # Prometheus metrics
journalctl -u electrs --since "1 hour ago" | grep -iE 'error|warn'
sudo -u bitcoin bitcoin-cli -conf=/etc/bitcoin/bitcoin.conf -datadir=/var/lib/bitcoind getblockchaininfo | grep size_on_diskDisk is the thing to watch; set yourself a reminder to check df monthly, because the chain grows whether you look or not. Upgrades: rebuild electrs from the new tag and restart. Major releases occasionally change the index format and reindex from scratch, which is why the documentation asks for 120 GB free; read the upgrade notes before pulling. Bitcoin Core upgrades follow the Bitcoin node guide. There is nothing to back up: the chain and the index are both reproducible, so the automated backups add-on buys you nothing here.
Which plan to pick
For a mainnet Electrum server with electrs, the only plan with enough NVMe is BVG63 (48 dedicated vCPU, 192 GB RAM, 960 GB, from $1,550/mo in Europe, available in all six locations), and you should expect to outgrow it within a year. For development against testnet4 or signet, or for a pruned Core that Sparrow talks to directly, an 80 GB plan from $18/mo does the job. Configure a server, pay in Bitcoin for the number of days you need, and the root credentials arrive by magic link.