A Blog by Expatriotic

Node: Mempool

Tip jar 🫙 expatriotic@walletofsatoshi.com

Donations
Bitcoin paynym = +expatriotic
Monero QR

88D6SZFBA6fFhYGdnY4c57dTAJD6jyqRTfCKwHjZrfdnhd8phAMYnDQWSJrqyAmgVHV7mDU6soaHogZvno1AUXp79DwtWvK

Why Run Your Own Mempool?

When you use a public block explorer like mempool.space, you are broadcasting your interest in specific transactions and addresses to the server's operator. This leaks your IP address and links it to your on-chain activity, a significant privacy gap.

The only sovereign solution is to run your own instance.

Mempool.space is not a single program but a multi-service stack, requiring a web frontend, a backend API, and a database. Attempting a "bare metal" install is complex. The official and most robust method is using Docker.

Think of Docker as a system for running pre-packaged, isolated "apps." We will simply provide a docker-compose.yml "blueprint" file that tells Docker how to connect these apps to your existing Bitcoin Core and Fulcrum nodes.

Prerequisites: Your Foundation

This guide assumes you have an Ubuntu server with the following already installed, fully synced, and running.

  1. A Synced Bitcoin Core Node:

    • Your bitcoin.conf file must have txindex=1 and ZMQ enabled.

    Example: /home/satoshis/.bitcoin/bitcoin.conf

    txindex=1
    rpcbind=127.0.0.1
    rpcport=8332
    rpcuser=YOUR_USER_NAME
    rpcpassword=YOUR_VERY_STRONG_PASSWORD
    
    # ZMQ (ZeroMQ)
    
    zmqpubrawblock=tcp://127.0.0.1:28332
    zmqpubrawtx=tcp://127.0.0.1:28333
    zmqpubhashblock=tcp://127.0.0.1:28334
    
  2. A Synced Fulcrum Electrum Server:

    • Your Fulcrum node must be configured to listen for wallet connections. This guide uses the unencrypted tcp port, which is perfectly secure on an internal network (like Docker's or your LAN).

    Example: /home/satoshis/fulcrum/fulcrum.conf

    # --- Bitcoin Daemon ---
    bitcoind = 127.0.0.1:8332
    rpcuser = YOUR_USER_NAME
    rpcpassword = YOUR_VERY_STRONG_PASSWORD
    
    
    # --- Server Ports ---
    
    # This is for wallets like Eigenwallet
    
    tcp = 0.0.0.0:50001
    
    # This is for SSL-capable wallets like Sparrow
    
    ssl = 0.0.0.0:50002
    cert = /home/satoshis/fulcrum/cert.pem
    key = /home/satoshis/fulcrum/key.pem
    

Phase 1: Install the Docker Engine

First, we install the Docker engine that will run our containers.

1. Add Docker's Security Key

This verifies the authenticity of the software we're about to install.

# Update your package list and install prerequisites
sudo apt-get update
sudo apt-get install ca-certificates curl
# Add Docker's official GPG key
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

2. Add the Docker Repository

This tells your system's package manager (apt) where to find the Docker packages.

# This is one single command, broken up with \ for readability
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

3. Install Docker

Now we install the engine, command-line tools (CLI), and the docker-compose plugin, which reads our blueprint file.

sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

4. (CRITICAL) Add Your User to the docker Group

This is the most common failure point. The Docker "daemon" (the service) runs as root. By default, only the root user can interact with it. This step adds your user to the special docker group, granting you permission.

# Replace 'satoshis' with your own username
sudo usermod -aG docker satoshis

IMPORTANT: This permission change only applies to new terminal sessions. For the change to take effect, you MUST log out of your SSH session and log back in before proceeding.

exit


Phase 2: Prepare the Mempool Environment

After logging back in, we'll download the docker-compose.yml blueprint from the official Mempool project.

# Go to your home directory
cd ~
# Clone the project from GitHub
git clone https://github.com/mempool/mempool.git
# Move into the new docker directory
cd mempool/docker

You are now in the directory with the blueprint file we need to edit.


Phase 3: Find Your Host's "Secret Passageway" IP

This is a vital concept. Your new Mempool container is an isolated box. When it thinks of 127.0.0.1 (localhost), it's talking to itself, not to your main server.

To talk to your Bitcoin and Fulcrum nodes (which are on the "host" server), the container needs the host's IP address on the internal Docker network, known as docker0.

Run this command on your node to find it:

ip addr show docker0 | grep "inet\b" | awk '{print $2}' | cut -d/ -f1

The output will almost certainly be 172.17.0.1. This is the "secret passageway" from the container back to your main server.


Phase 4: Configure the docker-compose.yml Blueprint

It's time to write our blueprint. The default file is complex; we'll use a cleaner version tailored for our setup.

1. Back up the original file (just in case):

cp docker-compose.yml docker-compose.original.yml

2. Open the file for editing:

nano docker-compose.yml

3. Delete everything in that file and paste in this entire new configuration. I have commented every line to explain what it does. See my nano guide for help, or just follow the 3 commands below.

  1. ctrl + 6 marks the beginning of text to be cut
  2. ctrl + / + 999 jumps to the end whilst marking
  3. ctrl + k cuts the selected text

You must edit the CORE_RPC_USERNAME and CORE_RPC_PASSWORD to match your bitcoin.conf.

# This is the blueprint for our Mempool stack
# We removed 'version: "3.7"' as it's obsolete and causes a warning.

services:
  # 1. The Web Frontend (what you see)
  web:
    image: mempool/frontend:latest # Use the latest official image
    container_name: mempool-web
    restart: unless-stopped
    ports:
      # This connects your server's port 8080 to the container's port 8080
      # You will access your instance at http://YOUR_NODE_IP:8080
      - "8080:8080"
    environment:
      FRONTEND_HTTP_PORT: "8080"
      BACKEND_MAINNET_HTTP_HOST: "api" # Tells the frontend to get data from the 'api' container
    depends_on:
      - api # Won't start until the 'api' is running

  # 2. The Backend API (the brain)
  api:
    image: mempool/backend:latest
    container_name: mempool-api
    restart: unless-stopped
    depends_on:
      - db # Won't start until the 'db' is running
    volumes:
      - ./data:/data # Saves mempool's cache to your server's disk
    environment:
      # --- Connection to Fulcrum (Electrum) ---
      MEMPOOL_BACKEND: "electrum"
      ELECTRUM_HOST: "172.17.0.1"     # [REPLACE IF YOURS WAS DIFFERENT] The 'docker0' IP from Phase 3
      ELECTRUM_PORT: "50001"          # Your Fulcrum's unencrypted TCP port
      ELECTRUM_TLS_ENABLED: "false"

      # --- Connection to Bitcoin Core ---
      CORE_RPC_HOST: "172.17.0.1"     # [REPLACE IF YOURS WAS DIFFERENT] The 'docker0' IP from Phase 3
      CORE_RPC_PORT: "8332"
      
      # [REPLACE THESE VALUES]
      # These MUST match your bitcoin.conf
      CORE_RPC_USERNAME: "YOUR_USER_NAME"
      CORE_RPC_PASSWORD: "YOUR_VERY_STRONG_PASSWORD"

      # --- Connection to the Database ---
      DATABASE_HOST: "db"             # Tells the API to find the 'db' container
      DATABASE_DATABASE: "mempool"
      DATABASE_USERNAME: "mempool"
      DATABASE_PASSWORD: "mempool"

  # 3. The Database (the memory)
  db:
    image: mariadb:10.5               # A MariaDB (MySQL) database
    container_name: mempool-db
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: "mempool"
      MYSQL_USER: "mempool"
      MYSQL_PASSWORD: "mempool"
      MYSQL_ROOT_PASSWORD: "admin"    # Internal password, you don't need to change this
    volumes:
      - ./mysql/data:/var/lib/mysql  # Saves the database to your server's disk

4. Save and Exit: Press Ctrl+X, then Y, then Enter.


Phase 5: Launch and Secure

The blueprint is written. This single command tells Docker to build, connect, and run all three containers in the background.

docker compose up -d

Common Sticking Point: "Permission Denied"

If you immediately get a permission denied while trying to connect to the Docker daemon socket error, it means you did not log out and log back in after Phase 1, Step 4.

The Fix:

  1. Log out: exit
  2. Log back in: ssh satoshis@node
  3. Go back to the directory: cd ~/mempool/docker
  4. Run the command again: docker compose up -d

Docker will now download the images. This may take a few minutes.

While it works, let's open your server's firewall to allow access to the web frontend from your LAN.

sudo ufw allow 8080/tcp
sudo ufw reload

Phase 6: Access Your Private Mempool

You're done. You can check that all three containers are running with:

docker compose ps

You should see mempool-web, mempool-api, and mempool-db all in an "up" or "running" state.

Open a web browser on your desktop computer (not the server) and navigate to your node's IP address on port 8080.

You will see your own private, self-hosted Mempool.space instance. It may take 5-10 minutes to populate its graphs and sync with your node, but you are now fully self-sovereign.

Maintenance: How to Stop and Update