Light wallet server (monero-lws)¶
Difficulty: Hard Tested v0.18.5.3
A normal Monero wallet downloads and scans every block to find your outputs. On a phone that's slow and drains the battery. A light wallet hands its view key to a server, which scans the chain in the background, all the time, and answers "what's my balance?" right away.
monero-lws by vtnerd is a light wallet server that speaks the Monero light-wallet REST API (MyMonero-compatible). Running it on your own node keeps the speed of a light wallet without giving your view key to a third party.
What the server learns
The view key lets the server see every incoming payment and your balance, forever, for that wallet. It can't spend: the spend key never leaves your wallet app. That's exactly why this server should be yours and nobody else's.
Why it's rated Hard
- There are no release binaries. You compile monero-lws, plus the Monero code it depends on, from source. This takes 30โ90 minutes and ~4 GB of RAM, and every Monero upgrade means rebuilding.
- Few wallet apps support a custom light wallet server. Check that yours does before you start (see Connect a wallet).
Requirements¶
- 2.1 Monero node synced, with
zmq-pub=tcp://127.0.0.1:18083inmonerod.conf(part of the 2.1 config). monerod's ZMQ RPC on127.0.0.1:18082is on by default. - 2.2 Anonymous networking: wallets reach the server only over Tor
- ~10 GB of free disk space for the build
Preparations¶
Create a dedicated user and data directory:
sudo adduser --disabled-password --comment "" monero-lws
sudo mkdir /data/monero-lws
sudo chown monero-lws:monero-lws /data/monero-lws
sudo chmod 700 /data/monero-lws
chmod 700 matters here: the database in this folder holds your view keys.
Install the build dependencies, the same set as the Monero build guide for Ubuntu. monero-lws's own CI builds on Ubuntu 26.04 with these system packages, including CMake 4 and Boost 1.90:
sudo apt install -y build-essential cmake pkg-config git libssl-dev libzmq3-dev libunbound-dev \
libsodium-dev libunwind-dev liblzma-dev libreadline-dev libexpat1-dev libpgm-dev \
libhidapi-dev libusb-1.0-0-dev libprotobuf-dev protobuf-compiler libudev-dev \
libboost-all-dev
Build¶
Build in a temporary folder as nodeadmin. Pin the release and its exact commit. Check the latest at https://github.com/vtnerd/monero-lws/tags.
cd /tmp
VERSION=1.0.4
COMMIT=969b959dc16980316e34b5dcfd7c35a718684e9a
git clone --branch v$VERSION https://github.com/vtnerd/monero-lws.git
cd monero-lws
Verify the source¶
Make sure you got exactly the release commit:
The output must equal the COMMIT value above.
The release tag is signed by its author (Lee Clagett), but at the time of writing the signing key isn't published on GitHub, a keyserver or the Monero repository. So you can check which key signed it, but not tie that key to the author through an independent source:
git cat-file tag v$VERSION | sed -n '/BEGIN PGP/,/END PGP/p' > /tmp/lws-tag.sig
gpg --list-packets /tmp/lws-tag.sig | grep 'issuer fpr'
Expected: issuer fpr v4 CFC71BC34CA6BD25BE086FA33AC8C072BE0FEEF3. If the author publishes the key, import it and run git verify-tag v$VERSION for a full check.
Danger
If the commit or the fingerprint doesn't match, stop and ask for help in the community.
Compile¶
The release pins its Monero dependency (v0.18.5.3) as a git submodule:
git submodule update --init --recursive
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j$(nproc)
Out of memory?
If the build gets killed, use fewer jobs (make -j2), or make sure you have the 8 GB swap file from 1.4 Configuration.
Install¶
sudo install -m 0755 -o root -g root -t /usr/local/bin src/monero-lws-daemon src/monero-lws-admin
monero-lws-daemon --version
cd /tmp && rm -rf /tmp/monero-lws /tmp/lws-tag.sig
Autostart on boot¶
# MoneroBox: systemd unit for monero-lws
# /etc/systemd/system/monero-lws.service
[Unit]
Description=Monero light wallet server (monero-lws)
Requires=monerod.service
After=monerod.service
[Service]
User=monero-lws
Group=monero-lws
Type=simple
ExecStart=/usr/local/bin/monero-lws-daemon \
--db-path=/data/monero-lws \
--daemon=tcp://127.0.0.1:18082 \
--sub=tcp://127.0.0.1:18083 \
--rest-server=http://127.0.0.1:8443 \
--auto-accept-creation \
--log-level=1
Restart=on-failure
RestartSec=30
# Hardening
PrivateTmp=true
ProtectSystem=full
ProtectHome=true
NoNewPrivileges=true
PrivateDevices=true
[Install]
WantedBy=multi-user.target
--daemon: monerod's ZMQ RPC, which the server uses to fetch blocks.--sub: monerod's ZMQ pub feed, so new blocks are scanned the moment they arrive instead of every 20 seconds. P2Pool can share this same feed.--rest-server: the wallet API. It listens on localhost only and is reached over Tor below. The view key travels in this traffic, so it never crosses your network unencrypted.--auto-accept-creation: a wallet that logs in for the first time gets its account right away, with no approval step. See Accounts.
Reach it over Tor¶
Add an onion service for the wallet API:
# MoneroBox: monero-lws wallet API
HiddenServiceDir /var/lib/tor/monero-lws/
HiddenServicePort 80 127.0.0.1:8443
Save it in your password manager as your LWS onion, and keep it private. Your wallets use http://YOUR_LWS_ONION.onion. Tor encrypts the connection end to end, so plain http is fine here.
The onion address is the only lock
New accounts are accepted automatically, so anyone who has this address can register wallets on your server and make it scan for them, using your CPU and disk. Only give it to people you trust, and if it leaks, delete /var/lib/tor/monero-lws and reload Tor to get a new address.
Connect a wallet¶
Support for a custom light wallet server varies between apps and versions. Look for a setting like "light wallet server", "LWS" or "MyMonero-compatible server", then enter your LWS onion (with Tor enabled in the app or through Orbot).
Wallets that have supported monero-lws servers include MyMonero and Edge. Check the app's current documentation before relying on it.
Accounts¶
The first time a wallet logs in, the server creates its account automatically and starts scanning from the current block. Check the accounts and their scan progress:
Older wallets: scan from the restore height¶
A new account only sees payments from now on. For a wallet that already has history, rescan from its restore height (the block height when the wallet was created):
sudo -u monero-lws monero-lws-admin --db-path=/data/monero-lws \
rescan RESTORE_HEIGHT YOUR_PRIMARY_ADDRESS
Some apps instead send an import request, asking the server to rescan the wallet from the start of the chain. --auto-accept-creation doesn't cover these, so they wait for you:
sudo -u monero-lws monero-lws-admin --db-path=/data/monero-lws list_requests | jq
sudo -u monero-lws monero-lws-admin --db-path=/data/monero-lws accept_requests import YOUR_PRIMARY_ADDRESS
To accept those automatically too, add --auto-accept-import to the service. Each import is a full-chain scan, though, so leave it off unless you trust everyone who has the onion address.
Add a wallet by hand¶
You can also add a wallet without logging in from an app. You need its primary address and secret view key (Feather: Wallet โ Keys; monero-wallet-cli: viewkey):
sudo -u monero-lws monero-lws-admin --db-path=/data/monero-lws \
add_account YOUR_PRIMARY_ADDRESS YOUR_SECRET_VIEW_KEY
Warning
This puts your view key in the shell history. Clear it afterwards with history -c (and remove the line from ~/.bash_history), or put a space before the command so the shell skips it (Ubuntu's default HISTCONTROL=ignoreboth does).
Remove an account¶
Deleting accounts isn't supported yet. To stop scanning one, deactivate it:
sudo -u monero-lws monero-lws-admin --db-path=/data/monero-lws \
modify_account_status inactive YOUR_PRIMARY_ADDRESS
Upgrade¶
Repeat Build with the new VERSION and COMMIT, then:
Rebuild after every Monero network upgrade too. New monero-lws releases bump their pinned Monero version. Releases with a new major number (1.x โ 2.x) can change the database format. Read the release notes, and back up /data/monero-lws first.
Uninstall¶
sudo systemctl disable --now monero-lws
sudo rm /etc/systemd/system/monero-lws.service /usr/local/bin/monero-lws-*
sudo rm -rf /data/monero-lws # deletes the stored view keys
sudo deluser --remove-home monero-lws
Remove the monero-lws block from /etc/tor/torrc, then run sudo systemctl reload tor and sudo rm -rf /var/lib/tor/monero-lws.