Dojo: Ashigaru Wallet Server
Dojo is the wallet backend for the Ashigaru wallet (formerly Samourai). It stores your extended public keys, handles BIP47 payment codes, and answers your wallet's questions about balances and history. Run it yourself and no third party ever sees your wallet's metadata.
This guide takes you from a standard Ubuntu machine to a working Dojo. Every command is given in full. Every step shows what the screen should look like when it works, and what to do when it does not. You do not need server experience. You do need patience: the first chain sync takes days.
If you are brand new to the terminal, read these two short guides of mine first: terminal basics and the nano editor.
There are two ways to build this, and you pick once, up front:
- Path A, everything in Docker. You start with an empty machine. One install command brings Bitcoin Core, a Fulcrum indexer, a block explorer, Tor, a MariaDB database, and the Dojo API itself. The chain downloads from scratch, which takes 2 to 7 days. This is the setup the Ashigaru team tests against. If you are unsure, pick this.
- Path B, the hybrid. You already run Bitcoin Core and Fulcrum on this machine as regular system services, fully synced. Dojo runs in Docker beside them and points at them. Nothing is re-downloaded, so you skip the week of waiting. This path has more steps, because you must wire the Docker world to your existing services.
Either way you end at the same place: a Dojo your wallets pair to over Tor.
What you need before starting
Hardware:
- x86-64 computer, 2 GHz dual-core or better
- 8 GB of RAM
- 2 TB NVMe SSD (Path A ends up storing roughly 800 GB of chain and index data)
- Reliable internet, machine left on around the clock
Software: Ubuntu 24.04 or 26.04 LTS. A refurbished Optiplex, EliteDesk, or ThinkCentre is ideal. See my hardware guide.
Path B only: Bitcoin Core (with txindex=1) and Fulcrum already installed, synced, and running as services on this same machine. If that sentence means nothing to you yet, you want Path A.
How to read this guide:
- Lines in gray boxes are commands. Paste them into the terminal and press Enter. In most terminals, paste is
ctrl+shift+v. - Text in angle brackets, like
<MY-DOCKER-IP>, is a placeholder. Never paste it as-is. Replace it with your own value, brackets included. - A "healthy output" block shows what the screen looks like when a step works. Compare yours to it before moving on.
One thing to know before anything else: sudo means "run this as administrator." The first time, it asks for your password. While you type it, the screen shows nothing. That is normal. Keep typing and press Enter.
Part 1: Prepare the machine
Update the system and install the tools we need:
cd ~/
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg unzip tor torsocks
sudo systemctl enable --now tor
tor and torsocks are there because the download in Part 2 goes over Tor. torsocks only works while the tor service is running, which is what the last line makes sure of.
Now Docker. Skip this block if docker run hello-world already works on this machine.
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo usermod -aG docker $USER
That last line adds your user to the docker group, so you will not need sudo for every docker command. It only takes effect after you log out and log back in. Do that now, then verify:
docker run hello-world
Healthy output starts with Hello from Docker!. If you do not see it, reboot once and try again before looking for deeper problems.
Part 2: Download and verify Dojo
This is money software, so we do not trust the download. We check two things: that the file came from the real developer (a PGP signature), and that it is the exact file released (a SHA256 hash). The full reasoning is in my guide on verifying software.
At the time of writing, the newest release is 1.29.3. Check the releases page of the Dojo-Open-Source-Project/samourai-dojo repository on GitHub. If a newer version exists, use that number instead.
cd ~/
DOJO_VER=1.29.3
That line creates a variable holding the version number, so the rest of the commands can reuse it. Variables vanish when you close the terminal. If you close it, run that line again before continuing.
Fetch the developer's signing key and the release itself, all over Tor:
torsocks wget https://keys.openpgp.org/vks/v1/by-fingerprint/E53AD419B242822F19E23C6D3033D463D6E544F6
gpg --import E53AD419B242822F19E23C6D3033D463D6E544F6
torsocks wget -O samourai-dojo-$DOJO_VER.zip https://github.com/Dojo-Open-Source-Project/samourai-dojo/archive/refs/tags/v$DOJO_VER.zip
torsocks wget https://github.com/Dojo-Open-Source-Project/samourai-dojo/releases/download/v$DOJO_VER/samourai-dojo-$DOJO_VER-fingerprints.txt
torsocks wget https://github.com/Dojo-Open-Source-Project/samourai-dojo/releases/download/v$DOJO_VER/samourai-dojo-$DOJO_VER-fingerprints.txt.sig
If these fail with "connection refused", Tor is not running yet. Wait a minute and try again.
Check the signature:
gpg --verify samourai-dojo-$DOJO_VER-fingerprints.txt.sig
Healthy output looks like this (the date will differ):
gpg: Signature made <date and time>
gpg: using EDDSA key E53AD419B242822F19E23C6D3033D463D6E544F6
gpg: Good signature from "dojocoder@pm.me" <dojocoder@pm.me> [unknown]
Two things must both be true: the words Good signature, and the key on the "using" line ending in D6E544F6. WARNING lines below that, about the key not being certified, are normal and safe to ignore. Anything else, like BAD signature or a different key, means stop. Delete everything and start Part 2 again.
Check the file itself:
grep "$(sha256sum samourai-dojo-$DOJO_VER.zip | cut -d' ' -f1)" samourai-dojo-$DOJO_VER-fingerprints.txt
This computes the fingerprint of the zip you downloaded and searches the signed list for it. Healthy output is one line containing a long string of letters and numbers. If nothing prints, the zip does not match the signed release. Delete it and download it again. Do not continue with a zip that prints nothing.
Unpack:
unzip samourai-dojo-$DOJO_VER.zip -d .
mkdir -p ~/dojo-app
mv ~/samourai-dojo-$DOJO_VER/* ~/dojo-app/
rm -r samourai-dojo-$DOJO_VER samourai-dojo-$DOJO_VER.zip samourai-dojo-$DOJO_VER-fingerprints.txt samourai-dojo-$DOJO_VER-fingerprints.txt.sig E53AD419B242822F19E23C6D3033D463D6E544F6
You now have a folder called ~/dojo-app. Everything Dojo-related lives in there from now on.
Part 3: Generate your secrets
Dojo needs eight passwords before it will install. Make each one in your password manager (Bitwarden, KeePassXC, anything with a generator).
Settings for all eight:
- Length: 40 characters
- Letters and numbers only. No symbols. The config files reject characters like
! @ # $ - Each one different from the others
| Secret | Goes in | What it is for |
|---|---|---|
| BITCOIND_RPC_USER | docker-bitcoind.conf.tpl | Username for bitcoind's remote control |
| BITCOIND_RPC_PASSWORD | docker-bitcoind.conf.tpl | Password for that username |
| MYSQL_ROOT_PASSWORD | docker-mysql.conf.tpl | Master password for the database |
| MYSQL_USER | docker-mysql.conf.tpl | Database account name |
| MYSQL_PASSWORD | docker-mysql.conf.tpl | Password for that account |
| NODE_API_KEY | docker-node.conf.tpl | Key wallets use to talk to Dojo |
| NODE_ADMIN_KEY | docker-node.conf.tpl | Your login for the Dojo dashboard |
| NODE_JWT_SECRET | docker-node.conf.tpl | Used to sign login sessions |
Path B: skip the first two rows. Part 5B generates the bitcoind login for you.
Generate the rest now and keep the list open. After the install, the only one you need to keep in your password manager forever is NODE_ADMIN_KEY, because it is your dashboard login. The others stay inside Dojo's config files and can be looked up there later.
About the config files. They live in ~/dojo-app/docker/my-dojo/conf/, and each one comes in two forms:
- Files ending in
.tplare the templates. Before the first install, this is where you type your settings. - Files ending in
.confare the live settings. The installer creates them from your templates. After that, Dojo only reads the.conffiles.
So: before installing, edit .tpl. After installing, edit .conf, then run ./dojo.sh upgrade to apply the change. Updates replace the .tpl files with fresh blank copies and leave your .conf files alone, which is why your settings survive.
Open a file like this:
cd ~/dojo-app/docker/my-dojo/conf/
nano docker-mysql.conf.tpl
In nano, the text editor:
- Move around with the arrow keys. The mouse does nothing.
- Delete with Backspace.
- Paste with
ctrl+shift+v - Save and exit:
ctrl+x, theny, then Enter - Made a mistake and want to start over: exit without saving with
ctrl+x, thenn, then Enter, and reopen the file
You will repeat that open, edit, save cycle for every file in Parts 5A and 5B.
Part 4: Find your numbers (the worksheet)
Machines on a network have addresses, like houses on a street. Docker builds its own private street inside your machine, and the addresses there are different from the ones on your home network. They also differ from person to person, so this guide cannot print yours. You will discover them now and write them on paper.
Path A users: you only need this part if you want Sparrow Wallet on your home network to use your server. Otherwise skip to Part 5A.
Run each command, compare with the sample output, and write your value into the worksheet at the end.
Your Docker host address. This is the address of the machine itself, as seen from inside Docker:
ip -4 addr show docker0
Sample output:
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 ...
inet 172.17.0.1/16 ...
Find the line that starts with inet. The number before the slash is your value. In the sample it is 172.17.0.1. Write it in as MY-DOCKER-IP.
Dojo's container network. The file you unpacked defines the private street's address range:
grep 'subnet:' ~/dojo-app/docker/my-dojo/docker-compose.yaml
Sample output:
- subnet: 172.28.0.0/16
- subnet: 172.29.0.0/16
The first line is the network called dojonet, where the Dojo containers live. Write the whole thing, slash included, as MY-DOJONET-SUBNET. In the sample that is 172.28.0.0/16. The /16 means "this entire range of addresses," so keep it. Do not trim it down to a single address.
Your LAN address. This is the machine's address on your home network:
ip -4 addr show scope global
Find the block belonging to your wired network card (its name usually starts with enp or eth) and its inet line. Write the number before the slash as MY-LAN-IP. Ignore blocks for docker0, tailscale0, or anything starting with br- or veth.
Your Tailscale address, if you run Tailscale:
tailscale ip -4
It will look like 100.something.something.something. Write it in as MY-TAILSCALE-IP. Skip this if you do not use Tailscale.
The worksheet. Copy this onto paper and fill it in:
MY-DOCKER-IP: ______________________ (Path B)
MY-DOJONET-SUBNET: ______________________ (Path B)
MY-LAN-IP: ______________________ (optional, Sparrow at home)
MY-TAILSCALE-IP: ______________________ (optional, Sparrow over Tailscale)
For reference, a typical machine might have 172.17.0.1, 172.28.0.0/16, 192.168.8.20, and 100.101.102.103. Yours may differ. Trust only what your own terminal printed.
One rule keeps all of this simple. The Dojo containers reach this machine's services at MY-DOCKER-IP, always. The other two addresses are only for your other devices, like your laptop running Sparrow: MY-LAN-IP when it is on your Wi-Fi, MY-TAILSCALE-IP when it connects through the tailnet.
Part 5A: Path A, everything in Docker
Four files to edit, then one command. Move into the config folder:
cd ~/dojo-app/docker/my-dojo/conf/
File 1: bitcoind settings
nano docker-bitcoind.conf.tpl
Set BITCOIND_RPC_USER and BITCOIND_RPC_PASSWORD to your first two secrets. If the machine has 16 GB of RAM or more, also set BITCOIND_DB_CACHE=2048, which speeds up the sync. Leave BITCOIND_INSTALL=on, which is the default. Save and exit.
File 2: database settings
nano docker-mysql.conf.tpl
Set MYSQL_ROOT_PASSWORD, MYSQL_USER, and MYSQL_PASSWORD. If your machine has only 8 GB of RAM, also set MYSQL_CONF_PROFILE=low_mem to keep the database frugal. Save and exit.
File 3: indexer settings
nano docker-indexer.conf.tpl
Out of the box, this file turns the indexer off and names a different one. Change these lines:
INDEXER_INSTALL=on
INDEXER_TYPE=fulcrum
INDEXER_BATCH_SUPPORT=active
Leave INDEXER_EXTERNAL=off unless you want Sparrow on your home network to use this server directly. Ashigaru does not need it, and Sparrow can reach the server over Tor anyway (see Part 7). If you do want it:
INDEXER_EXTERNAL=on
INDEXER_EXTERNAL_IP=<MY-LAN-IP>
Then reserve that address for this machine in your router's settings (often called a DHCP reservation or static lease). If the address ever changes, the indexer will refuse to start. Save and exit.
File 4: Dojo settings
nano docker-node.conf.tpl
Set NODE_API_KEY, NODE_ADMIN_KEY, and NODE_JWT_SECRET. Also set NODE_ACTIVE_INDEXER=local_indexer. Save and exit.
Install
First, a check for a known packaging bug:
cd ~/dojo-app/docker/my-dojo
if grep -q 'node:20-alpine' node/Dockerfile; then
sed -i -E 's/node:20-alpine[0-9.]*/node:24-alpine/g' node/Dockerfile
fi
grep '^FROM' node/Dockerfile
Healthy output is two lines, both starting with FROM node:24 (or a higher number).
Why: some releases build the nodejs image on Node 20 while the Dojo code needs Node 24, and without the fix the dashboard crashes after install. The check only changes the file when the old version is present. On a release that already ships the right version, it does nothing.
Now install:
./dojo.sh install
The installer asks whether you wish to continue. Type y and press Enter. It then builds the images. Expect 10 to 30 minutes of scrolling text. When it finishes, it shows the live logs. Press ctrl+c to close that view. Dojo keeps running.
The chain download starts on its own. Nothing to babysit. Check on it:
./dojo.sh logs bitcoind
Healthy output while downloading:
IBD progress = 0.051000 (5.1%)
Watch that percentage climb. Done is shown as progress = 1.000000. Press ctrl+c to stop watching. This only closes your view of the logs; the download keeps running. Then check the indexer:
./dojo.sh logs indexer
Fulcrum waits for bitcoind to finish, then builds its index. Look for a percentage climbing to 100. After both are done, the Dojo tracker catches up on wallet data, usually within a few hours.
Total time from install to fully green: 2 to 7 days, depending mostly on your internet. Leave the machine on. When you are done waiting, continue at Part 6.
Part 5B: Path B, borrow your existing node
The single line that matters in this path is BITCOIND_INSTALL=off. It tells the installer: do not download another copy of the chain, one already exists here. Everything else in this part is plumbing that lets the Docker containers reach your existing services.
5B.1: Check your services and find their config files
sudo systemctl status bitcoind
sudo systemctl status fulcrum
Both must say active (running). If not, fix that before continuing. (If your services have different names, use yours everywhere below.)
Now find where their config files live:
systemctl cat bitcoind | grep ExecStart
systemctl cat fulcrum | grep ExecStart
For bitcoind: if the line contains -conf=, that is your file. If it contains -datadir=, your file is bitcoin.conf inside that folder. If it contains neither, it is ~/.bitcoin/bitcoin.conf in the home folder of the user that runs bitcoind. For Fulcrum, the line usually ends with the path to fulcrum.conf.
Save both paths in variables so you do not have to retype them, and back both files up:
BTC_CONF=/home/satoshis/.bitcoin/bitcoin.conf
FUL_CONF=/home/satoshis/.fulcrum/fulcrum.conf
sudo cp -a "$BTC_CONF" "$BTC_CONF.bak"
sudo cp -a "$FUL_CONF" "$FUL_CONF.bak"
Replace the two paths with the ones you found. If anything in this part goes wrong, copying the .bak files back puts everything exactly as it was. If you close the terminal, set the two variables again.
5B.2: Make a login for Dojo
Dojo gets its own login to bitcoind. Your existing logins keep working, so Fulcrum and anything else that talks to bitcoind are not affected. Run:
python3 -c 'import hmac,secrets; p=secrets.token_hex(20); s=secrets.token_hex(16); h=hmac.new(s.encode(),p.encode(),"sha256").hexdigest(); print(f"rpcauth=dojo:{s}${h}"); print(f"BITCOIND_RPC_PASSWORD={p}")'
Healthy output is two lines:
rpcauth=dojo:3f9c...e1$7a0b...44
BITCOIND_RPC_PASSWORD=9d2e...c7
The first line goes into bitcoin.conf. It is a salted fingerprint of the password, so the password itself never sits in bitcoind's config. The second line goes into Dojo's config in 5B.6. Copy both into a text note now. Running the command again makes a different pair, so do not mix lines from two runs.
5B.3: Let bitcoind accept visitors from Docker
bitcoind has a remote-control interface called RPC. By default it only accepts knocks from the machine itself. Containers knock from their own separate network, so we tell bitcoind where to listen and which visitors to trust.
sudo nano "$BTC_CONF"
Add these lines near the top of the file, above any line in square brackets such as [test]:
rpcbind=0.0.0.0
rpcallowip=127.0.0.1
rpcallowip=<MY-DOJONET-SUBNET>
rpcauth=dojo:<the rest of the first line from 5B.2>
zmqpubrawtx=tcp://0.0.0.0:28333
zmqpubhashblock=tcp://0.0.0.0:28334
Before saving, look through the rest of the file for three things:
- Existing
rpcbind=lines: put a#at the start of each one, so only the new line is active. - Existing
zmqpubrawtx=orzmqpubhashblock=lines: delete the two new ones you just added. Instead, change the address in the existing lines to0.0.0.0and keep their port numbers. Write those port numbers down; you need them in 5B.5 and 5B.6. - Existing
rpcuser,rpcpassword, orrpcauthlines: leave them alone. Other software uses them.
Line by line:
rpcbind=0.0.0.0makes bitcoind listen on every address the machine has. It does not let everyone in; the allowlist below decides that. Why not listen only on MY-DOCKER-IP: at boot, bitcoind can start before Docker has created that address, and bitcoind then refuses to start at all.- The two
rpcallowiplines say who may log in.127.0.0.1is the machine itself. The second line trusts the whole container network range. Why that range and not MY-DOCKER-IP: a container connects to that address, but its request carries the container's own address as the return label, and bitcoind checks the return label. Trust the range the labels come from. rpcauthis the Dojo login from 5B.2.- The two
zmqpublines are announcement wires. bitcoind broadcasts every new transaction and block onto them, and Dojo listens so your wallet updates instantly.
Save and exit.
5B.4: Let Fulcrum accept visitors from Docker
Check how Fulcrum listens right now:
sudo ss -ltn | grep 50001
If you see 0.0.0.0:50001 or *:50001, it already listens everywhere; skip to 5B.5. If you see 127.0.0.1:50001, it only accepts the machine itself. Fix it:
sudo nano "$FUL_CONF"
Find the line starting with tcp and change it to:
tcp = 0.0.0.0:50001
Save and exit.
5B.5: Restart and test
Stop Fulcrum first, so it shuts down cleanly instead of being cut off. Then restart bitcoind:
sudo systemctl stop fulcrum
sudo systemctl restart bitcoind
Stopping Fulcrum can take a few minutes. Wait for the prompt to come back. Do not press ctrl+c.
Wait 30 seconds, then check that bitcoind listens where Docker can reach it:
sudo ss -ltn | grep -E ':(8332|28333|28334)\b'
Healthy output is three lines, each showing 0.0.0.0 followed by one of those port numbers. If you kept different ZMQ ports in 5B.3, look for those instead. If a line is missing, bitcoind did not load the new config: run sudo systemctl status bitcoind and read the last lines for the reason.
Now test Dojo's login:
curl -s -u dojo -H 'content-type: text/plain;' --data-binary '{"jsonrpc":"1.0","id":"t","method":"getblockcount","params":[]}' -w ' HTTP %{http_code}\n' http://127.0.0.1:8332/
It asks for a password. Paste the value after BITCOIND_RPC_PASSWORD= from 5B.2 and press Enter. Healthy output:
{"result":915432,"error":null,"id":"t"} HTTP 200
The number is the current block height. HTTP 401 means the password does not match the rpcauth line: check that both came from the same run of 5B.2. A message about loading the block index means bitcoind is still starting: wait a minute and try again.
Start Fulcrum again and confirm it listens:
sudo systemctl start fulcrum
sudo ss -ltn | grep 50001
Fulcrum can take a few minutes before it starts listening. Run the second line again until you see 0.0.0.0:50001.
5B.6: Open the firewall
Check whether the firewall is on:
sudo ufw status
If it says Status: active, it blocks the containers' knocks. Allow the container range to reach four specific doors:
sudo ufw allow from <MY-DOJONET-SUBNET> to any port 8332 proto tcp comment 'Dojo to bitcoind RPC'
sudo ufw allow from <MY-DOJONET-SUBNET> to any port 28333 proto tcp comment 'Dojo to bitcoind ZMQ'
sudo ufw allow from <MY-DOJONET-SUBNET> to any port 28334 proto tcp comment 'Dojo to bitcoind ZMQ'
sudo ufw allow from <MY-DOJONET-SUBNET> to any port 50001 proto tcp comment 'Dojo to Fulcrum'
The doors: 8332 is bitcoind's remote control, 28333 and 28334 are the announcement wires, 50001 is Fulcrum. Use your own ZMQ port numbers if you kept different ones in 5B.3. If you run Tailscale and want your other tailnet devices to reach this machine:
sudo ufw allow in on tailscale0
If it says Status: inactive, skip the rules. bitcoind's remote control is still protected by the allowlist from 5B.3. The announcement wires and Fulcrum can then be reached from your home network, never from the internet, as long as you follow the next rule.
Never forward any of these ports from your router to the internet. They are for your machine and your devices only.
5B.7: Configure the templates
Move into the config folder:
cd ~/dojo-app/docker/my-dojo/conf/
File 1, docker-bitcoind.conf.tpl:
BITCOIND_INSTALL=off
BITCOIND_IP=<MY-DOCKER-IP>
BITCOIND_RPC_PORT=8332
BITCOIND_ZMQ_RAWTXS=28333
BITCOIND_ZMQ_BLK_HASH=28334
BITCOIND_RPC_USER=dojo
BITCOIND_RPC_PASSWORD=<the value from 5B.2>
BITCOIND_INSTALL=off is the line that prevents the 700 GB re-download. BITCOIND_IP is where the containers knock. The user is dojo and the password is the second line from 5B.2. Use your own ZMQ port numbers if you kept different ones.
Everything in this file under the headings about onion addresses, bloom filters, and exposing RPC switches itself off when BITCOIND_INSTALL=off. Do not spend time on those sections.
File 2, docker-indexer.conf.tpl:
INDEXER_INSTALL=off
INDEXER_TYPE=fulcrum
INDEXER_IP=<MY-DOCKER-IP>
INDEXER_RPC_PORT=50001
INDEXER_BATCH_SUPPORT=active
INDEXER_PROTOCOL=tcp
INDEXER_INSTALL=off keeps Fulcrum on the metal. INDEXER_IP is where the containers find it. Leave the INDEXER_EXTERNAL lines as they are: they only control a Fulcrum that Dojo runs itself, which does not exist on this path.
File 3, docker-explorer.conf.tpl: set EXPLORER_INSTALL=off if you already run a block explorer such as mempool.space on this machine, because a second one is redundant. Otherwise leave it on and enjoy the built-in BTC-RPC Explorer.
Files 4 and 5, docker-mysql.conf.tpl and docker-node.conf.tpl: the same secrets as Part 3, and in the node file set NODE_ACTIVE_INDEXER=local_indexer. The word "local" here means reachable, not containerized, so it stays correct on this path.
5B.8: Install
Same as Path A. Run the packaging check, then the installer:
cd ~/dojo-app/docker/my-dojo
if grep -q 'node:20-alpine' node/Dockerfile; then
sed -i -E 's/node:20-alpine[0-9.]*/node:24-alpine/g' node/Dockerfile
fi
grep '^FROM' node/Dockerfile
./dojo.sh install
Before the installer runs, the grep line must show two lines starting with FROM node:24 or higher. Type y when the installer asks. When the logs appear, press ctrl+c to close the view.
No chain download this time, because your node is already synced. The Dojo tracker reads your existing Fulcrum index and catches up, usually within hours.
Confirm what is running:
docker ps --format '{{.Names}}' | sort
Healthy output includes db, nodejs, nginx, and tor. You may also see soroban, and explorer if you left it on. You must not see bitcoind or fulcrum: those would mean Dojo started its own copies, so recheck 5B.7. If nodejs is missing, run ./dojo.sh logs node and read the errors.
Part 6: Verify it works
Watch Dojo's own logs:
cd ~/dojo-app/docker/my-dojo
./dojo.sh logs node
Healthy signs within the first few minutes are lines similar to:
Importer : Successfully connected to indexer
Tracker : Processing active Mempool
Block heights should climb to the current tip. Press ctrl+c when you have seen enough; this only closes your view.
Bad signs, with fixes in Part 9: Bitcoind RPC : API is still unreachable, or connect ECONNREFUSED.
The dashboard. Dojo ships with a control panel called the Dojo Maintenance Tool, and it is reachable only through Tor. Get your address:
./dojo.sh onion
Sample output:
Dojo API and Maintenance Tool = abcdef...xyz.onion
Block Explorer = ghijkl...xyz.onion
You may see a few more lines, such as an Electrum server address. Never share any of these addresses.
Take the Dojo API and Maintenance Tool address. In Tor Browser, which you can get from torproject.org, set the security level to Standard or Safer, because the page needs JavaScript. Paste the address into the address bar, add /admin to the end, and press Enter. The page asks for your admin key: paste NODE_ADMIN_KEY from your password manager and click CONNECT.
If the status page shows green checks next to Full Node, Indexer, Tracker, and Dojo DB, your Dojo is live. Orange checks during a first sync are normal and mean work in progress. Red crosses mean Part 9.
Part 7: Pair your wallets
In the Maintenance Tool, open the Pairing tab. A QR code appears. When Ashigaru asks for a Dojo, during setup or later in its settings, scan that code. From then on, the wallet talks to your Dojo, over Tor, end to end.
Sparrow Wallet does not talk to Dojo itself. It talks to the Fulcrum server underneath it. In Sparrow's server settings, choose a private Electrum server:
- Path A, over Tor: use the Electrum server address from
./dojo.sh onion, port 50001. - Path A, at home: MY-LAN-IP, port 50001, if you turned on
INDEXER_EXTERNALin Part 5A. - Path B: MY-LAN-IP, or MY-TAILSCALE-IP over the tailnet, port 50001.
Part 8: Everyday use and updates
Commands you will actually use, run from ~/dojo-app/docker/my-dojo:
| Command | What it does |
|---|---|
| ./dojo.sh logs | Watch all logs; ctrl+c to exit the view |
| ./dojo.sh logs node | Watch only Dojo's own logs |
| ./dojo.sh stop | Shut everything down cleanly |
| ./dojo.sh start | Start it again |
| ./dojo.sh restart | Stop, then start |
| ./dojo.sh upgrade | Apply config changes or a new version |
| ./dojo.sh onion | Show your Tor addresses again |
| ./dojo.sh version | Show the installed version |
| ./dojo.sh help | List every available command |
Four rules that prevent pain:
- Run
./dojo.sh stopbefore powering off, rebooting, or updating. Pulling power while the databases are writing can corrupt them, and Fulcrum's database is the fragile one. - Never run
./dojo.sh installa second time. On a machine that already has Dojo, it offers to wipe the old install first, data included. To apply changes, use./dojo.sh upgrade. - Never run
docker system prune --all --volumes, and never delete a Docker volume. The volume nameddata-mysqlis Dojo's entire database. On top of that, Dojo builds every image on your machine, and some images may only rebuild from that local cache if their upstream downloads break. Deleting what looks like junk can take out both. - Never forward ports 8332, 50001, 28333, or 28334 from your router.
Updating to a new release. Stop Dojo first:
cd ~/dojo-app/docker/my-dojo
./dojo.sh stop
Then repeat Part 2 with the new version number, from DOJO_VER= through the unzip line, including both checks. Do not run the mkdir, mv, and rm lines. Instead:
cp -a ~/samourai-dojo-$DOJO_VER/. ~/dojo-app/
cd ~/dojo-app/docker/my-dojo
grep DOJO_VERSION_TAG .env
That grep line is a check. It must print the new version number. If it still shows the old one, open .env in nano and change DOJO_VERSION_TAG by hand, or the upgrade will reinstall the version you already have.
The copy also replaced the nodejs Dockerfile, so run the packaging check from Part 5A again. Then upgrade and clean up:
./dojo.sh upgrade
rm -r ~/samourai-dojo-$DOJO_VER ~/samourai-dojo-$DOJO_VER.zip ~/samourai-dojo-$DOJO_VER-fingerprints.txt ~/samourai-dojo-$DOJO_VER-fingerprints.txt.sig ~/E53AD419B242822F19E23C6D3033D463D6E544F6
Type y when the upgrade asks. Your settings carry over, because they live in the .conf files and the copy only replaced the .tpl templates.
Part 9: Troubleshooting
| Symptom | What it means | Fix |
|---|---|---|
| connect ECONNREFUSED, ending in :8332 | bitcoind is not listening where Docker can reach it | Redo the listening check in 5B.5. Every line must show 0.0.0.0. If the firewall is active, check the rules in 5B.6 |
| Bitcoind RPC : API is still unreachable | bitcoind refused the login, or does not trust the visitor | Run grep -i 'incorrect password' on the debug.log in bitcoind's data folder. If it shows lines, the password in Dojo's config does not match: fix BITCOIND_RPC_PASSWORD in conf/docker-bitcoind.conf (the .conf, not the .tpl), then ./dojo.sh upgrade. If it shows nothing, the rpcallowip range is wrong: compare it with the output of docker network inspect my-dojo_dojonet, grep for Subnet |
| Dojo cannot reach the indexer (Path B) | Fulcrum only listens on 127.0.0.1 | Redo 5B.4 |
| bitcoind will not start after a reboot, log mentions binding | an rpcbind or zmqpub line points at a Docker address that did not exist yet at boot | Change it to 0.0.0.0, as in 5B.3 |
| Dashboard blank, or the nodejs container keeps restarting | the Node version bug from Part 5A | Run the packaging check, then ./dojo.sh upgrade |
| Install fails while building tor, with 404 errors | an upstream download that tor's image needs has moved | Not your fault. Do not prune or delete anything. Check the issues page of the Dojo repository for a fix or a newer release |
| Onion address will not load | tor container is wedged | docker restart tor |
| Fulcrum database corrupt after a power cut | the machine lost power without ./dojo.sh stop | Path A only: ./dojo.sh stop, docker container rm fulcrum, docker volume rm my-dojo_data-fulcrum, then ./dojo.sh upgrade. Expect 1 to 2 days of reindexing. On Path B, Fulcrum is a host service, so rebuild its database there |
| Fulcrum stuck for hours during an upgrade | database migration to a new format | Wait. Interrupting it corrupts the database |
If nothing here matches your problem, run ./dojo.sh logs node, copy the exact error line plus the ten lines around it, and ask in the Ashigaru community with that paste.
Don't trust. Verify.