From 0 to Hero: Dealing DAMAGE with a Docker-Powered DamageBDD Node
Install Docker, run the verified stack, publish your node, and start serving behaviour verification
1. From 0 to hero
This guide takes you from a fresh machine to a running DamageBDD node.
By the end, you should have:
- Docker installed on Windows, macOS, or Linux
- the DamageBDD Docker stack running
- the web interface open locally
- an optional Tor onion address for private public access
- a node/account address copied from the web UI
- a first smoke test executed
- the basic operator path understood
The verified DamageBDD stack is not just a web app. It is a behaviour verification node with supporting infrastructure:
- DamageBDD web/API runner
- IPFS report storage
- Aeternity middleware/node for verification paths
- Bitcoin Core
- Core Lightning
- optional Tor onion service for exposing the web UI without exposing your home IP
DamageBDD exposes execution routes such as /version/, /tx/, and /execute_feature/, and the feature execution path writes reports that can be published through IPFS.
2. What you are building
A DamageBDD node gives users a place to submit behaviour tests.
In plain English:
- A user opens your node.
- The user submits a Gherkin feature file.
- DamageBDD runs the behaviour test.
- A report is produced.
- The report is stored/published through the stack.
- Eligible verified execution can earn DAMAGE.
Careful wording matters: running a node creates execution capacity. Rewards, payments, and token flows depend on configuration, demand, network state, pricing, eligibility, and review rules. This is not an investment promise and not a guarantee of profit.
3. Hardware expectations
3.1. Beginner / learning node
Use this for learning Docker, opening the UI, and running small tests.
| Part | Suggested minimum |
|---|---|
| CPU | 4 cores |
| RAM | 8 GB minimum, 16 GB better |
| Disk | 100–250 GB free for app testing |
| OS | Windows, macOS, or Linux |
| Net | stable broadband |
This is enough to learn the workflow, but it is not the serious sovereign configuration.
3.2. Full sovereign node
Use this for a full-power operator node.
| Part | Suggested serious spec |
|---|---|
| CPU | 8 cores / 16 threads |
| RAM | 32 GB minimum, 64 GB recommended |
| Disk | 4 TB NVMe minimum |
| Better disk | 8 TB NVMe |
| Network | always-on broadband |
| Power | UPS strongly recommended |
| OS | Linux server preferred |
| Runtime | Docker Compose |
| Exposure | Tor onion service or hardened reverse proxy |
For Bitcoin Core, no pruning means real disk planning. Bitcoin.org lists 750 GB as the default-setting disk requirement and explains that pruning reduces disk usage from over 750 GB to around 7 GB; this guide assumes the full-power path, so do not design around pruned storage. ([Bitcoin][1])
Aeternity middleware also needs persistent storage. The `aemdw` Docker setup mounts persistent mnesia, mdw.db, and log paths, and the middleware runs together with an Aeternity node in the same container/BEAM instance. ([GitHub][2])
4. Install Docker
Docker Compose is the command that brings the whole stack up. Docker’s current recommendation is Docker Desktop for the easiest cross-platform Compose setup; Docker Desktop includes Docker Engine, Docker CLI, and Docker Compose. ([Docker Documentation][3])
The modern command is:
docker compose version
Not:
docker-compose version
The old docker-compose binary may still exist on some machines, but the current Docker Compose plugin is used as docker compose.
5. Windows setup
5.1. 1. Install Docker Desktop
On Windows, install Docker Desktop for Windows.
Docker’s Windows documentation notes that Docker Desktop uses the WSL 2 backend for Linux containers and that Docker commands are available from Windows terminals when the WSL 2 engine is enabled. ([Docker Documentation][4])
5.2. 2. Enable WSL 2 integration
Open Docker Desktop:
Settings → General → Use the WSL 2 based engine
Then enable your Linux distribution if you use one:
Settings → Resources → WSL Integration
Check WSL status from PowerShell:
wsl.exe -l -v
Use WSL 2 for your Ubuntu distribution:
wsl.exe --set-version Ubuntu 2 wsl.exe --set-default-version 2
5.3. 3. Give Docker enough resources
For a learning node, start with:
CPU: 4 RAM: 8–16 GB Disk: 100+ GB
For a full node, move Docker’s storage to a large SSD/NVMe drive. Docker Desktop stores WSL 2 engine data under the user profile by default, and Docker’s WSL documentation points operators to Settings → Resources → Advanced for changing the location. ([Docker Documentation][5])
Avoid placing chain data under OneDrive, Dropbox, iCloud Drive, or network-synced folders.
6. macOS setup
6.1. 1. Install Docker Desktop
Install Docker Desktop for Mac.
Docker’s Mac documentation provides separate installers for Apple silicon and Intel Macs, notes that Docker Desktop requires a supported macOS version, and lists at least 4 GB RAM as a requirement. ([Docker Documentation][6])
6.2. 2. Start Docker Desktop
Open:
Applications → Docker
Wait until Docker says it is running.
Verify:
docker version docker compose version
6.3. 3. Resource settings
For a learning node:
CPU: 4 RAM: 8–16 GB Disk: 100+ GB
For a full sovereign node, macOS can work, but Linux server hardware is cleaner for always-on operation, large disks, and long-running blockchain databases.
7. Linux setup
Linux is the preferred full-time operator environment.
The example below is for Ubuntu. Docker’s official Ubuntu install guide lists supported Ubuntu releases and recommends installing Docker from Docker’s apt repository. ([Docker Documentation][7])
7.1. 1. Remove conflicting packages
sudo apt remove docker.io docker-compose docker-compose-v2 docker-doc podman-docker containerd runc || true
7.2. 2. Add Docker’s apt repository
sudo apt update
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL [https://download.docker.com/linux/ubuntu/gpg](https://download.docker.com/linux/ubuntu/gpg)
-o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
sudo tee /etc/apt/sources.list.d/docker.sources >/dev/null <<EOF
Types: deb
URIs: [https://download.docker.com/linux/ubuntu](https://download.docker.com/linux/ubuntu)
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
sudo apt update
7.3. 3. Install Docker Engine and Compose plugin
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Docker’s Ubuntu docs list these packages for the latest Docker Engine install path. ([Docker Documentation][7])
7.4. 4. Verify Docker
sudo docker run hello-world docker compose version
7.5. 5. Optional: run Docker without sudo
sudo usermod -aG docker "$USER" newgrp docker docker run hello-world
Log out and back in if the group change does not apply.
7.6. 6. Firewall note
Docker warns that published container ports can bypass ufw or firewalld rules unless you account for Docker’s iptables behaviour. For a node operator, bind admin/RPC ports to localhost and expose only what you intend to expose. ([Docker Documentation][7])
8. Get the DamageBDD source
Choose a working directory with enough disk space.
mkdir -p ~/damage cd ~/damage git clone <YOUR_DAMAGEBDD_REPO_URL> damagebdd cd damagebdd
Use the real project repository URL in place of <YOUR_DAMAGEBDD_REPO_URL>.
Check the important files:
ls -la Dockerfile docker-compose.yml
You should have:
Dockerfile docker-compose.yml .env or .env.example features/ contracts/
9. Configure the node
Copy the example environment file:
cp .env.example .env
Edit it:
nano .env
A starter .env should look like this:
DAMAGE_API_URL=[http://localhost:4888/api](http://localhost:4888/api) BITCOIN_CHAIN=main CLN_NETWORK=bitcoin BITCOIN_RPC_USER=damage BITCOIN_RPC_PASSWORD=change_me_with_a_real_random_password BITCOIN_PRUNE=0 CLN_LOG_LEVEL=info CLN_RUNE= AE_FEE_MULTIPLIER=2 AE_GAS_MULTIPLIER=2 AE_GAS_PRICE_MULTIPLIER=3
Generate a real Bitcoin RPC password:
openssl rand -hex 32
Put the result into BITCOIN_RPC_PASSWORD.
For a full-power node, keep:
BITCOIN_PRUNE=0
That means no pruning.
10. Add Tor onion service support
Tor is optional, but it is the clean operator path when you want users to access your node without exposing your home IP directly.
The Tor Project’s onion service guide uses HiddenServiceDir to store onion service keys and HiddenServicePort to map the onion service port to a local service; the onion hostname is written to a file named hostname in the hidden service directory. ([Tor Community][8])
10.1. 1. Create Tor files
mkdir -p tor
Create tor/Dockerfile:
FROM debian:bookworm-slim RUN apt-get update && apt-get install -y --no-install-recommends tor ca-certificates && rm -rf /var/lib/apt/lists/* COPY torrc /etc/tor/torrc COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh RUN chmod +x /usr/local/bin/docker-entrypoint.sh ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"] CMD ["tor", "-f", "/etc/tor/torrc"]
Create tor/docker-entrypoint.sh:
#!/bin/sh set -e mkdir -p /var/lib/tor chown -R debian-tor:debian-tor /var/lib/tor exec "$@"
Create tor/torrc:
SocksPort 0 Log notice stdout DataDirectory /var/lib/tor HiddenServiceDir /var/lib/tor/damagebdd/ HiddenServiceVersion 3 # Tor-facing users visit port 80 on the onion address. # Inside the shared network namespace, Tor forwards to DamageBDD on localhost:4888. HiddenServicePort 80 127.0.0.1:4888 User debian-tor
10.2. 2. Add the Tor service to docker-compose.yml
Add this service:
tor: build: context: ./tor dockerfile: Dockerfile container_name: damagebdd-tor restart: unless-stopped depends_on: damagebdd: condition: service_started ``` # Share the DamageBDD container network namespace. # This makes 127.0.0.1:4888 point at the DamageBDD web interface. network_mode: "service:damagebdd" volumes: - tor_data:/var/lib/tor ```
Add this volume:
volumes: tor_data:
Do not delete tor_data. It contains the onion service key. If you delete it, your onion address changes.
11. Bring the stack up
From the DamageBDD repository:
docker compose up --build -d
Watch the services:
docker compose ps
Follow logs:
docker compose logs -f damagebdd
For the full stack:
docker compose logs -f bitcoin docker compose logs -f lightning docker compose logs -f ae_mdw docker compose logs -f ipfs docker compose logs -f tor
12. Open the web interface
On the machine running Docker:
[http://localhost:4888](http://localhost:4888)
Health check:
curl -fsS [http://localhost:4888/version/](http://localhost:4888/version/)
A successful response means the DamageBDD HTTP service is reachable. The /version/ route is part of the DamageBDD HTTP routes.
13. Get your onion address
Once Tor starts, read the onion hostname:
docker compose exec tor cat /var/lib/tor/damagebdd/hostname
You should see something like:
exampleexampleexampleexampleexampleexampleexampleexampleexample.onion
Open Tor Browser and visit:
[http://exampleexampleexampleexampleexampleexampleexampleexampleexample.onion](http://exampleexampleexampleexampleexampleexampleexampleexampleexample.onion)
Replace the example address with your real onion hostname.
That onion address is the access point you can share with testers.
14. Get your node/account address
Open the web interface locally or through Tor.
Then copy the node/account address shown by the UI.
That address is important because it identifies the node/operator side of the execution flow.
Keep three things together in your operator notes:
Local UI: [http://localhost:4888](http://localhost:4888) Onion UI: http://<your-onion-hostname>.onion Node address: ak_...
Do not publish private keys, seed material, token files, macaroon files, rune secrets, or raw wallet credentials.
15. Run your first smoke test
Create a basic feature file:
mkdir -p features nano features/smoke.feature
Paste:
Feature: DamageBDD node smoke test Scenario: The local DamageBDD version endpoint responds Given I am using server "[http://127.0.0.1:4888](http://127.0.0.1:4888)" When I make a GET request to "/version/" Then the response status must be "200"
DamageBDD supports plain-language HTTP steps such as setting a server, making GET requests, and asserting response status through the HTTP step implementation.
Submit the feature through the web UI, or use the API flow supported by your node configuration.
A simple API-style test shape is:
curl -X PUT [http://localhost:4888/execute_feature/](http://localhost:4888/execute_feature/) -H 'content-type: application/json' --data-binary @- <<'JSON' { "feature": "Feature: API smoke\n\n Scenario: Version responds\n Given I am using server "[http://127.0.0.1:4888\"\n](http://127.0.0.1:4888\%22\n) When I make a GET request to "/version/"\n Then the response status must be "200"\n" } JSON
Some nodes require authentication or a paid/signed execution flow. If the node returns an auth, balance, transaction, or payment error, that means the web server is up but the economic execution path still needs configuration.
16. Check IPFS report flow
DamageBDD’s execution path adds the run directory to IPFS and formats a report URL using the configured Damage API URL.
Check IPFS:
docker compose logs -f ipfs
Check whether the IPFS API is reachable from the host:
curl -fsS [http://127.0.0.1:5001/api/v0/id](http://127.0.0.1:5001/api/v0/id) -X POST
The DamageBDD IPFS step module also supports explicit IPFS API and gateway testing patterns.
17. Check Bitcoin and Lightning
Bitcoin Core will take time to sync. On mainnet with no pruning, expect a long initial sync.
Check Bitcoin:
docker compose exec bitcoin bitcoin-cli -rpcuser="$BITCOIN_RPC_USER" -rpcpassword="$BITCOIN_RPC_PASSWORD" getblockchaininfo
Check Core Lightning:
docker compose exec lightning lightning-cli getinfo
DamageBDD includes Nostr Wallet Connect request handling for Bitcoin-network wallet actions such as get_info, get_balance, pay_invoice, make_invoice, lookup_invoice, and list_transactions.
DamageBDD also exposes NWC-related HTTP routes for minting/revoking sessions, checking ledger balance, creating top-up invoices, and checking top-up status.
18. Check Aeternity middleware
Check the middleware status:
curl -fsS [http://localhost:4000/status](http://localhost:4000/status)
Check logs:
docker compose logs -f ae_mdw
DamageBDD reads Aeternity middleware nodes from configuration and uses middleware contract logs for ledger/event-style reads in the NWC ledger path.
19. How the node earns
The operator path is:
- Run the verified stack.
- Keep the node online.
- Publish the web UI through Tor or another controlled public route.
- Share the onion address.
- Share the node/account address.
- Let users submit behaviour tests.
- Execute tests reliably.
- Produce reports.
- Keep the verification path healthy.
- Receive eligible rewards/payments according to the configured DamageBDD economy.
The clean signal is not hype.
The clean signal is:
working node working onion address working web UI working execution working reports working verification path
When those are true, the node has useful capacity.
20. Operator safety checklist
20.1. Keep private material private
Never commit:
.env token.aes *.aes *.key *.pem secrets/ wallet files macaroons CLN hsm_secret Tor onion private keys Aeternity private keys Bitcoin wallet files
20.2. Back up persistent volumes
Back up:
damage_data damage_logs ipfs_data ae_mdw_data bitcoin_data lightning_data tor_data
The most critical ones are:
lightning_data bitcoin_data tor_data secrets node identity files
If you lose tor_data, you lose the onion identity.
If you lose lightning_data, you may lose funds or channel state.
If you leak tor_data, someone can impersonate your onion service.
20.3. Avoid public RPC exposure
Keep these local unless you know exactly why you are exposing them:
Bitcoin RPC IPFS API Aeternity internal API Core Lightning RPC Docker socket
Expose the DamageBDD web UI through Tor first.
21. Troubleshooting
21.1. Docker command not found
Install Docker Desktop on Windows/macOS, or Docker Engine plus the Compose plugin on Linux. Docker’s Compose overview says Docker Desktop includes Compose, while Linux can use the Compose plugin. ([Docker Documentation][3])
21.2. docker compose command not found
Try:
docker compose version docker-compose version
If only docker-compose works, you are using the legacy binary. Install the Compose plugin.
21.3. Port 4888 already in use
Find the process:
lsof -i :4888
Or change the host port in docker-compose.yml:
#+BEGINSRC yaml ports:
22. "0.0.0.0:4889:4888"
#+ENDSRC
Then open:
[http://localhost:4889](http://localhost:4889)
22.1. Tor onion address does not appear
Check logs:
docker compose logs -f tor
Check the hostname file:
docker compose exec tor ls -la /var/lib/tor/damagebdd/ docker compose exec tor cat /var/lib/tor/damagebdd/hostname
The Tor Project notes that Tor creates the hidden service directory when it starts and that the hostname file contains the onion address. ([Tor Community][8])
22.2. Bitcoin sync is slow
That is normal for no-pruning mainnet operation. Use NVMe, enough RAM, and stable power.
Do not delete the Bitcoin volume unless you want to sync again from scratch.
22.3. Aeternity middleware is slow
Use persistent SSD/NVMe volumes. The `aemdw` Docker setup persists mnesia and mdw.db; losing those means rebuild/resync work. ([GitHub][9])
22.4. UI loads locally but not over Tor
Check:
curl -fsS [http://localhost:4888/version/](http://localhost:4888/version/) docker compose logs -f tor docker compose exec tor cat /var/lib/tor/damagebdd/hostname
Then open the onion address in Tor Browser, not a normal browser.
23. Daily operator commands
Start:
docker compose up -d
Stop:
docker compose down
Rebuild DamageBDD after code changes:
docker compose up --build -d damagebdd
Watch everything:
docker compose logs -f
Check service status:
docker compose ps
Show disk usage:
docker system df
Do not blindly run:
docker system prune --volumes
That can delete state you care about.
24. The hero path
A beginner proves the node can run.
An operator proves the node can stay up.
A sovereign operator proves the whole verification stack can survive real use.
The final state looks like this:
Docker stack: running DamageBDD UI: reachable Tor onion: published Node/account address: copied Bitcoin Core: syncing or synced Core Lightning: running Aeternity middleware: running IPFS: running Smoke test: passing Reports: produced Operator backups: done
That is the path from zero to hero.
Run the node.
Publish the onion.
Serve execution.
Deal DAMAGE through verified behaviour.
[1]: https://bitcoin.org/en/bitcoin-core/features/requirements?utm_source=chatgpt.com "Bitcoin Core Requirements and Warnings" [2]: https://github.com/aeternity/ae_mdw?utm_source=chatgpt.com "GitHub - aeternity/aemdw: Aeternity Middleware in Elixir" [3]: https://docs.docker.com/compose/install/ "Overview of installing Docker Compose | Docker Docs" [4]: https://docs.docker.com/desktop/setup/install/windows-install/?utm_source=chatgpt.com "Install Docker Desktop on Windows" [5]: https://docs.docker.com/desktop/features/wsl/?utm_source=chatgpt.com "Docker Desktop WSL 2 backend on Windows" [6]: https://docs.docker.com/desktop/setup/install/mac-install/ "Install Docker Desktop on Mac | Docker Docs" [7]: https://docs.docker.com/engine/install/ubuntu/ "Install Docker Engine on Ubuntu | Docker Docs" [8]: https://community.torproject.org/onion-services/setup/ "Tor Project | Set up Your Onion Service" [9]: https://github.com/aeternity/ae_mdw/blob/master/docker-compose.yml?utm_source=chatgpt.com "docker-compose.yml - aeternity/aemdw"
