How to Run a Bitcoin Node
Learn to Build a verifiable, Tor‑ready Bitcoin Node stack
You don’t outsource freedom. You build it.
This guide is your path to running Bitcoin like a sovereign operator: auditable, verifiable, private by default. No app store gatekeepers. No waiting for Start9 or Umbrel to ship an update. You decide what runs, and why - because you understand it.
What you’ll build
- Hardware: Mini PC (Intel N100, 16 GB RAM, 2 TB NVMe)
- OS: Ubuntu Server 24.04 LTS (headless)
- Network posture: Mullvad VPN for fast initial sync; then Tor‑only Bitcoin Core
Services:
- Bitcoin Core (verified, supervised with systemd)
- Fulcrum (Electrum server) over LAN and a Tor hidden service
- mempool.space via Docker (LAN + Tor)
- Samourai Dojo via Docker
- Robosats via Docker
Monero node via Docker (simple‑monerod credit: SethForPrivacy) with Tor hidden service
- Ops: PGP verification, Docker primer, firewall, SSH hardening, backups, upgrades, and troubleshooting
Constraints and mindset
- This is a guide. You are responsible for your own due diligence, local laws, and ongoing maintenance. Basically DYOR
- Every command includes inline comments to explain what it does.
- When facts are uncertain (e.g., ecosystem changes), we state so and offer trade‑offs.
- Expect to learn Linux basics. It’s an investment that pays dividends across your digital life.
1) Why this manual path beats plug‑and‑play
Running a node is about enforcing rules you accept. Doing it manually ensures you actually know which rules you’re enforcing and how.
- Trust minimization: Node distros (like Start9 and Umbrel) add layers - opinionated packaging, dashboards, custom scripts. More code surface, more trust in their release and update process.
- Update sovereignty: You choose when to update. No waiting for a platform to push an app version. You can verify, stage, roll back.
- Auditability: You know exactly what runs. Your configs are readable. Your services are plain systemd units or Docker Compose files you control.
- Efficiency: Only install what you need. Less bloat, fewer daemons, smaller attack surface.
- Skills dividend: Basic Linux and Docker competency is invaluable. It makes you harder to censor and easier to self‑support.
2) What a node does (and why it matters)
A Bitcoin node is your fake‑Bitcoin detector. It downloads and verifies every block and transaction from genesis under the rules you choose (like the 21 million cap), and lets you broadcast your transactions without permission.
- Verification: Balances and incoming payments are only “real” when your node says they are.
- Censorship resistance: Broadcast on your schedule, not a custodian’s.
- Privacy: Query your own infrastructure; stop creating logs on third‑party servers.
3) Hardware profile and storage planning
Baseline (minimum target):
- CPU: Intel N100 (efficient, modern)
- RAM: 16 GB DDR4/DDR5 (helps Fulcrum fast‑sync and future headroom)
- Storage: 2 TB NVMe SSD (txindex=1 + Fulcrum DB + OS + growth)
- Network: Ethernet (wired beats Wi‑Fi for reliability)
- Power: Consider a small UPS or use a device with a battery if you can (Optional but recommended)
Storage outlook (approximate; grows over time):
- Bitcoin Core (full, txindex=1): ~700–800 GB today, growing
- Fulcrum DB: ~170 GB initial, grows with chain
- Monero full node: ~250 GB today, growing
- OS + logs + Docker layers: ~30–60 GB
Pruning trade‑off: You could prune Core to reduce disk, but then you lose features that depend on historical data. This guide uses txindex=1.
Network planning:
- Set a static DHCP lease for your node in your router to avoid IP changes.
- Enable AC recovery “Power On” in BIOS so your node auto‑boots after power loss.
4) BIOS/UEFI and Ubuntu Server install
Goal: A minimal, long‑lived base OS that survives outages and doesn’t get in your way.
BIOS/UEFI:
- Boot order: USB first for install; then NVMe.
- UEFI: Keep enabled. Disable Secure Boot if it blocks Ubuntu Server.
- AC recovery: “Power On” so the machine starts automatically after outages.
Install Ubuntu 24.04 LTS Server:
- Guide from Ministry of Nodes
- Minimal install (no GUI).
- Enable OpenSSH Server during install.
- On first boot, unplug install media; keep only Ethernet + power.
After install:
- Note your node’s IP from your router or via display during install.
- From your laptop/desktop, you will SSH into the node for everything else.
5) Linux command lexicon for beginners
You only need a short toolkit to run a secure node. You’ll see these throughout the guide.
Navigation and files
1
pwd
Print working directory (where am I?)
1
ls -la
List files (including hidden), long format
1
cd /path
Change directory to /path
1
mkdir /path/dir
Create a new directory
1
rm -rf /path/dir
Remove directory and contents (dangerous; triple-check path)
Editing text
1
nano /path/file
Open file in nano editor; Ctrl+O to write, Ctrl+X to exit
Packages and updates
1
sudo apt update
Refresh package indexes (what updates are available)
1
sudo apt upgrade -y
Install available updates (security + bug fixes)
Disk and logs
1
df -h
Show disk usage by filesystem (human-readable)
1
du -sh /path
Show total size of a directory
1
tail -f /var/log/syslog
Follow a log file in real time
Services (systemd)
1
sudo systemctl enable name.service
Enable on boot (create symlink)
1
sudo systemctl start name.service
Start service now
1
sudo systemctl status name.service
Check service state/log tail
1
journalctl -u name.service -f
Follow service logs in real time
- Also ctrl+k can be used to delete entire lines when editing files with nano
SSH and copy/paste
- Use your terminal application (macOS/Linux) or PowerShell (Windows).
- In many terminals, paste is Ctrl+Shift+V, not Ctrl+V.
- Tab autocompletion is your friend; use it to avoid typos in long paths.
- You can use the up/down arrowkeys to go to previous/next commands you have entered in your terminal’s bash history
- Entering ‘‘sudo !!” runs your last command with sudo
Backups (what you might consider backing up after this guide)
Configs and secrets, not blockchains:
- ~/.bitcoin/bitcoin.conf
- Fulcrum: ~/fulcrum/fulcrum.conf, ~/fulcrum/cert.pem, ~/fulcrum/key.pem
- Docker Compose files and .env files
- Dojo secrets and admin keys
- Tor hidden service directories (each service’s hostname/private_key)
- rpcauth credentials or rpcuser/rpcpassword if used
6) Hardening and quality of life
Security and operability steps worth doing early.
Enable unattended security updates
1
sudo apt install -y unattended-upgrades
Install auto security patcher
1
sudo dpkg-reconfigure -plow unattended-upgrades
Enable automatic security updates
Optional: mDNS for easy hostname (nodebox.local)
1
sudo apt install -y avahi-daemon
Enables .local hostname discovery on LAN
1
2
# After install, you can reach the node as: ssh youruser@nodebox.local
# (or whatever yout hostname is instead of nodebox)
Optional: Cockpit (browser UI at nodebox.local:9090)
1
sudo apt install -y cockpit
Simple web UI for health, logs, and a shell
SSH key authentication and disable password logins (recommended but totally optional)
1
mkdir -p ~/.ssh && chmod 700 ~/.ssh
Create SSH dir with secure perms
1
nano ~/.ssh/authorized_keys
Paste your public key; save file
1
chmod 600 ~/.ssh/authorized_keys
Secure the authorized keys file
1
sudo nano /etc/ssh/sshd_config
Set: PasswordAuthentication no; PubkeyAuthentication yes
1
sudo systemctl reload ssh
Apply SSH daemon changes without disconnect
Firewall (UFW) basics
Note: UFW can break things if you do not use it properly so ensure you understand how to use this first, watch this guide:
1
sudo apt install -y ufw
Install uncomplicated firewall
1
sudo ufw default deny incoming
Block inbound connections by default
1
sudo ufw default allow outgoing
Allow outbound by default
1
sudo ufw allow OpenSSH
Allow SSH from your LAN
1
sudo ufw enable
Turn on firewall (be sure SSH works first)
7) Mullvad first, then Tor: your staged privacy model
We’ll use Mullvad VPN to hide IBD from your ISP and improve throughput, then switch Bitcoin Core to Tor‑only for steady‑state privacy. This will also be useful for maintaining some privacy from your ISP when running your monero node.
Install Mullvad CLI (from Mullvad’s docs; adjust if they change URLs)
1
2
3
4
5
6
7
8
9
# Download the Mullvad signing key
sudo curl -fsSLo /usr/share/keyrings/mullvad-keyring.asc https://repository.mullvad.net/deb/mullvad-keyring.asc
# Add the Mullvad repository server to apt
echo "deb [signed-by=/usr/share/keyrings/mullvad-keyring.asc arch=$( dpkg --print-architecture )] https://repository.mullvad.net/deb/stable stable main" | sudo tee /etc/apt/sources.list.d/mullvad.list
# Install the package
sudo apt update
sudo apt install mullvad-vpn
Initial Mullvad setup
1
2
3
4
5
6
7
mullvad account login <YOUR_MULLVAD_ACCOUNT_NUMBER> # Activates your device
mullvad lan set allow # Prevents locking yourself out of the node
mullvad relay set location # Example: pick a location (e.g., Sweden Gothenburg)
mullvad auto-connect set on # Connect VPN automatically on boot
mullvad connect # Bring up the VPN now
mullvad status # Verify connection and selected exit
mullvad lockdown-mode set on # (optional) Disables all traffic that is not through the VPN
Notes:
- “lan set allow” is critical; without it, local connections to your node may fail when VPN is active.
- You can choose a relay closer to you for better performance. List here.
8) Verify, install, and supervise Bitcoin Core
Treat Bitcoin Core like critical infrastructure: verify, configure, supervise.
Create a working directory
1
2
mkdir -p ~/downloads
cd ~/downloads
Keep downloads organized
Download Bitcoin Core (adjust version as needed)
1
2
3
4
5
# Replace version with the latest stable from bitcoincore.org
BITCOIN_VERSION=29.1
wget https://bitcoincore.org/bin/bitcoin-core-${BITCOIN_VERSION}/bitcoin-${BITCOIN_VERSION}-x86_64-linux-gnu.tar.gz
wget https://bitcoincore.org/bin/bitcoin-core-${BITCOIN_VERSION}/SHA256SUMS
wget https://bitcoincore.org/bin/bitcoin-core-${BITCOIN_VERSION}/SHA256SUMS.asc
Verify checksums
1
sha256sum --ignore-missing -c SHA256SUMS
Should show “OK” for the tarball you downloaded
Import a trusted PGP key (e.g., fanquake/Michael Ford) and verify signature
Bitcoin releases are signed by a number of individuals, each with a unique public key. In order to recognize the validity of signatures, you must use GPG to load these public keys locally. You can find many developer keys listed in the bitcoin-core/guix.sigs repository, which you can then load into your GPG key database.
For example, you could load the key builder-keys/fanquake.gpg by downloading the file as fanquake.gpg and using this command:
1
2
wget https://raw.githubusercontent.com/bitcoin-core/guix.sigs/refs/heads/main/builder-keys/fanquake.gpg
gpg --import fanquake.gpg
The output of the command above should say that one key was imported, updated, has new signatures, or remained unchanged.
It is recommended that you choose a few individuals from this list who you find trustworthy and import their keys as above. You will later use their keys to check the signature attesting to the validity of the checksums you use to check the binaries. You can import all keys at once by cloning the repo and importing the directory:
1
2
git clone https://github.com/bitcoin-core/guix.sigs
gpg --import guix.sigs/builder-keys/*
Verify that the checksums file is PGP signed by a sufficient amount of keys you trust and have imported into your keychain:
1
gpg --verify SHA256SUMS.asc
The command above will output a series of signature checks for each of the public keys that signed the checksums. Each valid signature will show the following text:The output from the verify command may contain warnings that a public key is not available. As long as you have all the public keys of signers you trust, this warning can be disregarded. There may be additional warnings that a “key is not certified with a trusted signature.” This means that to fully verify your download, you need to confirm that the signing key’s fingerprint (e.g. E777 299F.. .) listed in the second line above matches what you had expected for the signers public key. See the GNU handbook section on key management for more details.
A line that starts with: gpg: Good signature
A complete line saying: Primary key fingerprint: E777 299F C265 DD04 7930 70EB 944D 35F9 AC3D B76A
Install binaries to /usr/local/bin
1
2
tar xzf bitcoin-${BITCOIN_VERSION}-x86_64-linux-gnu.tar.gz # Extract the tarball
sudo install -m 0755 -o root -g root -t /usr/local/bin bitcoin-${BITCOIN_VERSION}/bin/* # Copy binaries system-wide
Create bitcoin.conf
1
2
mkdir -p ~/.bitcoin
nano ~/.bitcoin/bitcoin.conf
Recommended initial config (IBD over VPN, not Tor yet):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# ~/.bitcoin/bitcoin.conf
server=1
daemon=1
txindex=1
# RPC (local only)
rpcbind=127.0.0.1
rpcallowip=127.0.0.1
rpcport=8332
# Credentials (use rpcauth for stronger security if exposing RPC beyond localhost)
# Replace with values you generate below (rpcauth), or set rpcuser/rpcpassword for local tools like Fulcrum.
rpcauth=USERNAME:HASHOFPASSWORD
# ZMQ for real-time block/tx notifications (used by Fulcrum/mempool)
zmqpubrawblock=tcp://127.0.0.1:28332
zmqpubrawtx=tcp://127.0.0.1:28333
zmqpubhashblock=tcp://127.0.0.1:28334
# Networking (IBD stage: use default clearnet over VPN)
listen=1
whitelist=127.0.0.1
rpcallowip=127.0.0.1
rpcallowip=10.0.0.0/8
rpcallowip=172.0.0.0/8
rpcallowip=192.0.0.0/8
Generate rpcauth and add the USERNAME:HASHOFPASSWORD to the above file:
1
2
3
4
5
# Download helper script from Bitcoin Core repo to generate rpcauth line
cd ~/downloads
wget https://raw.githubusercontent.com/bitcoin/bitcoin/master/share/rpcauth/rpcauth.py
chmod +x rpcauth.py
./rpcauth.py YourUsername YourStrongPassword # Outputs an rpcauth line to put in bitcoin.conf
Copy the string to be appended to bitcoin.conf
Start bitcoind once to initialize data dir
1
2
3
4
5
6
7
bitcoind -daemon
``>
> Starts Bitcoin Core in the background using your config
### Follow logs and check sync state
```bash
tail -f ~/.bitcoin/debug.log
Watch sync progress in real time (Ctrl+C to stop)
1
bitcoin-cli getblockchaininfo
Snapshot of headers/blocks sync status
1
bitcoin-cli getconnectioncount
How many peers you’re connected to
Create a systemd service so Core auto‑starts on boot
1
sudo nano /etc/systemd/system/bitcoind.service
Paste:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# It is not recommended to modify this file in-place, because it will
# be overwritten during package upgrades. If you want to add further
# options or overwrite existing ones then use
# $ systemctl edit bitcoind.service
# See "man systemd.service" for details.
# Note that almost all daemon options could be specified in
# /etc/bitcoin/bitcoin.conf, but keep in mind those explicitly
# specified as arguments in ExecStart= will override those in the
# config file.
[Unit]
Description=Bitcoin daemon
Documentation=https://github.com/bitcoin/bitcoin/blob/master/doc/init.md
# https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/
After=network-online.target
Wants=network-online.target
[Service]
ExecStart=/usr/local/bin/bitcoind -daemon \
-pid=/run/bitcoind/bitcoind.pid \
-conf=/home/satoshi/.bitcoin/bitcoin.conf \
-datadir=/home/satoshi/.bitcoin
# Make sure the config directory is readable by the service user
PermissionsStartOnly=true
#ExecStartPre=/bin/chgrp bitcoin /etc/bitcoin
# Process management
####################
Type=forking
PIDFile=/run/bitcoind/bitcoind.pid
Restart=on-failure
TimeoutStartSec=infinity
TimeoutStopSec=600
# Directory creation and permissions
####################################
# Run as bitcoin:bitcoin
User=satoshi
Group=satoshi
# /run/bitcoind
RuntimeDirectory=bitcoind
RuntimeDirectoryMode=0710
# /etc/bitcoin
ConfigurationDirectory=bitcoin
ConfigurationDirectoryMode=0710
# /var/lib/bitcoind
StateDirectory=bitcoind
StateDirectoryMode=0710
# Hardening measures
####################
# Provide a private /tmp and /var/tmp.
PrivateTmp=true
# Mount /usr, /boot/ and /etc read-only for the process.
ProtectSystem=full
# Deny access to /home, /root and /run/user
#ProtectHome=true
# Disallow the process and all of its children to gain
# new privileges through execve().
NoNewPrivileges=true
# Use a new /dev namespace only populated with API pseudo devices
# such as /dev/null, /dev/zero and /dev/random.
PrivateDevices=true
# Deny the creation of writable and executable memory mappings.
MemoryDenyWriteExecute=true
[Install]
WantedBy=multi-user.target
Enable and start (replace “satoshi” with your username if different)
1
sudo systemctl enable bitcoind@satoshi.service
Enable templated service for your user
1
sudo systemctl start bitcoind@satoshi.service
Start Core under your user account
1
systemctl status bitcoind@satoshi.service
Confirm running
IBD will take a few hours to a few day depending on your hardware and internet. That’s fine - Mullvad conceals it from your ISP and often improves throughput. When done:
bitcoin-cli getblockchaininfo shows headers == blocks and “initialblockdownload”: false
9) Flip to Tor‑only Core and add hidden services
Install Tor and set up control access (so apps can use Tor programmatically)
1
2
sudo apt install -y tor
sudo nano /etc/tor/torrc
Edit torrc (uncomment/add):
1
2
3
ControlPort 9051
CookieAuthentication 1
CookieAuthFileGroupReadable 1
Apply and verify Tor
1
sudo systemctl reload tor
Reload Tor config
1
sudo ss -tulpn | grep tor | grep LISTEN
Confirm Tor is listening on 127.0.0.1:9050 and 9051
1
sudo journalctl -f -u tor@default
View Tor logs (Ctrl+C to exit)
Reconfigure Bitcoin Core to use Tor‑only for P2P
1
nano ~/.bitcoin/bitcoin.conf
Delete old contents of bitcoin.conf and replace with this below:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# ------------------------------
# Networking & Tor Configuration
# ------------------------------
# Accept only Tor (.onion) peers — used after initial block download (IBD)
onlynet=onion
# Route all traffic through Tor's SOCKS5 proxy
proxy=127.0.0.1:9050
# Bind to localhost (for security, no external IPs)
bind=127.0.0.1
# ------------------------------
# Node Operation Settings
# ------------------------------
# Enable JSON-RPC server (for remote control, wallet, etc.)
server=1
# Enable transaction index (stores all transactions for querying via RPC)
txindex=1
# Run in the background as a daemon (Unix only)
daemon=1
# ------------------------------
# RPC (Remote Procedure Call) Settings
# ------------------------------
# Set RPC server port (default is 8332)
rpcport=8332
# Listen for RPC connections on all interfaces
rpcbind=0.0.0.0
# Allow RPC connections from localhost
rpcallowip=127.0.0.1
# Allow RPC from common private network ranges (customize as needed)
rpcallowip=10.0.0.0/8
rpcallowip=172.0.0.0/8
rpcallowip=192.0.0.0/8
# ⚠️ Note: This opens RPC server to LAN. Make sure authentication is enabled!
# ------------------------------
# ZMQ (ZeroMQ) Event Broadcasting
# ------------------------------
# Publish raw block data to this TCP address
zmqpubrawblock=tcp://0.0.0.0:28332
# Publish raw transaction data
zmqpubrawtx=tcp://0.0.0.0:28333
# Publish block hash notifications
zmqpubhashblock=tcp://0.0.0.0:28334
# ⚠️ ZMQ binds to all interfaces (0.0.0.0)
# ------------------------------
# Whitelisting
# ------------------------------
# Never ban localhost even if misbehaving
whitelist=127.0.0.1
# ------------------------------
# RPC Authentication (REQUIRED if rpcbind is not localhost)
# ------------------------------
rpcauth=username:hash-of-password
# Allow creation of legacy wallets (required for JoinMarket if you decide to use that, you should be whirlpooling instead!)
deprecatedrpc=create_bdb
maxmempool=2000
# Filters - for Bisq
peerbloomfilters=1
Restart Core and confirm Tor reachability
1
2
sudo systemctl restart bitcoind@satoshi.service
bitcoin-cli getnetworkinfo
onion reachable: true; ipv4/ipv6 reachable: false
1
bitcoin-cli getpeerinfo
Peer addresses show .onion
1
bitcoin-cli getnetworkinfo | grep -A3 localaddresses
This is your bitcoin p2p address
Create Tor hidden services for remote access to specific apps
We will expose Fulcrum (50002), mempool.space (web UI on 4080), and Monero restricted RPC (18089).
1
sudo nano /etc/tor/torrc
Append per‑service hidden services:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
############### This section is just for location-hidden services ###
# Hidden Service: Fulcrum (SSL 50002)
HiddenServiceDir /var/lib/tor/hs_fulcrum_ssl/
HiddenServiceVersion 3
HiddenServicePort 50002 127.0.0.1:50002
# Hidden Service: Fulcrum (TCP)
HiddenServiceDir /var/lib/tor/hs_fulcrum_tcp/
HiddenServiceVersion 3
HiddenServicePort 50001 127.0.0.1:50001
# Hidden Service: mempool.space
HiddenServiceDir /var/lib/tor/hs_mempool/
HiddenServiceVersion 3
HiddenServicePort 80 127.0.0.1:4080
# Hidden Service: Robosats
HiddenServiceDir /var/lib/tor/hs_robosats/
HiddenServiceVersion 3
HiddenServicePort 80 127.0.0.1:12596
# Hidden Service: Monero restricted RPC (18089)
HiddenServiceDir /var/lib/tor/hs_monero_rpc/
HiddenServiceVersion 3
HiddenServicePort 18089 127.0.0.1:18089
Reload and retrieve onion addresses
1
sudo find /var/lib/tor/ -type f -name hostname -path "/var/lib/tor/hs_*/hostname" -exec sh -c 'echo "{}"; cat "{}"; echo' \;
Important: Back up each hidden service directory (it contains the private key that controls the onion identity).
10) Fulcrum: your private Electrum server
Why Fulcrum? It indexes the chain for fast wallet queries and keeps your wallet’s addresses on your node, not on random public servers. Faster and more private.
Create directories and download a release
1
2
3
4
5
6
mkdir -p ~/fulcrum ~/fulcrum_db
cd ~/downloads
# Replace version as needed (see Fulcrum releases)
wget https://github.com/cculianu/Fulcrum/releases/download/v2.0.0/Fulcrum-2.0.0-x86_64-linux.tar.gz
tar xzf Fulcrum-1.12.0-x86_64-linux.tar.gz
mv Fulcrum-2.0.0-x86_64-linux/* ~/fulcrum/ # Put binaries in ~/fulcrum
Generate LAN keys for encrypted Electrum connections
1
2
cd ~/fulcrum
openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem
Creates a self-signed cert pair; leave prompts blank or fill generically
Create and edit config
1
2
cp fulcrum-example-config.conf fulcrum.conf # Name may vary; use the example shipped with your release
nano fulcrum.conf
Key settings to adapt:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
datadir = /home/satoshi/fulcrum_db
# Bitcoin Core RPC (local)
bitcoind = 127.0.0.1:8332
rpcuser = bitcoin
rpcpassword = bitcoin
# Serve SSL to clients on LAN (and to Tor hidden service)
tcp = 0.0.0.0:50001
ssl = 0.0.0.0:50002
cert = /home/satoshi/fulcrum/cert.pem
key = /home/satoshi/fulcrum/key.pem
#banner is optional and you may remove
banner = /home/satoshi/fulcrum/banner.txt
# Performance and behavior
peering = false
db_mem = 5120
Create optional banner
in ~/fulcrum nano a banner.txt and add a fun ASCII art to make your node your own. You will see this when you connect to sparrow. It can be a lighthearted way to verify you are connected to your own server. Here is a useful ASCII art creation website.
Create a systemd service for auto startup at boot
1
sudo nano /etc/systemd/system/fulcrum.service
Paste:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[Unit]
Description=Fulcrum
After=network.target bitcoind@satoshi.service
Requires=bitcoind@satoshi.service
[Service]
ExecStart=/home/satoshi/fulcrum/Fulcrum /home/satoshi/fulcrum/fulcrum.conf
User=satoshi
LimitNOFILE=8192
TimeoutStopSec=30min
Restart=on-failure
[Install]
WantedBy=multi-user.target
Enable, start, and monitor
1
2
3
sudo systemctl enable fulcrum.service
sudo systemctl start fulcrum.service
journalctl -u fulcrum.service -f
Watch the index build; expect many hours and ~170+ GB
Sparrow wallet connections
- LAN: Add your node’s LAN IP (or nodebox.local) and port 50002 in Sparrow, check “Use SSL.” [On first connect some wallets will allow you to view and pin your self‑signed cert/fingerprint].
- Tor: In Sparrow, enable tor, and use your Fulcrum onion with port 50002 (SSL). Pin the cert on first connect.
11) mempool.space via Docker (LAN + Tor)
Why Docker here? mempool.space is a multi‑service app (frontend, API, backend indexers). Docker Compose gives a clean one‑file definition, isolated dependencies, and reproducible updates.
Install Docker and join the docker group
1
2
3
4
5
6
7
8
9
10
11
12
13
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
To install the latest version, run
1
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Clone mempool repo and prepare Compose
1
2
3
cd ~
git clone https://github.com/mempool/mempool.git
cd mempool/docker
Edit docker-compose.yml (key changes)
- Map frontend port to 4080 on the host.
- Set backend to “electrum” and point to Fulcrum.
- Provide Core RPC credentials and ZMQ endpoints.
Example docker-compose.yml snippet (adapt to upstream format if they change service names):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
version: "3.7"
services:
web:
environment:
FRONTEND_HTTP_PORT: "8080"
BACKEND_MAINNET_HTTP_HOST: "api"
container_name: mempool-web
image: mempool/frontend:v3.2.1
user: "1000:1000"
restart: always
stop_grace_period: 1m
command: "./wait-for db:3306 --timeout=720 -- nginx -g 'daemon off;'"
ports:
- 4080:8080
api:
environment:
MEMPOOL_BACKEND: "none"
MEMPOOL_BACKEND: "electrum"
ELECTRUM_HOST: "172.17.0.1"
ELECTRUM_PORT: "50002"
CORE_RPC_HOST: "172.17.0.1"
CORE_RPC_PORT: "8332"
CORE_RPC_USERNAME: "bitcoin"
CORE_RPC_PASSWORD: "bitcoin"
DATABASE_ENABLED: "true"
DATABASE_HOST: "db"
DATABASE_DATABASE: "mempool"
DATABASE_USERNAME: "mempool"
DATABASE_PASSWORD: "mempool"
STATISTICS_ENABLED: "true"
image: mempool/backend:v3.2.1
container_name: mempool-api
user: "1000:1000"
restart: always
stop_grace_period: 1m
command: "./wait-for-it.sh db:3306 --timeout=720 --strict -- ./start.sh"
volumes:
- ./data:/backend/cache
db:
environment:
MYSQL_DATABASE: "mempool"
MYSQL_USER: "mempool"
MYSQL_PASSWORD: "mempool"
MYSQL_ROOT_PASSWORD: "admin"
container_name: mempool-db
image: mariadb:10.5.21
user: "1000:1000"
restart: always
stop_grace_period: 1m
volumes:
- ./mysql/data:/var/lib/mysql
networks:
default:
driver: bridge
ipam:
config:
- subnet: 172.16.57.0/24
To avoid network conflicts this has been added to the bottom of the file:
1
2
3
4
5
6
networks:
default:
driver: bridge
ipam:
config:
- subnet: 172.16.57.0/24
Start it up
1
docker compose up -d
Launches the stack in the background
1
docker compose ps
Shows running containers and ports
Access mempool.space
- LAN: nodebox.local:4080 (or your node IP)
- Tor: Use the mempool onion created earlier; visit with Tor Browser
To Update
1
2
docker compose pull
docker compose up -d
Pull new images and recreate containers with new images
12) Samourai Dojo via Docker
Dojo gives Samurai‑ecosystem wallets a private backend you control (like Ashigaru). The Ashigaru fork emerged after the indictment of the samourai wallet devs - read. The wallet server functionality still matters for private use.
Full Credit to K3tan of Ministry of nodes - Support him here please
Follow this video guide to setup Samourai Dojo step by step:
Dojo Maintenance Tool via Tor
- The installer typically prints an onion URL for the admin interface.
- Visit in Tor Browser, enter your admin key, and wait for all subsystems to go green.
- Pair your Samourai/Ashigaru wallet using the QR in the “Pairing” tab.
13) Robosats via Docker
Robosats is a Tor‑native P2P exchange. I will show you how to self host it for the most sovereign experience when buying bitcoin peer-to-peer.
Step 1: Clone the RoboSats Repository
Clone the official RoboSats GitHub repo.
1
git clone https://github.com/RoboSats/robosats.git
Step 2: Navigate to the Project Directory
Change into the cloned directory and then into the nodeapp subdirectory.
1
2
cd robosats/
cd nodeapp/
Step 3: Prepare the Docker Compose File
Rename the example Docker Compose file to the actual file Docker uses.
1
mv docker-compose-example.yml docker-compose.yml
Step 4: Edit Docker Compose Configuration
If needed, open the file for editing:
1
nano docker-compose.yml
Change
1
container_name: tor
To
1
container_name: robosats-tor
Step 5: Start the RoboSats Docker Services
Build and start the Docker containers in detached mode:
1
docker compose up -d
You might see a warning about the version field — it’s safe to ignore or remove from docker-compose.yml if desired.
Use this to access your own robosats instance over tor or just use your server’s ip with port 12596
14) Monero node via Docker (simple‑monerod) + Tor
Monero complements Bitcoin with generally more private by default transactions. Running your own node prevents wallet leaks to remote RPC servers.
Recommended run (restricted RPC + watchtower)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Monero daemon (restricted RPC exposed on 18089; P2P on 18080)
docker run -d --restart unless-stopped --name="monerod" \
-p 18080:18080 -p 18089:18089 \
-v bitmonero:/home/monero \
ghcr.io/sethforprivacy/simple-monerod:latest \
--rpc-restricted-bind-ip=0.0.0.0 \
--rpc-restricted-bind-port=18089 \
--no-igd --no-zmq --enable-dns-blocklist
# Watchtower auto-updates (monerod and tor if present)
docker run -d --name watchtower --restart unless-stopped \
-v /var/run/docker.sock:/var/run/docker.sock \
containrrr/watchtower --cleanup \
monerod tor
Logs and status
1
docker logs --follow monerod
Follow daemon logs
1
docker exec monerod /usr/local/bin/monerod status
Short status: peers, height, sync
1
docker exec monerod /usr/local/bin/monerod sync_info
Detailed sync info
1
docker exec monerod /usr/local/bin/monerod print_net_stats
Traffic stats and limits
1
docker exec monerod /usr/local/bin/monerod update check
Check for new version
Expose Monero restricted RPC over Tor
1
2
# We already added a Tor hidden service for Monero RPC in torrc earlier (hs_monero_rpc).
sudo cat /var/lib/tor/hs_monero_rpc/hostname
Use in your wallet settings
15) Maintenance, upgrades, and backups
Sovereignty is a practice, not a product. Put maintenance on your calendar.
OS and packages
1
sudo apt update && sudo apt upgrade -y
Periodic manual updates alongside unattended upgrades
Bitcoin Core upgrades
1
2
3
4
5
6
7
# Stop Core, verify new release, install, then start
sudo systemctl stop bitcoind@satoshi.service
# Repeat the download + checksum + PGP verify steps from earlier with the new version
tar xzf bitcoin-<NEW>.tar.gz
sudo install -m 0755 -o root -g root -t /usr/local/bin bitcoin-<NEW>/bin/*
sudo systemctl start bitcoind@satoshi.service
bitcoin-cli -version
Fulcrum upgrades
1
2
3
4
sudo systemctl stop fulcrum.service
# Replace ~/fulcrum binaries with new release after verifying checksums/signature if provided
sudo systemctl start fulcrum.service
journalctl -u fulcrum.service -f
mempool.space upgrades
1
2
3
cd ~/mempool/docker
docker compose pull
docker compose up -d
Monero upgrades
Watchtower restarts your container on new tags automatically, no manual input neccesary.
Backups (configs and keys, not block data)
- ~/.bitcoin/bitcoin.conf and rpcauth/rpc credentials
- ~/fulcrum/fulcrum.conf, cert.pem, key.pem
- Docker Compose files and any .env files
- Dojo secrets/admin key (and any wallet pairing info)
- Tor hidden service directories:
- /var/lib/tor/hs_fulcrum
- /var/lib/tor/hs_mempool
- /var/lib/tor/hs_monero_rpc
- (and any others you create like hs_robosats)
- Store backups encrypted, off the machine. Test restores.
Power and shutdown
- Always shut down gracefully to protect Fulcrum and databases.
- Consider a small UPS; configure the BIOS AC “Power On” setting.
16) Threat models and pitfalls
Who sees what?
- IBD over Mullvad (clearnet through VPN): ISP sees VPN traffic; Mullvad sees volume/destinations, not Bitcoin payloads; Bitcoin peers see your VPN egress IP.
- Tor‑only Core: ISP sees Tor usage (unless over VPN); peers see only your onion identity; you avoid clearnet IP exposure.
- LAN services: Anyone on your LAN can see open ports; protect with firewall and strong auth.
Common foot‑guns
- Mullvad without “lan allow” can lock you out; set it before connecting.
- Wrong ExecStart path (/usr vs /usr/local/bin) breaks systemd units..
- Fulcrum DB corruption from hard power loss; always shut down cleanly - This should not be an issue after the main release of Fulcrum 2.0.
- Disk exhaustion; keep headroom and monitor df -h.
- PGP trust: Verify fingerprints out‑of‑band where possible; don’t blindly trust keyservers.
When asking for help
- Share logs and configs selectively (redact secrets and onion hostnames).
- Use paste services with expiry; never post private keys or admin tokens.
17) Appendix: operator’s cheat sheet
Frequently used commands
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# System
df -h
du -sh /path
journalctl -u name.service -f
sudo systemctl {start,stop,restart,status,enable,disable} name.service
# Bitcoin
tail -f ~/.bitcoin/debug.log
bitcoin-cli getblockchaininfo
bitcoin-cli getnetworkinfo
bitcoin-cli getpeerinfo
bitcoin-cli gettxoutsetinfo
# Docker
docker compose ps
docker compose logs -f
docker ps
docker logs -f <container>
# Tor
sudo systemctl reload tor
sudo cat /var/lib/tor/<hs_name>/hostname
Key file paths
- Bitcoin: ~/.bitcoin/bitcoin.conf
- Fulcrum: ~/fulcrum/fulcrum.conf, ~/fulcrum/cert.pem, ~/fulcrum/key.pem
- systemd units: /etc/systemd/system/*.service
- mempool: ~/mempool/docker/docker-compose.yml
- Dojo: ~/dojo-app/docker/my-dojo/*.tpl and generated configs
- Tor hidden services: /var/lib/tor/*/ (hostname, private_key)
Ports overview
Service Local port(s) Tor HS port mapping Notes
Bitcoin Core RPC 8332 n/a RPC local only (default)
Bitcoin P2P 8333 (loopback) 8333 -> 127.0.0.1:8333 Bitcoin p2p Tor
Bitcoin Core ZMQ 28332/28333/28334 n/a For block/tx notifications
Fulcrum SSL 50002 50002 -> 127.0.0.1:50002 Electrum Server
mempool.space 4080 (HTTP) 80 -> 127.0.0.1:4080 Use Tor Browser
Monero RPC (restricted) 18089 18089 -> 127.0.0.1:18089 Wallet RPC
Tor control 9051 n/a CookieAuth enabled
Tor SOCKS 9050 n/a Local proxy
Closing: The necessary journey
Sovereignty isn’t a product you buy. It’s a practice you adopt. You’ve now built a Bitcoin stack you can explain, verify, and repair. You know where the binaries came from, which keys signed them, what every service does, and how to turn any of it off. You can patch when you want, roll back when you need, and expose only what you intend—over Tor, on your terms.
Next steps
- Connect Sparrow to Fulcrum (LAN or Tor) and verify you can view and broadcast transactions.
- Use your local mempool.space (ideally over tor) to inspect fees and monitor transactions without leaking queries.
- Pair Ashigaru to your Dojo if you use that wallet.
- Keep good backups of configs and Tor hiddenservice addresses, and schedule maintenance.
You didn’t just install software - you claimed responsibility. That’s what sovereign stacking looks like.
Credits to https://raspibolt.org/ + https://sethforprivacy.com/ + https://k3tan.com/ for providing us with the knowledge required. Show them support.
For any corrections, edits or suggestions please contact me on signal at vibrant.01 or on X at https://x.com/VibrantBTC
Share this if it was helpful and support the people/projects credited above.
