monostr / Watcher

Host a watcher

Run a watcher like watcher.monostr.com on your own server: with your own Monero node, under your own domain, for yourself or for others.

Only for yourself? A personal watcher is much simpler: no node, no domain, no open port, and it runs on a Raspberry Pi.

What it does

The watcher holds the private view keys of the tip wallets registered with it, detects incoming tips and publishes signed receipts on Nostr. Everything runs on one host with Docker Compose: a pruned Monero node (monerod), the scanner monero-lws, the watcher, and Caddy for HTTPS.

What you need

Already running a Monero node? See Using an existing node.

1. Install

git clone https://github.com/schmidt1024/monostr.git
cd monostr/watcher
cp .env.selfhost.example .env
chmod 600 .env
sed -i "s/^WATCHER_SECRET_KEY=.*/WATCHER_SECRET_KEY=$(openssl rand -hex 32)/" .env

Open .env in an editor and fill in:

WATCHER_DOMAIN
your domain, for example watcher.example.com
WATCHER_ALLOWED_PUBKEYS
your npub (several separated by commas). Only these accounts can register a wallet. Leave it empty only if you want to offer the watcher to everyone.
WATCHER_RELAYS
optional: the relays the watcher reads tip intents from and publishes receipts to. The default is fine.

2. Start

docker compose -f compose.selfhost.yml up -d --build
curl https://watcher.example.com/v1/info

/v1/info answers right away with the watcher's pubkey, network and height. Keep the secret key in .env safe: it is the watcher's identity, and the receipts are signed with it.

3. Wait for the sync

docker compose -f compose.selfhost.yml logs -f monerod

monerod is done when it logs You are now synchronized with the network. Then height in /v1/info is close to the current block height (compare with any block explorer). Connect the app only after that.

4. Connect the app

In monostr: Settings → Monero tips → Switch watcher (or Set up receiving Monero tips if you have not set up tips yet). Enter https://watcher.example.com as the watcher URL, tap Check watcher and register your tip wallet: its primary address and private view key.

The app removes your account from the previous watcher and announces the new one in your profile, so senders use it from then on.

Use a wallet only for tips: the view key shows the watcher every incoming payment of that wallet, not only tips. It can never spend anything.

Updates

cd monostr && git pull
cd watcher && docker compose -f compose.selfhost.yml up -d --build

The images of monerod, monero-lws and Caddy are pinned by digest in compose.selfhost.yml; a git pull brings tested new versions.

Backup

Back up .env: it holds the secret key. The watcher database lives in the volume monostr-watcher_watcher-data (watcher.db, SQLite) and holds open tips and receipts.

Losing it is not fatal: on the next start the watcher reads the last day's tip intents from the relays again and takes over the receipts it had already published instead of publishing them twice. Tips older than a day that were still open are lost. Wallets registered in monero-lws are added again the next time the app registers. The blockchain does not need a backup.

Using an existing node

monero-lws needs monerod's ZMQ interface, which public nodes do not offer. If you run monerod yourself, start it with:

--zmq-rpc-bind-ip=0.0.0.0 --zmq-rpc-bind-port=18082 --confirm-zmq-rpc-external-bind
--zmq-pub=tcp://0.0.0.0:18083

Never publish these ports to the internet. Then remove the monerod service and the monerod-data volume from your copy of compose.selfhost.yml, and point --daemon, --sub (monero-lws) and MONEROD_RPC_URL (watcher, restricted RPC) at your node, for example by attaching its Docker network.

Troubleshooting

/v1/info does not answer

Check the DNS record and that ports 80 and 443 are open. The Caddy log shows certificate errors:

docker compose -f compose.selfhost.yml logs caddy

"this watcher only accepts accounts of its operator"

Your npub is not in WATCHER_ALLOWED_PUBKEYS. After changing .env, apply it:

docker compose -f compose.selfhost.yml up -d

Tips stay unconfirmed

monerod or monero-lws is still syncing; check the logs of both.

More

The technical reference is SELFHOST.md in the repository. Questions or problems: open an issue or mention monostr on Nostr.