VMHeaven

Guides

Run your own Monero node on a VPS (monerod, step by step)

Download and verify monerod, run it as a hardened systemd service, open P2P, keep RPC private and connect your wallet over an SSH tunnel or Tor.

Updated 19 Sept 2026~7 min read

When your Monero wallet syncs through someone else’s remote node, that operator sees your IP address, when you sync and when you broadcast a transaction. That is enough to link activity to you, even though they never see your keys. Your own node removes that party. Your wallet talks only to a server you control, which validates every block itself, and in return you add a reachable peer to the network.

A VPS is a good home for it: always on, fast storage, a public IP for peers. This guide sets up monerod on Debian or Ubuntu as a locked-down systemd service. It then connects your wallet over an SSH tunnel or a Tor onion address, so the node’s RPC interface is never exposed to the internet.

What the node needs

  • SSD or NVMe storage. The unpruned blockchain runs to a few hundred gigabytes and grows every month. Plan for at least 400 GB for a full node. A pruned node keeps roughly a third of the data, still validates everything, and fits in about 150 GB. Spinning disks make the initial sync take weeks.
  • 2 GB RAM minimum, 4 GB comfortable, and two vCPUs. The initial sync is heavy on CPU and I/O. Once synced, the node is quiet.
  • Traffic. A reachable node serves blocks to peers and can move a few hundred gigabytes a month. You can cap it (below).

Download and verify monerod

Never skip verification. A tampered binary is the one attack a self-hosted node cannot protect you from.

  1. 1Install the tools
    Debian · Ubuntu
    sudo apt update && sudo apt install -y wget bzip2 gnupg
  2. 2Download the release and the signing key
    download
    cd /tmp
    wget --trust-server-names https://downloads.getmonero.org/cli/linux64
    wget -O binaryfate.asc https://raw.githubusercontent.com/monero-project/monero/master/utils/gpg_keys/binaryfate.asc
    wget -O hashes.txt https://www.getmonero.org/downloads/hashes.txt

    --trust-server-names saves the archive under its real, versioned file name, which the hash check below needs. Use linuxarm8 instead of linux64 on an ARM server.

  3. 3Check the key, then the signature
    verify the signer
    gpg --show-keys binaryfate.asc
    # fingerprint must be 81AC591FE9C4B65C5806AFC3F0AF4EA08D4EE68A
    gpg --import binaryfate.asc
    gpg --verify hashes.txt

    Look for Good signature from “binaryFate”. The warning that the key is not certified with a trusted signature is normal. A BAD signature is not normal: stop there.

  4. 4Check the archive against the signed hashes
    verify the download
    grep "$(sha256sum monero-linux-*.tar.bz2 | cut -d' ' -f1)" hashes.txt

    This must print one line containing your file name. If it prints nothing, the download does not match the signed release — delete it and try again.

  5. 5Install the binary
    install
    tar -xjf monero-linux-*.tar.bz2
    sudo install -m 0755 monero-*-linux-gnu-*/monerod /usr/local/bin/
    monerod --version

Run it as a service

A dedicated system user keeps the daemon away from everything else on the box:

user and directories
sudo useradd --system --home-dir /var/lib/monero --shell /usr/sbin/nologin monero
sudo mkdir -p /var/lib/monero /var/log/monero /etc/monero
sudo chown monero:monero /var/lib/monero /var/log/monero
/etc/monero/monerod.conf
data-dir=/var/lib/monero
log-file=/var/log/monero/monerod.log
log-level=0

# peer-to-peer: reachable from the internet
p2p-bind-ip=0.0.0.0
p2p-bind-port=18080

# RPC for your wallet: this machine only
rpc-bind-ip=127.0.0.1
rpc-bind-port=18081

# no UPnP on a server; ban known-bad peers
no-igd=1
enable-dns-blocklist=1

# optional: keep about a third of the chain, still fully validating
#prune-blockchain=1

# optional: cap bandwidth (kB/s) if your traffic allowance is tight
#limit-rate-up=1024
#limit-rate-down=4096
/etc/systemd/system/monerod.service
[Unit]
Description=Monero daemon
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=monero
Group=monero
ExecStart=/usr/local/bin/monerod --config-file=/etc/monero/monerod.conf --non-interactive
Restart=on-failure
RestartSec=30
TimeoutStopSec=120

NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=full
ProtectHome=yes

[Install]
WantedBy=multi-user.target
start and watch the sync
sudo systemctl daemon-reload
sudo systemctl enable --now monerod
sudo tail -f /var/log/monero/monerod.log

# progress, from any shell on the server
monerod status

monerod status prints the current height, the target height and a percentage. Expect the initial sync to take anywhere from several hours to a couple of days, depending mostly on disk speed.

Open the P2P port — and only that

ufw · firewalld
# ufw (Debian, Ubuntu)
sudo ufw allow 18080/tcp comment 'Monero P2P'

# firewalld (Rocky, Alma, RHEL)
sudo firewall-cmd --permanent --add-port=18080/tcp && sudo firewall-cmd --reload

Connect your wallet

Through an SSH tunnel (recommended)

on your computer
ssh -N -L 18081:127.0.0.1:18081 user@YOUR_SERVER_IP

While the tunnel runs, point the wallet at 127.0.0.1 port 18081. In the Monero GUI that is Settings → Node → Remote node; tick “mark as trusted”, because it is your node. Feather Wallet takes the same address as a custom node. On the command line:

monero-wallet-cli
monero-wallet-cli --daemon-address 127.0.0.1:18081 --trusted-daemon

Through a Tor onion address

Handy for a phone wallet, where SSH tunnels are awkward. Add a second, restricted RPC port on localhost, then publish only that port as an onion service:

append to /etc/monero/monerod.conf
rpc-restricted-bind-ip=127.0.0.1
rpc-restricted-bind-port=18089
Tor
sudo apt install -y tor
echo 'HiddenServiceDir /var/lib/tor/monero-rpc/
HiddenServicePort 18089 127.0.0.1:18089' | sudo tee -a /etc/tor/torrc

sudo systemctl restart monerod tor
sudo cat /var/lib/tor/monero-rpc/hostname     # your .onion address

Use <address>.onion:18089 as the remote node in a wallet with Tor support. On Android, route the wallet through Orbot. The restricted port serves wallets but refuses administrative calls, so a leaked onion address cannot be used to control the node.

Optional: run a public node

To let other people use your node, expose the restricted port publicly instead of on localhost, and advertise it to the network:

/etc/monero/monerod.conf
rpc-restricted-bind-ip=0.0.0.0
rpc-restricted-bind-port=18089
public-node=1
confirm-external-bind=1

Then open 18089/tcp in the firewall. Expect noticeably more traffic.

Keeping it updated

Network upgrades are hard forks: a node that has not been updated before the fork height stops following the chain. Watch the announcements on getmonero.org. For every new release, repeat the download and both verification steps in an empty directory, then:

update
sudo systemctl stop monerod
tar -xjf monero-linux-*.tar.bz2
sudo install -m 0755 monero-*-linux-gnu-*/monerod /usr/local/bin/
sudo systemctl start monerod && monerod --version

Disk getting tight later? The release archive includes monero-blockchain-prune, which converts an existing database into a pruned one.

A node is only as private as the account it runs on. Pairing it with a VPS paid in XMR keeps the payment trail out of the picture. VMHeaven’s Standard KVM plans run on replicated enterprise storage with fair-use traffic, which suits a node that is always on.

Frequently asked

Why run my own Monero node instead of a remote node?

A remote node's operator sees your IP address and when you sync and broadcast transactions. Your own node removes that party and verifies every block itself.

How much disk space does a Monero node need?

The unpruned blockchain is a few hundred gigabytes and growing, so plan for 400 GB of SSD. A pruned node stores about a third of that and still fully validates.

Is it safe to open port 18081?

No. 18081 is the unrestricted RPC interface. Open only the P2P port 18080 and reach RPC through an SSH tunnel, or publish a restricted RPC port (18089) as a Tor onion service.

More in Guides

See all