Install

Get Software

Get source code

git clone https://github.com/bitcoin/bitcoin.git

or the binaries at

curl https://bitcoincore.org/bin

# select version

curl https://bitcoincore.org/bin/bitcoin-core-22.1/bitcoin-22.1-x86_64-linux-gnu.tar.gz

Install from source

Install build dependencies and build:

# cd bitcoin/

# cmake -B build
...
# cmake --build build
...
# ctest --test-dir build
...
# cmake --install build
...

Install binaries

# tar -xvzf bitcoin-22.1-x86_64-linux-gnu.tar.gz
...
# install -m 0755 -o root -g root -t /usr/local/bin bitcoin-22.1/bin/*
# install -m 0755 -o root -g root -t /usr/local/lib/ bitcoin-22.1/lib/*
# install -m 0755 -o root -g root -t /usr/local/include/ bitcoin-22.1/include/*
# install -m 0755 -o root -g root -t /usr/local/share/man/man1 bitcoin-22.1/share/man/man1/*

Create user

# groupadd --system bitcoin
# adduser --system -g bitcoin --home /opt/bitcoind bitcoin

Configuration

Config File

Create folder

Be sure to have at least 700GB (Aug 2025) disk space available !!
In my case I’m putting the blockchain on a dedicated 1TB LVM volume using XFS filesystem which is optimized for smaller files sizes.

# lvcreate -L 1T -n bitcoind vg1
# mkfs.xfs /dev/vg1/bitcoind
# mount /dev/vg1/bitcoind /opt/bitcoind
# chown -R bitcoin:bitcoin /opt/bitcoind

# su - bitcoin
$ mkdir ~/.bitcoin

Create File ~/.bitcoin/bitcoin.conf:

# Bitcoin Core Konfiguration
# Allgemeine Einstellungen
daemon=1 # Run in background
server=1 # Aktiviert die RPC-Schnittstelle
datadir=/opt/bitcoind/.bitcoin/data
txindex=1 # Aktiviert Transaktionsindex für beliebige Abfragen
blocknotify=/opt/bitcoind/blocknotify.sh %s # Skript für Blockbenachrichtigungen

# Netzwerk
listen=1 # Akzeptiert eingehende P2P-Verbindungen
maxconnections=50 # Maximale Anzahl an Peers
port=8333 # Standard-P2P-Port für Mainnet

# Nodes
# this will connect exclusively to trusted-node-ip
# if you dont want to run a full node.
#connect=trusted-node-ip:8333

# RPC-Schnittstelle
rpcuser=thor
rpcpassword=password
rpcallowip=127.0.0.1 # Lokaler Zugriff
rpcallowip=192.168.1.0/24 # other allowed local network
rpcport=8332 # Standard-RPC-Port
rpcbind=0.0.0.0 # Bindet RPC an alle Schnittstellen
rpcthreads=4 # Anzahl der Threads für RPC

# Sicherheit
rpcssl=1 # Aktiviert SSL für RPC
rpcsslcertificatechainfile=/opt/bitcoind/.bitcoin/server.cert
rpcsslprivatekeyfile=/opt/bitcoind/.bitcoin/server.key

# Wallet
wallet=/opt/bitcoind/.bitcoin/wallets/main_wallet
walletnotify=/opt/bitcoind/walletnotify.sh %s # Skript für Wallet-Benachrichtigungen

Create SSL Keys

# openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /opt/bitcoind/.bitcoin/server.key -out /opt/bitcoind/.bitcoin/server.cert

# chmod 600 /opt/bitcoind/.bitcoin/server.key
# chmod 644 /opt/bitcoind/.bitcoin/server.cert
# chown bitcoin:bitcoin /opt/bitcoind/.bitcoin/server.*

Blocknotify Script (example)

#!/bin/bash
BLOCK_HASH=$1
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
BLOCK_HEIGHT=$(bitcoin-cli getblockheader $BLOCK_HASH | jq -r '.height')

# E-Mail-Versand mit mail (mailutils muss installiert sein)
SUBJECT="Neuer Bitcoin-Block erkannt: Höhe $BLOCK_HEIGHT"
MESSAGE="Ein neuer Block wurde erkannt!\nBlockhash: $BLOCK_HASH\nHöhe: $BLOCK_HEIGHT\nZeitpunkt: $TIMESTAMP"
echo -e "$MESSAGE" | mail -s "$SUBJECT" admin@example.com

# Optional: Log in Datei schreiben
echo "$TIMESTAMP: Neuer Block $BLOCK_HEIGHT mit Hash $BLOCK_HASH" >> /var/log/bitcoin_blocks.log

Walletnotify Script (example)

#!/bin/bash
TXID=$1
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
TX_DETAILS=$(bitcoin-cli gettransaction $TXID)
AMOUNT=$(echo $TX_DETAILS | jq -r '.amount')
ADDRESS=$(echo $TX_DETAILS | jq -r '.details[0].address')
CONFIRMATIONS=$(echo $TX_DETAILS | jq -r '.confirmations')

# Nur eingehende Zahlungen verarbeiten (amount > 0)
if (( $(echo "$AMOUNT > 0" | bc -l) )); then
    # HTTP-POST an einen Zahlungsprozessor (z. B. Webhook)
    curl -X POST https://example.com/webhook \
         -H "Content-Type: application/json" \
         -d "{\"txid\":\"$TXID\",\"amount\":$AMOUNT,\"address\":\"$ADDRESS\",\"confirmations\":$CONFIRMATIONS,\"timestamp\":\"$TIMESTAMP\"}"

    # Log in Datei schreiben
    echo "$TIMESTAMP: Eingehende Zahlung von $AMOUNT BTC an $ADDRESS (txid: $TXID, confirmations: $CONFIRMATIONS)" >> /var/log/bitcoin_wallet.log
fi

Firewall

At least open the default P2P port

# iptables -A INPUT -p tcp --dport 8333 -j ACCEPT
# ip6tables -A INPUT -p tcp --dport 8333 -j ACCEPT

Start daemon

Create systemd unit file

/etc/systemd/system/bitcoind.service

[Unit]
Description=Bitcoin Core Daemon
After=network.target

[Service]
ExecStart=/usr/local/bin/bitcoind -daemon -conf=/opt/bitcoind/.bitcoin/bitcoin.conf -pid=/opt/bitcoind/.bitcoin/bitcoind.pid
ExecStop=/usr/local/bin/bitcoin-cli -conf=/opt/bitcoind/.bitcoin/bitcoin.conf stop
User=bitcoin
Group=bitcoin
Type=forking
PIDFile=/opt/bitcoind/.bitcoin/bitcoind.pid
Restart=always
RestartSec=30
TimeoutSec=300
RuntimeDirectory=bitcoind
WorkingDirectory=/opt/bitcoind/.bitcoin
PrivateTmp=true
ProtectSystem=full
NoNewPrivileges=true
# If systemd supports it include:
MemoryDenyWriteExecute=true

[Install]
WantedBy=multi-user.target

Start daemon

Reload systemd

systemctl daemon-reload

Start bitcoind

Be sure your system/volume has at least 700GB of free space!
Starting your full node will download the entire BTC blockchain which is
at around 600GB and 909844 blocks right now (Aug 2025).

Downloading the blockchain will last for hours if not days or weeks – depending on your bandwidth and available CPU power.

# systemctl start bitcoind

# systemctl enable bitcoind

Logging

The default log location is /opt/bitcoind/.bitcoin/data/debug.log
Check the log for errors!

# tail -f /opt/bitcoind/.bitcoin/data/debug.log

2025-08-13T11:26:30Z UpdateTip: new best=00000000000000000004089e9d9d4f0ea035101660fd9cac317f85f1e6a4d5de height=804792 version=0x2000e000 log2_work=94.380085 tx=884374807 date='2023-08-25T11:51:24Z' progress=0.854459 cache=302.8MiB(1958446txo)
2025-08-13T11:26:40Z UpdateTip: new best=00000000000000000002aecfbe1fb51a5c5194aa4dfd57894b23ac2c495312dd height=804793 version=0x2a34a000 log2_work=94.380099 tx=884380001 date='2023-08-25T11:55:43Z' progress=0.854460 cache=303.1MiB(1961770txo)
2025-08-13T11:26:59Z UpdateTip: new best=0000000000000000000417948e364c647805f4668b6385c2a002f697e13772a3 height=804794 version=0x20e00000 log2_work=94.380112 tx=884382128 date='2023-08-25T12:05:51Z' progress=0.854462 cache=303.3MiB(1962949txo)
2025-08-13T11:27:40Z UpdateTip: new best=00000000000000000002c98c332fd346160c70e8ea09e2c212391d0b46f458e6 height=804795 version=0x20014000 log2_work=94.380125 tx=884384892 date='2023-08-25T12:18:54Z' progress=0.854464 cache=304.3MiB(1971225txo)
2025-08-13T11:27:40Z New outbound peer connected: version: 70016, blocks=909845, peer=4748 (outbound-full-relay)
2025-08-13T11:27:41Z Synchronizing blockheaders, height: 909845 (~100.00%)
2025-08-13T11:27:41Z New outbound peer connected: version: 70016, blocks=909845, peer=4749 (outbound-full-relay)
2025-08-13T11:27:42Z New outbound peer connected: version: 70016, blocks=909845, peer=4750 (outbound-full-relay)
2025-08-13T11:28:19Z UpdateTip: new best=0000000000000000000052b63be93b66258c6482040031c270da86dd4c4d4bb1 height=804796 version=0x33822000 log2_work=94.380139 tx=884388104 date='2023-08-25T12:57:36Z' progress=0.854469 cache=305.3MiB(1979267txo)
2025-08-13T12:40:27Z Synchronizing blockheaders, height: 909853 (~100.00%)

If everything is fine in the logs your bitcoind starts up.
As you can see in the exanple output above, you will find messages about

  • New blocks downloaded from the update peers
  • New peers that get connected
  • Or peers getting disconnected because of stalling download
  • The current block height that is going to be synchronized / downloaded.

Rotate the logs!
Be sure to include copytruncate. Even there is a risk of loosing data, bitcoind dues not support signals like HUP and thus you need to restart bitcoind after rotating the logfile! Using copytruncate will avoid restarting the daemon.

# cat /etc/logrotate.d/bitcoind

/opt/bitcoind/.bitcoin/data/debug.log {
        create 600 bitcoin bitcoin
        daily
        rotate 14
        compress
        delaycompress
        missingok
        notifempty
        copytruncate
}

bitcoin-cli

Add the following 2 parameters to any of the following commands as defined in your bitcoin.conf

-rpcuser=thor 
-rpcpassword=password

Create Wallet

With automatically generated Seed-Phrase

bitcoin-cli -named createwallet wallet_name=ThorWallet descriptors=true blank=false

Create an address for your wallet

Wallet addresses that have been created can’t be deleted anymore without deleting the whole wallet.

# bitcoin-cli getnewaddress
<ADDRESS>

Import watch-only Address

Import watch only address <ADDRESS> with a label Thor-Label and rescan blockchain set to False
Doing no rescan is quicker but you can’t find any old transactions only future transactions can be searched.

bitcoin-cli importaddress "<ADDRESS>" "Thor-Label" False

Show the result

# bitcoin-cli getaddressinfo <ADDRESS>
{
  "address": "<ADDRESS>",
  "scriptPubKey": "b914...cb87",
  "ismine": false,
  "solvable": false,
  "iswatchonly": true,
  "isscript": true,
  "iswitness": false,
  "ischange": false,
  "timestamp": 1,
  "labels": [
    "Thor-Label"
  ]
}

List Addresses in your Wallet

List all addresses including ‘watch-only’ addresses and those that have no transactions

# bitcoin-cli -named listreceivedbyaddress minconf=0 include_empty=true
[
  {
    "address": "<ADDRESS>",
    "amount": 0.00000000,
    "confirmations": 0,
    "label": "Thor-Label",
    "txids": [
    ]
  }
  {
    [...]
  }
]

Maybe you want to pass output to ‘jq’

Example 1

bitcoin-cli -named listreceivedbyaddress minconf=0 include_empty=true | jq '.[].address'
"3GS...Bt"
"3MZ...uV"
"bc1...m74"
"bc1...d2j"
"bc1...5yx"

Example 2

$ bitcoin-cli -named listreceivedbyaddress minconf=0 include_empty=true include_watchonly=true | jq '.[] | {address: .address, amount: .amount}'
{
  "address": "3GS...Bt",
  "amount": 0
}
{
  "address": "3MZ...uV",
  "amount": 0
}
{
  "address": "bc1...m74",
  "amount": 0
}
{
  "address": "bc1...d2j",
  "amount": 0
}
{
  "address": "bc1...5yx",
  "amount": 0
}

To be continued…

Leave a Reply