Fulcrum - tulliolo/mobybolt GitHub Wiki
Fulcrum is a fast & nimble SPV server for Bitcoin created by Calin Culianu. It can be used as an alternative to Electrs because of its performance, as we can see in Craig Raw's comparison of servers.
â To follow this section, log in to your node as admin user via Secure Shell (SSH) and access the project's home:
$ cd apps/mobybolt
- Bitcoin Knots or Bitcoin Core
- ~ 130GB of free storage for the database
â Fulcrum is a replacement for Electrs, these two services cannot be run at the same time (due to the same standard ports used). If you already have Electrs installed, please uninstall it before proceeding.
Bitcoin with hardware wallets
The best way to safely keep your bitcoin (meaning the best combination of security and usability) is to use a hardware wallet (like BitBox, Coldcard, Ledger, or Trezor) in combination with your own Bitcoin node. This gives you security, privacy and eliminates the need to trust a third party to verify transactions.
Bitcoin Knots/Core on the MobyBolt itself is not meant to hold funds.
One possibility to use Bitcoin Core with your Bitcoin wallets is to use an Electrum server as middleware. It imports data from Bitcoin Knots/Core and provides it to software wallets supporting the Electrum protocol. Desktop wallets like Sparrow, the BitBoxApp, Electrum, or Specter Desktop that support hardware wallets can then be used with your own sovereign Bitcoin node.
Create the fulcrum directory:
$ mkdir fulcrum
Edit the .env file and append the following content to the end:
$ nano .env
# fulcrum
FULCRUM_VERSION=1.11.1
FULCRUM_ADDRESS=172.16.21.5
FULCRUM_GID=1101
FULCRUM_UID=1101
đĄ In this file:
- we define the
FULCRUM_VERSION(check the latest available version here); - we define a static address for the container;
- we define the
uid(user id) andgid(group id) of the fulcrum user.
Create the banner file with the following content (it will be shown when Fulcrum starts):
$ nano fulcrum/fulcrum-banner.txt
______ __
/ ____/_ __/ /___________ ______ ___
/ /_ / / / / / ___/ ___/ / / / __ `__ \
/ __/ / /_/ / / /__/ / / /_/ / / / / / /
/_/ \__,_/_/\___/_/ \__,_/_/ /_/ /_/
__ ___ __ ____ ____
/ |/ /___ / /_ __ __/ __ )____ / / /_
/ /|_/ / __ \/ __ \/ / / / __ / __ \/ / __/
/ / / / /_/ / /_/ / /_/ / /_/ / /_/ / / /_
/_/ /_/\____/_.___/\__, /_____/\____/_/\__/
/____/
Create the Dockerfile and populate it with the following content:
$ nano fulcrum/Dockerfile
# base image
FROM debian:stable-slim AS base
# install dependencies
RUN set -eux && \
apt update && \
apt install -y \
build-essential \
curl \
git \
libbz2-dev \
libjemalloc-dev \
libzmq3-dev \
pkg-config \
qt5-qmake \
qtbase5-dev \
zlib1g-dev && \
rm -rf /var/lib/apt/lists/*
# builder image
FROM base AS builder
ARG FULCRUM_VERSION
ENV FULCRUM_URL="https://github.com/cculianu/Fulcrum.git"
RUN set -eux && \
# download repository
git clone --branch "v$FULCRUM_VERSION" $FULCRUM_URL
WORKDIR /Fulcrum
# install fulcrum
RUN set -eux && \
# verify signatures
git checkout "v$FULCRUM_VERSION" && \
# configure
qmake -makefile PREFIX=/usr/local Fulcrum.pro && \
# build
make -j$(nproc) && \
# install
make install
# result image
FROM debian:stable-slim
COPY --from=builder /usr/local/ /usr/local/
# install dependencies
RUN set -eux && \
apt update && \
apt install -y \
libjemalloc-dev \
libqt5network5 \
libzmq3-dev \
python3 && \
rm -rf /var/lib/apt/lists/*
# default uid for fulcrum user
ARG FULCRUM_GID=1101
ARG FULCRUM_UID=1101
ARG BITCOIN_GID=1100
RUN set -xe && \
# create fulcrum user
addgroup --gid $FULCRUM_GID fulcrum && \
adduser --disabled-password --comment "" --gid $FULCRUM_GID --uid $FULCRUM_UID fulcrum && \
# create bitcoin group and add fulcrum user to bitcoin group
addgroup --gid $BITCOIN_GID bitcoin && \
adduser fulcrum bitcoin && \
# setup dirs and permissions
mkdir -p /home/fulcrum/db/ /run/fulcrum/ && \
chmod 0700 /home/fulcrum/db/ /run/fulcrum/ && \
chown fulcrum:fulcrum /home/fulcrum/db/ /run/fulcrum/
# setup entrypoint
COPY --chmod=0755 docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]
# switch user
USER fulcrum
COPY ./fulcrum-banner.txt /home/fulcrum/.fulcrum/
đĄ In this file:
- we define a builder image (
builder) to buid fulcrum from github sources, verifying version tag signatures; - we define a result image:
- installing some needed dependencies;
- copying binaries from builder image;
- configuring the
fulcrumuser and the directories to which he will have access; - adding the
fulcrumuser to thebitcoingroup for RPC cookie authentication; - setting the
entrypoint(the script to run when the container starts).
Create the entrypoint file and populate it with the following content:
$ nano fulcrum/docker-entrypoint.sh
#!/bin/bash
set -eo pipefail
function die_func() {
echo "INFO: got SIGTERM... exiting"
exit 1
}
trap die_func TERM
CMD=$@
CONF_FILE="/home/fulcrum/fulcrum.conf"
if [[ $# -eq 0 ]]; then
# missing parameters, run fulcrum
CMD="/usr/local/bin/Fulcrum $CONF_FILE"
fi
exec $CMD
đĄ In this file:
- we define the configuration file;
- we run fulcrum.
Create the Fulcrum configuration file and populate it with the following content:
$ nano fulcrum/fulcrum.conf
# MobyBolt: fulcrum configuration
# /home/fulcrum/.fulcrum/fulcrum.conf
## Bitcoin Core settings
bitcoind = bitcoin:8332
rpccookie = /data/bitcoin/.cookie
## Admin Script settings
admin = 8000
## Fulcrum server general settings
datadir = /home/fulcrum/db
pidfile = /run/fulcrum/fulcrum.pid
tcp = 0.0.0.0:50001
peering = false
# Set utxo-cache according to your device,
# recommended: utxo-cache=1/2 x RAM available e.g: 4GB RAM -> dbcache=2048
utxo-cache = 4096
# Banner
banner = /home/fulcrum/.fulcrum/fulcrum-banner.txt
Create the Docker Compose file and populate it with the following content:
$ nano fulcrum/docker-compose.yml
services:
electrumserver:
build:
context: .
args:
FULCRUM_VERSION: ${FULCRUM_VERSION}
FULCRUM_GID: ${FULCRUM_GID}
FULCRUM_UID: ${FULCRUM_UID}
container_name: ${COMPOSE_PROJECT_NAME}_fulcrum
depends_on:
bitcoin:
condition: service_healthy
expose:
- "50001:50001"
image: ${COMPOSE_PROJECT_NAME}/fulcrum:${FULCRUM_VERSION}
networks:
default:
ipv4_address: ${FULCRUM_ADDRESS}
restart: unless-stopped
stop_grace_period: 3m
volumes:
- fulcrum-data:/home/fulcrum/db/
- bitcoin-data:/data/bitcoin/:ro
- ./fulcrum.conf:/home/fulcrum/fulcrum.conf:ro
volumes:
fulcrum-data:
đĄ In this file:
- we
buildthe Dockerfile and create an image namedmobybolt/fulcrum:<version>; - we define the
restartpolicy of the container in case of failures; - we declare the bitcoin service as a dependency (Fulcrum will not run if bitcoin is not active);
- we provide the container:
- with the previously defined configuration (bind mount);
- with the bitcoin volume data, from which it will reach the RPC authentication cookie;
- with a volume named
mobybolt_fulcrum-datato store persistent data; - with the
FULCRUM_ADDRESSstatic address.
Edit the main Docker Compose file and link the fulcrum docker compose file in the include section:
$ nano docker-compose.yml
The file should look like this:
include:
- ...
- fulcrum/docker-compose.ymlRun the following command and check the output:
$ docker compose config --quiet && printf "OK\n" || printf "ERROR\n"
> OK
đĄ If the output is not OK, check the error reported... Maybe some wrong indentation in the yaml files?
Let's build the fulcrum image by typing:
$ docker compose build electrumserver
Check for a new image called mobybolt/fulcrum:<version>:
$ docker images | grep fulcrum
> mobybolt/fulcrum 1.11.1 03c38d632c76 About a minute ago 345MB
Run the following command and check the output:
$ docker compose up -d electrumserver
> [+] Running 2/2
> â Volume "mobybolt_fulcrum-data" Created
> â Container mobybolt_fulcrum Started
Check the container logs:
$ docker logs mobybolt_fulcrum
> ...
> [2024-07-25 08:16:13.743] <Controller> Processed height: 1000, 0.1%, 88.4 blocks/sec, 90.1 txs/sec, 92.4 addrs/sec
> [2024-07-25 08:16:31.127] <Controller> Processed height: 2000, 0.2%, 57.5 blocks/sec, 58.2 txs/sec, 62.7 addrs/sec
> [2024-07-25 08:16:41.038] <Controller> Processed height: 3000, 0.4%, 100.9 blocks/sec, 102.9 txs/sec, 106.9 addrs/sec
> ...
Check the container status:
$ docker ps | grep fulcrum
> fbbd387b08d7 mobybolt/fulcrum:1.11.1 "docker-entrypoint.sh" 48 minutes ago Up 48 minutes 0/tcp mobybolt_fulcrum
âšī¸ If not already present, docker will also create the mobybolt_fulcrum-data volume. You can check for it with the command:
$ docker volume ls | grep fulcrum
> local mobybolt_fulcrum-data
Fulcrum must first fully index the blockchain and compact its database before you can connect to it with your wallets. This can take up to ~1.5 - 4 days or more, depending on the hardware. Only proceed with the Blockchain explorer: BTC RPC Explorer and Desktop Wallet Section once Fulcrum is ready.
Fulcrum will now index the whole Bitcoin blockchain so that it can provide all necessary information to wallets. With this, the wallets you use no longer need to connect to any third-party server to communicate with the Bitcoin peer-to-peer network.
â DO NOT REBOOT OR STOP THE SERVICE DURING THE DB CREATION PROCESS. YOU MAY CORRUPT THE FILES - in case that happens, start the sync from scratch by deleting the mobybolt_fulcrum-data volume, follow the next steps:
- Remove Fulcrum container:
$ docker compose down electrumserver > [+] Running 2/1 > â Container mobybolt_fulcrum Removed - Remove Fulcrum volume:
$ docker volume rm mobybolt_fulcrum-data > mobybolt_fulcrum-data - Follow the run section again.
When you see logs like this SrvMgr: starting 3 services ..., which means that Fulcrum is fully indexed
[2024-06-09 10:28:56.705] SrvMgr: starting 3 services ...
[2024-06-09 10:28:56.706] Starting listener service for TcpSrv 0.0.0.0:50001 ...
[2024-06-09 10:28:56.706] Service started, listening for connections on 0.0.0.0:50001
[2024-06-09 10:28:56.706] Starting listener service for SslSrv 0.0.0.0:50002 ...
[2024-06-09 10:28:56.706] Service started, listening for connections on 0.0.0.0:50002
[2024-06-09 10:28:56.707] Starting listener service for AdminSrv 127.0.0.1:8000 ...
[2024-06-09 10:28:56.707] Service started, listening for connections on 127.0.0.1:8000
[2024-06-09 10:28:56.707] <Controller> Starting ZMQ Notifier (hashblock) ...
Fulcrum comes with an admin script. The admin service, only available once Fulcrum is fully synchronized, is used for sending special control commands to the server. You may send commands to Fulcrum using this script.
Type the next command to see a list of possible subcommands that you can send to Fulcrum
$ docker exec mobybolt_fulcrum FulcrumAdmin -h
> usage: FulcrumAdmin [-h] -p port [-j] [-H [host]]
{addpeer,ban,banpeer,bitcoind_throttle...
> ...
Type the next command to get complete server information
$ docker exec mobybolt_fulcrum FulcrumAdmin -p 8000 getinfo
âšī¸ Get more information about this command in the official documentation section
As mentioned above, even though Fulcrum supports SSL/TLS connections, we'll still use nginx for these connections.
To perform this configuration:
-
create the electrumserver-reverse-proxy configuration file with the following contents:
$ nano nginx/config/streams-enabled/electrumserver-reverse-proxy.confupstream electrumserver { server 172.16.21.5:50001; } server { listen 50002 ssl; proxy_pass electrumserver; }
-
test nginx configuration:
$ docker exec mobybolt_nginx nginx -t > nginx: the configuration file /etc/nginx/nginx.conf syntax is ok > nginx: configuration file /etc/nginx/nginx.conf test is successful -
edit the nginx docker-compose file adding a
portssection betweenimageandrestart; the file should look like below:$ nano nginx/docker-compose.ymlimage: ${COMPOSE_PROJECT_NAME}/nginx:${NGINX_VERSION} ports: - "50002:50002" # electrumserver restart: unless-stopped
đĄ This configuration will allow the Fulcrum ssl/tls port in the docker-managed firewall.
â ī¸ Be very careful to respect the indentation. Yaml is very sensitive to this!â ī¸ -
test the docker compose file:
$ docker compose config --quiet && printf "OK\n" || printf "ERROR\n" > OK -
recreate the nginx container:
$ docker compose down nginx && docker compose up -d nginx > [+] Running 2/1 > â Container mobybolt_nginx Removed 0.8s > ! Network mobybolt_default Resource is still in use 0.0s > [+] Running 1/1 > â Container mobybolt_nginx Started -
check the nginx container status (it should be
healthy, if not repeat the command):$ docker ps | grep nginx > bc38795edbb3 mobybolt/nginx:mainline "/docker-entrypoint.âĻ" 2 hours ago Up 5 minutes (healthy) 0.0.0.0:4000->4000/tcp, :::4000->4000/tcp, 80/tcp, 0.0.0.0:50002->50002/tcp, :::50002->50002/tcp mobybolt_nginx
-
Edit the tor configuration file, adding the following content at the end:
$ nano tor/torrc## Hidden Service Electrum Server HiddenServiceDir /var/lib/tor/hidden_service_electrumserver/ HiddenServiceVersion 3 HiddenServicePoWDefensesEnabled 1 HiddenServicePort 50001 172.16.21.5:50001 -
Check the tor configuration file:
$ docker exec mobybolt_tor tor -f /etc/tor/torrc --verify-config > ... > Configuration was valid -
Restart tor:
$ docker compose restart tor > [+] Restarting 1/1 > â Container mobybolt_tor Started -
check the tor container status (it should be
healthy, if not repeat the command):$ docker ps | grep tor > bfc225986e0d mobybolt/tor:0.4.8.12 "docker-entrypoint.sh" 3 hours ago Up About a minute (healthy) 9050-9051/tcp -
get your onion address:
$ docker exec mobybolt_tor cat /var/lib/tor/hidden_service_electrumserver/hostname > abcdefg..............xyz.onion
Check the Fulcrum release page for a new version and change the FULCRUM_VERSION value in the .env file.
Then, redo the steps described in:
If everything is ok, you can clear the old image and build cache, like in the following example:
$ docker images | grep fulcrum
> mobybolt/fulcrum 1.11.1 03c38d632c76 3 minutes ago 345MB
> mobybolt/fulcrum 1.10.0 3613ae3d3613 14 minutes ago 322MB
$ docker image rm mobybolt/fulcrum:1.10.0
> Untagged: mobybolt/fulcrum:0.4.8.10
> Deleted: sha256:3613ae3d36137e9e4dd38e93d40edd21b8e4aa17df5527e934aed2013087537a
$ docker buildx prune
> WARNING! This will remove all dangling build cache. Are you sure you want to continue? [y/N] y
> ID RECLAIMABLE SIZE LAST ACCESSED
> pbzeixdrvu87hv3rajkrfprr8 true 398B 24 minutes ago
> xdufppotcvx2kegu5gc3zscg6* true 621.8MB 17 minutes ago
> ...
> Total: 1.853GB
Follow the next steps to uninstall fulcrum.
-
Remove the electrumserver-reverse-proxy configuration file:
$ rm nginx/config/streams-enabled/electrumserver-reverse-proxy.conf -
Edit the nginx docker-compose file and remove the line
- "50002:50002" # electrumserverin theportssection (or remove the entireportssection, if fulcrum is the only entry) -
Test the docker-compose file:
$ docker compose config --quiet && printf "OK\n" || printf "ERROR\n" > OK -
Recreate the nginx container:
$ docker compose down nginx && docker compose up -d nginx > [+] Running 2/1 > â Container mobybolt_nginx Removed 0.8s > ! Network mobybolt_default Resource is still in use 0.0s > [+] Running 1/1 > â Container mobybolt_nginx Started -
Check the nginx container status (it should be
healthy, if not repeat the command):$ docker ps | grep nginx > bc38795edbb3 mobybolt/nginx:mainline "/docker-entrypoint.âĻ" 2 hours ago Up 5 minutes (healthy) 0.0.0.0:4000->4000/tcp, :::4000->4000/tcp, 80/tcp, 0.0.0.0:50002->50002/tcp, :::50002->50002/tcp mobybolt_nginx
-
Edit the tor configuration file (
nano tor/torrc) and remove all the Fulcrum lines added above -
Check the tor configuration file:
$ docker exec mobybolt_tor tor -f /etc/tor/torrc --verify-config > ... > Configuration was valid -
Restart tor:
$ docker compose restart tor > [+] Restarting 1/1 > â Container mobybolt_tor Started -
Check the tor container status (it should be
healthy, if not repeat the command):$ docker ps | grep tor > bfc225986e0d mobybolt/tor:0.4.8.12 "docker-entrypoint.sh" 3 hours ago Up About a minute (healthy) 9050-9051/tcp
$ docker compose down electrumserver
> [+] Running 2/1
> â Container mobybolt_fulcrum Removed
> ...
-
Edit the main docker-compose file (
nano docker-compose.yaml) and remove the Fulcrum line added above -
Test the docker-compose file:
$ docker compose config --quiet && printf "OK\n" || printf "ERROR\n" > OK
$ docker image rm $(docker images | grep fulcrum | awk '{print $3}')
> Untagged: mobybolt/fulcrum:1.11.1
> Deleted: sha256:13afebf08e29c6b9a526a6e54ab1f93e745b25080add4e37af8f08bdf6cfbcc6
$ docker buildx prune
> WARNING! This will remove all dangling build cache. Are you sure you want to continue? [y/N] y
> ID RECLAIMABLE SIZE LAST ACCESSED
> 7r8ccrpq0g0e03deu2dh53ob6* true 9.69MB 19 minutes ago
> ndrhcdo756vejnx17qm775t08* true 1.212kB 24 minutes ago
> ...
$ docker volume rm mobybolt_fulcrum-data
> mobybolt_fulcrum-data
$ rm -rf fulcrum