Installing Monero
Build the Monero node the addon depends on — monerod and monero-wallet-rpc as supervised services, the RPC credentials the backend expects, the licence and chain row, and the master wallet.
Installing this addon is mostly not a Bicrypto task. Two thirds of the work is standing up a Monero node and a wallet RPC service on the same box as the backend, and then waiting for the blockchain to sync. Plan a day, most of which is unattended.
Before you begin
- Ecosystem installed, its extension enabled and its vault unlocked
- Root on the server, and a non-root user to own the Monero services
- 250 GB of free SSD and headroom — the Monero blockchain grows continuously
- 4 GB RAM free for
monerodalone, on top of the platform's own needs - The licence for this product activated, so
lic/54578959.licexists
Initial sync verifies every block. On anything but local SSD it does not finish in a useful amount of time, and once it is running, wallet refreshes go from seconds to minutes — which on this chain means deposits arrive late and withdrawals time out.
1. Install the Monero binaries
Take the official CLI bundle. Check getmonero.org for the current stable version and substitute it below.
sudo apt update
sudo apt install -y wget bzip2
# Replace with the current stable version from getmonero.org
MONERO_VERSION="0.18.3.1"
mkdir -p ~/monero && cd ~/monero
wget "https://downloads.getmonero.org/cli/monero-linux-x64-v${MONERO_VERSION}.tar.bz2"
tar -xf "monero-linux-x64-v${MONERO_VERSION}.tar.bz2"
sudo mv "monero-x86_64-linux-gnu-v${MONERO_VERSION}" /opt/monero
sudo ln -sf /opt/monero/monerod /usr/local/bin/monerod
sudo ln -sf /opt/monero/monero-wallet-rpc /usr/local/bin/monero-wallet-rpc
monerod --version
monero-wallet-rpc --version2. Configure and start monerod
The backend holds exactly one RPC username and password —
XMR_RPC_USER and XMR_RPC_PASSWORD — and sends it to monerod and to
monero-wallet-rpc, and forwards it again as the daemon login when it points
the wallet RPC at the daemon.
Give both services the same --rpc-login. Two different logins cannot both
work, and the half that fails does so as an HTTP 401 buried in the wallet
refresh path, which surfaces as "deposits are not being detected".
data-dir=/home/monero/.bitmonero
log-file=/home/monero/.bitmonero/monero.log
log-level=0
p2p-bind-ip=0.0.0.0
p2p-bind-port=18080
rpc-bind-ip=127.0.0.1
rpc-bind-port=18081
restricted-rpc=false
confirm-external-bind=true
rpc-login=bicrypto_rpc:CHANGE_ME
db-sync-mode=safe
max-concurrency=4
no-igd=truerestricted-rpc=false matters: the addon calls get_fee_estimate and reads
synchronized out of get_info, and a restricted daemon does not serve the
full picture. Keep rpc-bind-ip on loopback — the backend runs on the same
host, and there is no reason to expose an unrestricted daemon RPC.
Then supervise it:
[Unit]
Description=Monero Daemon
After=network.target
[Service]
Type=simple
User=monero
Group=monero
ExecStart=/usr/local/bin/monerod --config-file=/home/monero/.bitmonero/bitmonero.conf --non-interactive
Restart=always
RestartSec=30
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable --now monerod
sudo journalctl -u monerod -f3. Wait for the sync — and confirm it
This is the long part. Initial sync commonly takes a day or more. Do not continue past this point on an unsynced daemon: fee estimation and wallet refresh both come from here, so an unsynced node produces a chain that looks enabled and credits nothing.
curl -s -X POST http://127.0.0.1:18081/json_rpc \
-H 'Content-Type: application/json' \
--digest -u bicrypto_rpc:CHANGE_ME \
-d '{"jsonrpc":"2.0","id":"0","method":"get_info"}'You want "synchronized": true, a height that matches a public block
explorer, and the nettype you intend to run. Note --digest — both services
use HTTP Digest authentication, not Basic.
Disk is the usual reason this stalls. monerod --prune-blockchain cuts the
on-disk footprint substantially and wallets still sync against a pruned node;
decide before the first sync, not after.
4. Run monero-wallet-rpc
sudo -u monero mkdir -p /home/monero/monero-wallets[Unit]
Description=Monero Wallet RPC
After=network.target monerod.service
Requires=monerod.service
[Service]
Type=simple
User=monero
Group=monero
ExecStart=/usr/local/bin/monero-wallet-rpc \
--rpc-bind-ip 127.0.0.1 \
--rpc-bind-port 18083 \
--daemon-address 127.0.0.1:18081 \
--daemon-login bicrypto_rpc:CHANGE_ME \
--rpc-login bicrypto_rpc:CHANGE_ME \
--wallet-dir /home/monero/monero-wallets \
--trusted-daemon \
--log-level 1
Restart=always
RestartSec=30
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable --now monero-wallet-rpcThree flags decide whether this works at all:
--wallet-diris mandatory. The addon creates and opens wallets by filename — the ECO wallet's UUID for users,master_walletfor the platform. Starting with--wallet-fileinstead binds one wallet and everyopen_walletfails.--daemon-addressand--daemon-loginshould match the daemon, though the backend re-issuesset_daemonat startup and after any daemon-related refresh failure, so a wallet RPC started without them recovers.--rpc-loginmust match the daemon's. See the warning above.
If you would rather not run authentication at all, start both services with
--disable-rpc-login and leave XMR_RPC_USER and XMR_RPC_PASSWORD unset.
Only do that when both listeners are on loopback.
The addon passes an empty password to create_wallet and open_wallet. There
is no setting that changes this — XMR_WALLET_PASSWORD is read by no code. If
--wallet-dir points at a directory holding wallets some other tool created
with a password, the backend cannot open them, and the failure looks like a
generic "Failed to open wallet".
Treat the wallet directory as key material. Its file permissions are the only thing protecting every customer's Monero private keys.
5. Configure the backend
Add these to the project root .env. None of them are in .env.example.
XMR_DAEMON_RPC_URL="http://127.0.0.1:18081/json_rpc"
XMR_WALLET_RPC_URL="http://127.0.0.1:18083/json_rpc"
XMR_RPC_USER="bicrypto_rpc"
XMR_RPC_PASSWORD="CHANGE_ME"
XMR_NETWORK="mainnet"Both URLs must include the /json_rpc path and must not embed credentials.
A user:pass@host URL is rejected by the diagnostics precisely so it never
leaks into an error message. Full detail in
Configuring the RPC connection.
Restart the backend — the service reads these once, at construction.
pm2 restart backend6. Activate and enable the chain
-
Activate the licence. Product ID
54578959. Activation writeslic/54578959.lic, which is machine-bound. Without it the next step returns 403. -
Enable the chain row. Admin → Ecosystem → Blockchains, find Monero, flip the status. The seeded row ships disabled.
Enables or disables a seeded blockchain by product ID -
Watch the backend log on restart. A healthy start prints the wallet RPC version, the daemon height and sync flag, and
Monero service initialized successfully, all taggedXMR. -
Run the diagnostics. Admin → Ecosystem → Blockchains → Requirements → Monero → Test. It probes
get_versionon the wallet RPC andget_infoon the daemon, and compares the daemon'snettypeagainstXMR_NETWORK.Runs live read-only probes against a chain and returns per-flow readiness
7. Create the master wallet and the token
-
Create the XMR master wallet. Admin → Ecosystem → Wallets → Master Wallets → Create, chain
XMR. This callscreate_walletwith the filenamemaster_wallet, so a file by that name appears in your--wallet-dir.Generates, encrypts and stores a master wallet for a chainThe mnemonic is encrypted with the Ecosystem vault key before it is stored and is never displayed. If the vault is locked, this fails.
-
Import XMR as a native token. Admin → Ecosystem → Trading → Tokens → Import. Chain
XMR, currencyXMR, contract typeNATIVE, contract left blank, decimals12.Registers an already-deployed token without deploying anythingTwelve decimals is not cosmetic — Monero amounts are handled in piconero and converted by dividing by 10^12 throughout.
-
Set the token's withdrawal fee. This is the number the platform charges; the Monero network fee is taken out of it. Read Withdrawals before you pick a value, because a fee below the network fee silently earns you nothing.
-
Create a market if you want XMR traded rather than merely custodied — see Tokens and markets.
8. Prove it end to end
Open the XMR deposit page as a real user. The first visit creates that user's
wallet file, which is the moment you will find out whether the wallet RPC is
genuinely healthy — watch ls on your wallet directory and the XMR log lines
at the same time.
Then send a small real deposit and wait. Six confirmations is roughly twelve to twenty minutes on mainnet. If nothing lands, go to Troubleshooting rather than resending.
Backups
Two things must be backed up together, and a copy of one without the other is worthless:
- The wallet directory. Every file in it is a set of private keys. There is no derivation path that can regenerate them from the master wallet.
- The database plus
.env. The mnemonics are also stored encrypted inwallet_data, and the key that decrypts them lives in.env.
#!/bin/bash
set -euo pipefail
DEST="/backup/monero/$(date +%Y%m%d-%H%M%S)"
mkdir -p "$DEST"
rsync -a /home/monero/monero-wallets/ "$DEST/wallets/"Take the copy while the platform is quiet. A wallet file being written by an
open session can be copied mid-write; the .keys file is the important half and
is not rewritten on every refresh, but a quiescent copy is still the safe one.