Appearance
How to run a pruned Bitcoin Core node on a VPS
A Bitcoin Core full node checks every block and transaction against the consensus rules itself, so you do not have to trust anyone else's view of the chain. A pruned node does the same validation but keeps only the most recent blocks on disk. This guide installs Bitcoin Core on Ubuntu 24.04, verifies the download, configures pruning and runs bitcoind as a systemd service.
What you need
- A VPS with 2 vCPU, 4 GB RAM and 64 GB of disk. On DataPasa that is the VPS-3 plan. Our crypto node VPS page lists plan recommendations for other networks too.
- Ubuntu 24.04 and SSH access as root. See how to connect via SSH.
- Enough traffic for the first sync. More on that below.
You can pay for the server with BTC or other coins, see crypto VPS hosting.
Pruning does not save traffic
A pruned node still downloads and verifies the whole blockchain once, from the first block to today. That is well over 700 GB of download, plus upload to other peers. VPS-1 includes only 1 TB of traffic per month, so it is not a good fit. VPS-2 and larger plans include 32 TB.
Step 1. Download Bitcoin Core
Open the official download page and note the latest version number. Set it in a variable, for example if the page shows 31.1:
bash
VERSION=31.1
cd /tmp
wget https://bitcoincore.org/bin/bitcoin-core-${VERSION}/bitcoin-${VERSION}-x86_64-linux-gnu.tar.gz
wget https://bitcoincore.org/bin/bitcoin-core-${VERSION}/SHA256SUMS
wget https://bitcoincore.org/bin/bitcoin-core-${VERSION}/SHA256SUMS.ascStep 2. Verify the checksum and signatures
First check that the archive matches the list of checksums:
bash
sha256sum --ignore-missing --check SHA256SUMSThe output must end with bitcoin-VERSION-x86_64-linux-gnu.tar.gz: OK.
The checksum file itself is signed by several Bitcoin Core builders. Import their public keys from the guix.sigs repository and check the signatures:
bash
apt install -y git gnupg
git clone https://github.com/bitcoin-core/guix.sigs
gpg --import guix.sigs/builder-keys/*
gpg --verify SHA256SUMS.asc SHA256SUMSYou should see several lines starting with gpg: Good signature. Warnings that a key is "not certified with a trusted signature" are normal unless you have built a web of trust. Warnings about missing public keys can be ignored as long as the signers you trust are present.
Stop if verification fails
If a checksum does not match or no good signatures appear, delete the files and download them again. Never run a binary that failed verification.
Step 3. Install the binaries
Unpack the archive and copy the daemon and the command line client:
bash
tar -xzf bitcoin-${VERSION}-x86_64-linux-gnu.tar.gz
install -m 0755 -o root -g root -t /usr/local/bin bitcoin-${VERSION}/bin/bitcoind bitcoin-${VERSION}/bin/bitcoin-cli
bitcoind -versionCreate a system user that will run the node:
bash
useradd --system --no-create-home --shell /usr/sbin/nologin bitcoinStep 4. Write bitcoin.conf
The service below keeps its configuration in /etc/bitcoin and its data in /var/lib/bitcoind, the same layout as the official systemd unit from the Bitcoin Core repository.
bash
mkdir -p /etc/bitcoin
nano /etc/bitcoin/bitcoin.confPaste this configuration:
ini
server=1
prune=10000
dbcache=2048
maxconnections=40prune=10000keeps about 10,000 MiB (roughly 10 GB) of recent blocks. The minimum allowed value is550. A larger value leaves more history for rescans.dbcache=2048gives the UTXO cache 2 GB of RAM, which speeds up the initial sync a lot. On a 4 GB server lower it to1024or remove the line after the sync is done.server=1enables the local RPC interface forbitcoin-cli. RPC listens only on localhost by default, keep it that way.
The chain state database is stored in addition to the pruned blocks and grows over time, so a 64 GB disk leaves comfortable room.
Set the permissions so the service user can read the file:
bash
chown -R root:bitcoin /etc/bitcoin
chmod 0710 /etc/bitcoin
chmod 0640 /etc/bitcoin/bitcoin.confStep 5. Create the systemd service
Create /etc/systemd/system/bitcoind.service:
bash
nano /etc/systemd/system/bitcoind.serviceThis unit is based on contrib/init/bitcoind.service from the Bitcoin Core repository, with the binary path changed to /usr/local/bin:
ini
[Unit]
Description=Bitcoin daemon
After=network-online.target
Wants=network-online.target
[Service]
ExecStart=/usr/local/bin/bitcoind -pid=/run/bitcoind/bitcoind.pid \
-conf=/etc/bitcoin/bitcoin.conf \
-datadir=/var/lib/bitcoind \
-startupnotify='systemd-notify --ready' \
-shutdownnotify='systemd-notify --stopping'
Type=notify
NotifyAccess=all
PIDFile=/run/bitcoind/bitcoind.pid
Restart=on-failure
TimeoutStartSec=infinity
TimeoutStopSec=600
User=bitcoin
Group=bitcoin
RuntimeDirectory=bitcoind
RuntimeDirectoryMode=0710
StateDirectory=bitcoind
StateDirectoryMode=0710
PrivateTmp=true
ProtectSystem=full
ProtectHome=true
NoNewPrivileges=true
PrivateDevices=true
MemoryDenyWriteExecute=true
[Install]
WantedBy=multi-user.targetThe long TimeoutStopSec matters: on shutdown bitcoind flushes its cache to disk, and killing it early can force a slow reindex.
Start the node and enable it at boot:
bash
systemctl daemon-reload
systemctl enable --now bitcoind
systemctl status bitcoindStep 6. Follow the initial block download
Run bitcoin-cli as the bitcoin user so it can read the RPC cookie in the data directory:
bash
sudo -u bitcoin bitcoin-cli -datadir=/var/lib/bitcoind getblockchaininfoWatch these fields:
| Field | Meaning |
|---|---|
blocks / headers | Validated blocks versus known headers. Headers sync first, then blocks catch up. |
verificationprogress | Progress from 0 to 1. It is not linear, recent blocks are heavier. |
initialblockdownload | true until the node has caught up with the network. |
pruned | Should be true. |
size_on_disk | Stays near your prune target plus a small buffer. |
Other useful checks:
bash
sudo -u bitcoin bitcoin-cli -datadir=/var/lib/bitcoind getnetworkinfo
sudo -u bitcoin bitcoin-cli -datadir=/var/lib/bitcoind getconnectioncount
journalctl -u bitcoind -fOn a 2 vCPU server the initial sync usually takes from one to several days. CPU and disk speed matter more than bandwidth here. You can close the SSH session, the service keeps running.
Accept incoming peers
Outgoing connections are enough for your own node. If you want to help the network, allow port 8333: ufw allow 8333/tcp. A pruned node can relay new blocks and transactions but cannot serve old blocks.
Limit traffic after the sync
Once initialblockdownload is false, daily traffic drops a lot. If you want to cap upload, add a daily target in MiB to bitcoin.conf, for example maxuploadtarget=5000, and restart with systemctl restart bitcoind. Bitcoin.org recommends not going below 144 MiB per day.
What pruning cannot do
- The node cannot serve historical blocks to other peers.
txindex=1is not compatible with pruning, so you cannot look up arbitrary old transactions.- Rescanning a wallet older than the kept blocks requires a full resync.
If you need these features, you need an unpruned node with over 1 TB of disk.
Summary
You downloaded and verified Bitcoin Core, set prune and dbcache, and run bitcoind as a hardened systemd service. After the first sync the node validates new blocks on its own. If you are interested in Lightning payments, the LND with Neutrino guide shows a lighter setup that does not need a local bitcoind at all.