# Run a Pruned Bitcoin Node

### **Requirements:**

This guide is written for a Unix based system. It's reasonable to expect some modifications will be required for other operating systems.

When started, the pruned Bitcoin node will take roughly **\~24** hours to reach chain tip.

{% hint style="warning" %}
While bitcoin is syncing, it's recommended to keep a stacks-blockchain node at chain tip, or [use a stacks chainstate archive](https://docs.hiro.so/stacks/archive/guides/stacks-blockchain).
{% endhint %}

* Bitcoin Core >= v25.0
  * <https://github.com/bitcoin/bitcoin>
  * <https://bitcoincore.org/en/download/>
* Host with a minimum of:
  * 2 vCPU (a single dedicated cpu for the bitcoind process)
  * 4GB Memory (during sync, more available memory will improve sync time)
  * 50GB free disk space (actual usage is closer to 20GB)
* User account: `bitcoin:bitcoin`
* Chainstate directory located at: `/bitcoin/mainnet`
  * `bitcoin` user must have read/write access.
* Config directory located at: `/etc/bitcoin`
  * `bitcoin` user must have at least read access

### **Caveats**

[BIP-0159](https://github.com/bitcoin/bips/blob/master/bip-0159.mediawiki)

In short, this BIP specifies that pruned nodes will advertise the service bit `NODE_NETWORK_LIMITED`, which restricts syncing blocks older than 288 blocks (\~2 days).

What this means is that in practice, a stacks-blockchain node:

* **Cannot** sync from genesis using a pruned node.
* **Must not** be offline or otherwise down for longer than \~2 days (or 288 Bitcoin blocks).

***

### **Add bitcoin user and set file ownership**

```shell
$ sudo mkdir -p /bitcoin/mainnet
$ sudo mkdir /etc/bitcoin
$ sudo useradd bitcoin -d /bitcoin
$ sudo chown -R bitcoin:bitcoin /bitcoin /etc/bitcoin/
```

### **Bitcoin Config**

Below is a sample config used to sync a pruned bitcoin node - feel free to adjust as needed.

{% hint style="info" %}
If using the [systemd unit below](#systemd-unit-file), save this file as `/etc/bitcoin/bitcoin.conf`
{% endhint %}

* `btuser:btcpass` is hardcoded as an rpcauth user/password ([generated using this script](https://github.com/bitcoin/bitcoin/tree/master/share/rpcauth)).
* Only localhost access is allowed (`127.0.0.1`) on the standard mainnet ports.
* Pruning is set to be small, storing only the last 1GB of blocks (for p2p traffic, this is more than enough).
* `dbcache` is set to the maximum of 16GB.
* Wallet (and wallet rpc calls) are disabled.

```
## [rpc]
# Accept command line and JSON-RPC commands.
server=1

# Allow JSON-RPC connections from specified source.
rpcallowip=127.0.0.1/0

# Bind to given address to listen for JSON-RPC connections.
rpcbind=127.0.0.1:8332

# Username and HMAC-SHA-256 hashed password for JSON-RPC connections.
#   Use the script at https://github.com/bitcoin/bitcoin/tree/master/share/rpcauth to generate
#   Note: may be specified multiple times for different users.
rpcauth=btcuser:18857b4df4b1f0f5e6b1d7884617ab39$de6e02e1da8ee138ee702e13e0637e24679d844756216b066c3aeac4bcac5e10 # btuser:btcpass

# Optional: rpcwhitelist can restrict listed RPC calls to specific rpcauth users.
#   Uncomment the below the restrict the `limited` user to a small subset of `get` commands
# rpcauth=limited:350c91a60895b567c4662c27e63e9a41$25188b0f51f2f974dcdc75c1e0d41174e8f7ae19fb96927abf68ac5bc1e8897b # limited:limited
# rpcwhitelist=limited:getblockchaininfo,getblock,getblockcount,getblockhash,getblockheader,getnetworkinfo
# rpcwhitelistdefault=0

## [core]
# Specify data directory
datadir=/bitcoin/mainnet
# Do not keep transactions in the mempool longer than <n> hours (default: 336)
mempoolexpiry=24
# Bind to given address and always listen on it (default: 0.0.0.0)
bind=127.0.0.1:8333
# Maximum database cache size <n> MiB (4 to 16384, default: 450). In addition, unused mempool memory is shared for this cache
dbcache=16384
# Maintain a full transaction index, used by the getrawtransaction rpc call (**Running a pruned node requires that this option is disabled**)
txindex=0

# Reduce storage requirements by enabling pruning (deleting) of old
# blocks. This allows the pruneblockchain RPC to be called to
# delete specific blocks and enables automatic pruning of old
# blocks if a target size in MiB is provided. This mode is
# incompatible with -txindex. Warning: Reverting this setting
# requires re-downloading the entire blockchain. (default: 0 =
# disable pruning blocks, 1 = allow manual pruning via RPC, >=550 =
# automatically prune block files to stay under the specified
# target size in MiB)
prune=1024 # 1GB of chainstate is enough for p2p block data (if using the RPC,this can be adjusted higher to store more blocks)

## [wallet]
# Do not load the wallet and disable wallet RPC calls
disablewallet=1
```

## Systemd unit file

ref: <https://github.com/bitcoin/bitcoin/blob/master/contrib/init/bitcoind.service>

```
[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/bin/bitcoind -pid=/run/bitcoind/bitcoind.pid \
                            -conf=/etc/bitcoin/bitcoin.conf \
                            -startupnotify='systemd-notify --ready' \
                            -shutdownnotify='systemd-notify --stopping'

# Make sure the config directory is readable by the service user
PermissionsStartOnly=true
ExecStartPre=/bin/chgrp bitcoin /etc/bitcoin

# Process management
####################

Type=notify
NotifyAccess=all
PIDFile=/run/bitcoind/bitcoind.pid

Restart=on-failure
TimeoutStartSec=infinity
TimeoutStopSec=600

# Directory creation and permissions
####################################

# Run as bitcoin:bitcoin
User=bitcoin
Group=bitcoin

# /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

# Restrict ABIs to help ensure MemoryDenyWriteExecute is enforced
SystemCallArchitectures=native

[Install]
WantedBy=multi-user.target
```

### **Enable and start the Bitcoin service**

```shell
$ sudo systemctl daemon-reload
$ sudo systemctl enable bitcoin.service
$ sudo systemctl start bitcoin.service
```

{% hint style="info" %}
Once started, you may track the sync progress:

```
$ sudo tail -f /bitcoin/mainnet/debug.log
2024-12-05T19:35:31Z UpdateTip: new best=00000000000000000058990a84cc8f8eab25dbbd572f123f9190cea7256d7349 height=509258 version=0x20000000 log2_work=88.128280 tx=299522737 date='2018-02-15T03:42:14Z' progress=0.295203 cache=43.5MiB(172740txo)
...
$ bitcoin-cli \
    -rpcconnect=127.0.0.1 \
    -rpcport=8332 \
    -rpcuser=btcuser \
    -rpcpassword=btcpass \
    getblockcount
509016
```

{% endhint %}
