Bitcoin client
Install and run Bitcoin Core (bitcoind), GPG-verify the release, tune bitcoin.conf for a Pi 5 (dbcache, maxmempool), and sync the full blockchain (IBD, initial block download) through Tor.
Bitcoin Core is the reference client for the Bitcoin network. It downloads the entire blockchain, validates every transaction since the genesis block, and from then on holds the authoritative answer to "is this UTXO real?", no third party asked, no trust extended. Everything else in this guide, Electrs, Lightning, the block explorer, is a consumer of this node.
What to expect
Installing bitcoind is a short job. Syncing it is not. On a Pi 5
with a good USB 3 SSD (or NVMe via the M.2 HAT+), the initial block
download takes roughly two to five days. You don't have to sit
with it, start it, check in once a day, come back when
verificationprogress is a hair below 1.
Pi 4 owners
A Pi 4 with 8 GB RAM still gets there, just slower, plan for five to
seven days for the initial sync and keep the dbcache a little lower
(see below). Anything less than 8 GB of RAM will struggle once LND
and Electrs join the party; upgrade if you can.
Create the bitcoin user
bitcoind runs as its own system user. No shell password, no
sudo, if something ever does manage to break out of the daemon, it
lands in a sandbox, not on your admin account.
-
Create the user and add
adminto its group so you can read its files without jugglingsudo:sudo adduser --gecos "" --disabled-password bitcoin sudo adduser admin bitcoin -
Put the
bitcoinuser into thedebian-torgroup so it can read Tor's cookie file and use the control port you set up earlier:sudo adduser bitcoin debian-tor
Create the data directory
Bitcoin Core defaults to ~/.bitcoin inside the user's home. On
this node the chain lives under /data/bitcoin on the SSD, a
separate mount you carved out in System configuration.
A symlink from /home/bitcoin/.bitcoin to that location keeps the
defaults happy while the actual data sits on the fast disk.
sudo mkdir /data/bitcoin
sudo chown bitcoin:bitcoin /data/bitcoin
sudo ln -s /data/bitcoin /home/bitcoin/.bitcoin
sudo chown -h bitcoin:bitcoin /home/bitcoin/.bitcoinDownload and verify Bitcoin Core
Never run a Bitcoin binary you haven't verified. The point of a full node is to trust your own software, which means the software has to be what the developers actually signed.
-
As
admin, drop into/tmp(cleared on every reboot) and pull the binary, the checksum file, and the signature file:cd /tmp wget https://bitcoincore.org/bin/bitcoin-core-30.2/bitcoin-30.2-aarch64-linux-gnu.tar.gz wget https://bitcoincore.org/bin/bitcoin-core-30.2/SHA256SUMS wget https://bitcoincore.org/bin/bitcoin-core-30.2/SHA256SUMS.asc -
Check the checksum of the archive against the reference. The "improperly formatted" warning is about unrelated platforms in the same file, ignore it:
sha256sum --ignore-missing --check SHA256SUMSYou want to see:
bitcoin-30.2-aarch64-linux-gnu.tar.gz: OK -
Bitcoin Core releases are signed by multiple maintainers through the guix.sigs repository. Import all current signing keys in one sweep:
curl -s "https://api.github.com/repositories/355107265/contents/builder-keys" \ | grep download_url \ | grep -oE "https://[a-zA-Z0-9./-]+" \ | while read url; do curl -s "$url" | gpg --import; done -
Verify the checksum file's signatures. You want several
Good signaturelines, one signature alone is not enough:gpg --verify SHA256SUMS.ascSkim the output for multiple lines like:
gpg: Good signature from "..." Primary key fingerprint: ...
Don't skip the signature check
A matching SHA256 only proves the file matches the checksum file. The GPG step is what proves the checksum file itself came from the Bitcoin Core maintainers and not someone who also controls the download server. Verify both, or verify neither.
Install the binaries
If checksum and signature are happy, extract and install:
tar -xvf bitcoin-30.2-aarch64-linux-gnu.tar.gz
sudo install -m 0755 -o root -g root -t /usr/local/bin bitcoin-30.2/bin/*
bitcoin-cli --versionExpected output:
Bitcoin Core RPC client version v30.2.0
Copyright (C) 2009-2026 The Bitcoin Core developersGenerate RPC credentials
Other programs (Electrs, LND, the block explorer) talk to bitcoind
through its RPC interface. Bitcoin Core doesn't store the password
in plaintext, it stores a salted hash. A short Python script ships
with the source tree to generate the config line.
-
As the
bitcoinuser, fetch the helper script:sudo su - bitcoin cd .bitcoin wget https://raw.githubusercontent.com/bitcoin/bitcoin/master/share/rpcauth/rpcauth.py -
Run it with the username
raspiboltand your password [B] from Preparations. Put a leading space in front of the command so bash keeps it out of your shell history, passwords don't belong in~/.bash_history:python3 rpcauth.py raspibolt YourPasswordBThe script prints a line starting with
rpcauth=raspibolt:...$.... Copy it, you'll paste it into the config file next.
Write bitcoin.conf
This config is tuned for a Pi 5 with 8 GB of RAM: a generous dbcache
to accelerate the initial sync, outbound traffic through Tor, ZMQ
ports exposed for LND later on, and RPC locked to localhost.
-
Still as the
bitcoinuser, open the config:nano /home/bitcoin/.bitcoin/bitcoin.conf -
Paste the following. Replace the
rpcauth=line with the onerpcauth.pyjust printed for you:# RaspiBolt: bitcoind configuration # /home/bitcoin/.bitcoin/bitcoin.conf # Daemon server=1 txindex=1 # Network, listen on IPv4 localhost, reach peers over Tor listen=1 listenonion=1 bind=127.0.0.1 proxy=127.0.0.1:9050 # RPC, paste your own line from rpcauth.py rpcauth=<replace-me> rpccookieperms=group # ZMQ for LND and other consumers zmqpubrawblock=tcp://127.0.0.1:28332 zmqpubrawtx=tcp://127.0.0.1:28333 # Electrs gets a whitelisted block-download fast path whitelist=download@127.0.0.1 # OP_RETURN relay limit. Bitcoin Core 30.0 raised the default from 83 to # 100000 bytes. Setting it explicitly keeps this node conservative: it # will not relay or mine transactions whose OP_RETURN data exceeds 83 bytes. # Raise or remove this line if you want to relay inscription-heavy traffic. datacarriersize=83 # Peer connections maxconnections=40 maxuploadtarget=5000 # Memory pool maxmempool=300 # Initial block download tuning (Pi 5, 8 GB RAM) # Reduce dbcache to ~450 after the chain is synced. dbcache=2000 blocksonly=1 -
Lock the file down so only
bitcoinand its group can read it, therpcauthhash isn't exactly a secret, but it's a credential:chmod 640 /home/bitcoin/.bitcoin/bitcoin.conf
Why blocksonly=1 during IBD?
blocksonly=1 tells bitcoind to skip relaying loose transactions
during the initial sync. It cuts bandwidth use significantly while
the node is chewing through history. You'll turn it off after the
sync completes, alongside the dbcache reduction, see the bottom
of this page.
Systemd unit
The node needs to start on boot and stay running, that's what
systemd is for. This unit runs bitcoind as the bitcoin user,
locks it into a few standard hardening primitives, and restarts on
failure with a sensible backoff.
-
Drop back to
admin:exit -
Create the unit file:
sudo nano /etc/systemd/system/bitcoind.service -
Paste:
# RaspiBolt: systemd unit for bitcoind # /etc/systemd/system/bitcoind.service [Unit] Description=Bitcoin daemon After=network-online.target tor.service Wants=network-online.target [Service] ExecStart=/usr/local/bin/bitcoind -daemon \ -pid=/run/bitcoind/bitcoind.pid \ -conf=/home/bitcoin/.bitcoin/bitcoin.conf \ -datadir=/home/bitcoin/.bitcoin \ -startupnotify="systemd-notify --ready" Type=forking PIDFile=/run/bitcoind/bitcoind.pid Restart=on-failure TimeoutSec=300 RestartSec=30 User=bitcoin UMask=0027 RuntimeDirectory=bitcoind RuntimeDirectoryMode=0710 # Hardening PrivateTmp=true ProtectSystem=full NoNewPrivileges=true PrivateDevices=true MemoryDenyWriteExecute=true [Install] WantedBy=multi-user.target -
Enable it (so it runs on boot) and start it now:
sudo systemctl enable bitcoind.service sudo systemctl start bitcoind.service -
Also symlink the data directory into
admin's home sobitcoin-cliworks without a-datadirflag:ln -s /data/bitcoin /home/admin/.bitcoin
Verify it's syncing
-
Check the service is up:
sudo systemctl status bitcoind.serviceYou want
Active: active (running). -
Confirm the cookie file is group-readable, Electrs and LND need this later:
ls -la /home/admin/.bitcoin/.cookieThe mode should be
-rw-r-----with ownerbitcoinand groupbitcoin. -
Ask the running node for its view of the chain:
bitcoin-cli getblockchaininfoEarly on you'll see a low
blocksnumber and averificationprogressfar below 1. That's the initial block download in progress. Check back each day; whenverificationprogressreads0.99999..., the node is caught up. -
To watch it work in real time, tail the debug log (
Ctrl-Cto exit):tail -f /home/admin/.bitcoin/debug.log
Back up any wallet you create
Bitcoin Core on the RaspiBolt is not where you should store
funds, the Electrum server and Sparrow Wallet in the next pages
are. If you do create a wallet here for testing, the file lives at
/data/bitcoin/wallets/<name>/wallet.dat. Copy it to an encrypted
USB stick before you load any real sats into it. The Pi is a node,
not a vault.
Main takeaway: bitcoind is running under its own user, syncing
the chain through Tor, and exposing the RPC and ZMQ surfaces the
next services in this guide will plug into.
After the initial sync
Once verificationprogress clears 0.99999..., trim the dbcache
back to a sensible steady-state value so Electrs and LND have room
to breathe, and turn transaction relay back on so the node earns
its keep on the network.
-
Open the config:
sudo nano /home/bitcoin/.bitcoin/bitcoin.conf -
Comment out the IBD tuning lines:
#dbcache=2000 #blocksonly=1 -
Restart the daemon:
sudo systemctl restart bitcoind
Bitcoin Core now uses its default ~450 MB cache and relays transactions in addition to blocks.
OpenTimestamps client (optional)
Later in this guide you'll verify signatures on LND, Electrs, and other software. Those projects ship OpenTimestamps proofs for their release files, cryptographic evidence that a given file existed before a particular Bitcoin block. Your node can verify those proofs against its own chain data, so you're not trusting a third-party timestamp server.
sudo apt install python3 python3-dev python3-pip python3-setuptools python3-wheel
sudo pip3 install opentimestamps-client --break-system-packages
ots --versionThe --break-system-packages flag is Debian 13's way of telling you
that it prefers packaged installs, in this case, upstream pip is
the only current source for the client, and it's an isolated tool
that does not touch the system Python.
Updating Bitcoin Core later
Upgrades follow the same download-verify-install rhythm as a fresh
install. Always read the release notes
first, some releases change the data format or default behaviour.
The 30.2 token and its derived URL in
lib/versions.ts are the single source of truth in this guide; bump
that file when a new version lands.
cd /tmp
wget https://bitcoincore.org/bin/bitcoin-core-30.2/bitcoin-30.2-aarch64-linux-gnu.tar.gz
wget https://bitcoincore.org/bin/bitcoin-core-30.2/SHA256SUMS
wget https://bitcoincore.org/bin/bitcoin-core-30.2/SHA256SUMS.asc
sha256sum --ignore-missing --check SHA256SUMS
gpg --verify SHA256SUMS.asc
tar -xvf bitcoin-30.2-aarch64-linux-gnu.tar.gz
sudo install -m 0755 -o root -g root -t /usr/local/bin bitcoin-30.2/bin/*
sudo systemctl restart bitcoindOverview
Install Bitcoin Core, Electrs, and a block explorer, then point a desktop wallet at your own node.
Electrum server
Build Electrs from source, index the blockchain for Electrum-protocol wallets, wrap the raw TCP port in TLS with stunnel so Sparrow, Electrum, and hardware wallets can connect privately.

