Skip to content

Commit a53c263

Browse files
authored
add: Dockerized mining setup (#10301)
* Add Docker Compose setup for Zebra and S-NOMP mining pool * Extract s-nomp entrypoint script into dedicated shell file * Add healthcheck for zebra and update service dependencies in compose * Remove extra blank line before version 6.0.0 section in changelog * Add blank lines in mining README documentation
1 parent 5ab556b commit a53c263

File tree

5 files changed

+396
-1
lines changed

5 files changed

+396
-1
lines changed

docker/mining/.env.example

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Zebra + S-NOMP Mining Pool Configuration
2+
# ========================================
3+
4+
# === REQUIRED ===
5+
# Mining address, all block rewards go to this address.
6+
MINER_ADDRESS=
7+
8+
# === OPTIONAL COINBASE DATA ===
9+
# Data included in coinbase transaction (max 94 bytes). Hex or UTF-8 encoded.
10+
# MINER_DATA=
11+
# Shielded memo in coinbase output (max 512 bytes). Only for shielded addresses.
12+
# MINER_MEMO=
13+
14+
# === NETWORK SELECTION ===
15+
# Options: Mainnet, Testnet
16+
NETWORK=Testnet
17+
18+
# === PORTS ===
19+
# Uncomment and modify to override defaults
20+
# RPC_PORT=18232 # 18232 Testnet, 8232 Mainnet (internal, not exposed)
21+
# PEER_PORT=18233 # 18233 Testnet, 8233 Mainnet (P2P network)
22+
# STRATUM_PORT=3333 # Miners connect to this port
23+
24+
# === NHEQMINER (optional, use --profile miner) ===
25+
# Worker name suffix (address.WORKER_NAME)
26+
# WORKER_NAME=docker
27+
# CPU threads (default: 1)
28+
# CPU_THREADS=1
29+
30+
# === USAGE ===
31+
# 1. Copy to .env: cp .env.example .env
32+
# 2. Set MINER_ADDRESS
33+
# 3. Start: docker compose up -d
34+
# 4. Check sync: docker compose logs -f zebra
35+
# 5. Once synced, either:
36+
# a) Start built-in miner: docker compose --profile miner up -d nheqminer
37+
# b) Connect external miner: nheqminer -l <host>:3333 -u <address>.worker1 -t <threads>
38+
# 6. Web UI: http://<host>:8080

docker/mining/README.md

Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
# Zebra + S-NOMP Mining Pool
2+
3+
Docker Compose setup for running a Zcash mining pool with Zebra and S-NOMP.
4+
5+
## Architecture
6+
7+
```
8+
┌─────────────┐ ┌───────────┐ ┌─────────────┐
9+
│ Miners │─────▶│ S-NOMP │────▶│ Zebra │
10+
│ (nheqminer, │:3333 │ (Stratum) │:RPC │ (Full Node) │
11+
│ Antminer) │ │ │ │ │
12+
└─────────────┘ └──────┬────┘ └─────────────┘
13+
14+
15+
┌─────────┐
16+
│ Redis │
17+
│ (Stats) │
18+
└─────────┘
19+
```
20+
21+
- **Zebra**: Zcash full node - validates blocks, provides `getblocktemplate`
22+
- **S-NOMP**: Stratum mining pool - distributes work to miners, submits blocks
23+
- **Redis**: Stores share counts and pool statistics
24+
25+
All block rewards go to the address configured in `MINER_ADDRESS`.
26+
27+
## Quick Start
28+
29+
```bash
30+
# 1. Configure
31+
cp .env.example .env
32+
# Edit .env - set MINER_ADDRESS (required)
33+
34+
# 2. Start
35+
docker compose up -d
36+
37+
# 3. Wait for Zebra to sync (hours)
38+
docker compose logs -f zebra
39+
40+
# 4. Once synced, start mining (choose one):
41+
42+
# Option A: Built-in nheqminer container
43+
docker compose --profile miner up -d nheqminer
44+
45+
# Option B: External miner
46+
nheqminer -l <host>:3333 -u <address>.worker1 -t <threads>
47+
```
48+
49+
## Configuration
50+
51+
Edit `.env` to configure:
52+
53+
| Variable | Default | Description |
54+
|-----------------|------------|----------------------------------------------|
55+
| `MINER_ADDRESS` | (required) | Transparent address for block rewards |
56+
| `NETWORK` | `Testnet` | `Mainnet` or `Testnet` |
57+
| `RPC_PORT` | `18232` | Zebra RPC port (18232 Testnet, 8232 Mainnet) |
58+
| `PEER_PORT` | `18233` | P2P port (18233 Testnet, 8233 Mainnet) |
59+
| `STRATUM_PORT` | `3333` | Port miners connect to |
60+
| `WORKER_NAME` | `docker` | Worker name suffix (for nheqminer container) |
61+
| `CPU_THREADS` | `1` | CPU threads for nheqminer |
62+
63+
## Checking Sync Status
64+
65+
Zebra must fully sync before mining can begin.
66+
67+
```bash
68+
# Quick status
69+
docker exec zebra curl -s -H "Content-Type: application/json" \
70+
localhost:18232 -d '{"jsonrpc":"2.0","id":1,"method":"getblockchaininfo","params":[]}' \
71+
| grep -oE '"(blocks|estimatedheight)":[0-9]+'
72+
73+
# Watch sync progress
74+
docker logs -f zebra 2>&1 | grep -E "state_tip|verified"
75+
76+
# Detailed info
77+
docker exec zebra curl -s -H "Content-Type: application/json" \
78+
localhost:18232 -d '{"jsonrpc":"2.0","id":1,"method":"getblockchaininfo","params":[]}'
79+
```
80+
81+
## Connecting Miners
82+
83+
### Built-in nheqminer Container
84+
85+
The setup includes an optional nheqminer container for CPU mining. It uses a Docker Compose profile, so it won't start by default.
86+
87+
```bash
88+
# Start the miner (after Zebra is synced)
89+
docker compose --profile miner up -d nheqminer
90+
91+
# View miner logs
92+
docker compose logs -f nheqminer
93+
94+
# Stop the miner
95+
docker compose --profile miner stop nheqminer
96+
97+
# Adjust CPU threads in .env
98+
CPU_THREADS=4
99+
```
100+
101+
### External nheqminer (CPU/GPU)
102+
103+
```bash
104+
# CPU mining
105+
./nheqminer -l <pool-host>:3333 -u <your-address>.worker1 -t <threads>
106+
107+
# Example
108+
./nheqminer -l 192.168.1.100:3333 -u t27eWDgjFYJGVXmzrXeVjnb5J3uXDM9xH9v.rig1 -t 4
109+
```
110+
111+
### Antminer Z15
112+
113+
1. Open miner web interface
114+
2. Go to **Miner Configuration**
115+
3. Set:
116+
- **Pool URL**: `stratum+tcp://<pool-host>:3333`
117+
- **Worker**: `<your-address>.z15`
118+
- **Password**: `x`
119+
120+
## Web Interface
121+
122+
S-NOMP provides a web UI at `http://<host>:8080` showing:
123+
124+
- Pool hashrate
125+
- Connected workers
126+
- Found blocks
127+
- Per-worker statistics
128+
129+
API endpoint: `http://<host>:8080/api/stats`
130+
131+
## Ports
132+
133+
| Port | Service | Purpose |
134+
|------------|---------|-------------------------------|
135+
| 3333 | S-NOMP | Stratum (miners connect here) |
136+
| 8080 | S-NOMP | Web UI and API |
137+
| 18233/8233 | Zebra | P2P network (Testnet/Mainnet) |
138+
139+
Internal only (not exposed):
140+
141+
- 18232/8232: Zebra RPC
142+
- 6379: Redis
143+
144+
## Operations
145+
146+
```bash
147+
# Start all services (without miner)
148+
docker compose up -d
149+
150+
# Start all services including miner
151+
docker compose --profile miner up -d
152+
153+
# Stop all services
154+
docker compose down
155+
156+
# View logs
157+
docker compose logs -f # All services
158+
docker compose logs -f zebra # Zebra only
159+
docker compose logs -f s-nomp # S-NOMP only
160+
docker compose logs -f nheqminer # Miner only
161+
162+
# Restart a service
163+
docker compose restart s-nomp
164+
165+
# Rebuild after updates
166+
docker compose build --no-cache s-nomp
167+
docker compose build --no-cache nheqminer
168+
docker compose up -d s-nomp
169+
170+
# Check service status
171+
docker compose ps
172+
docker compose --profile miner ps # Include miner
173+
174+
# Shell into container
175+
docker compose exec zebra bash
176+
docker compose exec s-nomp bash
177+
docker compose exec nheqminer bash
178+
```
179+
180+
## Data Persistence
181+
182+
Zebra chain data is stored in a Docker volume (`zebra-data`). This persists across container restarts.
183+
184+
```bash
185+
# View volume
186+
docker volume ls | grep mining
187+
188+
# Remove all data (will require full resync!)
189+
docker compose down -v
190+
```
191+
192+
## Troubleshooting
193+
194+
### S-NOMP: "mempool is not active"
195+
196+
Zebra is still syncing. Wait for sync to complete.
197+
198+
```bash
199+
docker compose logs zebra | tail -20
200+
```
201+
202+
### S-NOMP keeps restarting
203+
204+
Check logs for errors:
205+
206+
```bash
207+
docker compose logs s-nomp | tail -50
208+
```
209+
210+
### Miners can't connect
211+
212+
1. Check S-NOMP is running: `docker compose ps`
213+
2. Check port is open: `nc -zv <host> 3333`
214+
3. Check firewall allows port 3333
215+
216+
### Zebra not syncing
217+
218+
1. Check peer connections:
219+
220+
```bash
221+
docker exec zebra curl -s -H "Content-Type: application/json" \
222+
localhost:18232 -d '{"jsonrpc":"2.0","id":1,"method":"getinfo","params":[]}' \
223+
| grep connections
224+
```
225+
226+
2. Ensure port 18233 (Testnet) or 8233 (Mainnet) is accessible
227+
228+
### Reset everything
229+
230+
```bash
231+
docker compose down -v
232+
docker compose up -d
233+
```
234+
235+
## Switching Networks
236+
237+
To switch between Testnet and Mainnet:
238+
239+
1. Stop services: `docker compose down`
240+
2. Edit `.env`:
241+
242+
```bash
243+
NETWORK=Mainnet
244+
MINER_ADDRESS=t1YourMainnetAddress
245+
```
246+
247+
3. Start: `docker compose up -d`
248+
249+
## Security Notes
250+
251+
- RPC port is internal only (not exposed to host)
252+
- Cookie authentication is disabled for S-NOMP compatibility

docker/mining/docker-compose.yml

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
services:
2+
zebra:
3+
build:
4+
context: ../..
5+
dockerfile: docker/Dockerfile
6+
container_name: zebra
7+
environment:
8+
- ZEBRA_NETWORK__NETWORK=${NETWORK:-Testnet}
9+
- ZEBRA_RPC__LISTEN_ADDR=0.0.0.0:${RPC_PORT:-18232}
10+
- ZEBRA_RPC__ENABLE_COOKIE_AUTH=false
11+
- ZEBRA_SYNC__PARALLEL_CPU_THREADS=12
12+
- ZEBRA_MINING__MINER_ADDRESS=${MINER_ADDRESS:?MINER_ADDRESS is required}
13+
- ZEBRA_MINING__MINER_DATA=${MINER_DATA:-}
14+
- ZEBRA_MINING__MINER_MEMO=${MINER_MEMO:-}
15+
volumes:
16+
- zebra-data:/home/zebra/.cache/zebra
17+
ports:
18+
- "${PEER_PORT:-18233}:${PEER_PORT:-18233}"
19+
networks:
20+
- mining
21+
restart: unless-stopped
22+
tty: true
23+
healthcheck:
24+
test: ["CMD-SHELL", "curl -sf http://127.0.0.1:8080/healthy || exit 1"]
25+
interval: 30s
26+
timeout: 10s
27+
retries: 3
28+
start_period: 90s
29+
30+
redis:
31+
image: redis:7-alpine
32+
container_name: redis
33+
networks:
34+
- mining
35+
restart: unless-stopped
36+
37+
s-nomp:
38+
build:
39+
context: https://github.com/ZcashFoundation/s-nomp.git
40+
dockerfile: Dockerfile.arch
41+
container_name: s-nomp
42+
environment:
43+
- ZEBRA_HOST=zebra
44+
- ZEBRA_RPC_PORT=${RPC_PORT:-18232}
45+
- REDIS_HOST=redis
46+
- STRATUM_PORT=${STRATUM_PORT:-3333}
47+
- NETWORK=${NETWORK:-Testnet}
48+
- POOL_ADDRESS=${MINER_ADDRESS}
49+
ports:
50+
- "${STRATUM_PORT:-3333}:${STRATUM_PORT:-3333}"
51+
- "8080:8080"
52+
depends_on:
53+
zebra:
54+
condition: service_healthy
55+
redis:
56+
condition: service_started
57+
networks:
58+
- mining
59+
restart: unless-stopped
60+
volumes:
61+
- ./s-nomp-entrypoint.sh:/app/s-nomp-entrypoint.sh:ro
62+
entrypoint: /app/s-nomp-entrypoint.sh
63+
64+
nheqminer:
65+
build:
66+
context: https://github.com/ZcashFoundation/nheqminer.git
67+
dockerfile: Dockerfile
68+
container_name: nheqminer
69+
environment:
70+
- POOL_HOST=s-nomp
71+
- POOL_PORT=${STRATUM_PORT:-3333}
72+
- WORKER_ADDRESS=${MINER_ADDRESS}
73+
- WORKER_NAME=${WORKER_NAME:-docker}
74+
- CPU_THREADS=${CPU_THREADS:-1}
75+
command: >
76+
-l ${POOL_HOST:-s-nomp}:${STRATUM_PORT:-3333}
77+
-u ${MINER_ADDRESS}.${WORKER_NAME:-docker}
78+
-t ${CPU_THREADS:-1}
79+
depends_on:
80+
- s-nomp
81+
networks:
82+
- mining
83+
restart: unless-stopped
84+
profiles:
85+
- miner
86+
87+
networks:
88+
mining:
89+
driver: bridge
90+
91+
volumes:
92+
zebra-data:

docker/mining/s-nomp-entrypoint.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
/app/docker-entrypoint.sh true
5+
6+
sed -i 's/}$/,"switching":{}}/g' /app/config.json
7+
sed -i 's/"diff": 0.05/"tls": false, "diff": 0.05/g' /app/pool_configs/zcash.json
8+
9+
if [ "$NETWORK" = "Mainnet" ]; then
10+
sed -i 's|tmRGc4CD1UyUdbSJmTUzcB6oDqk4qUaHnnh|t1Hsc1LR8yKnbbe3twRp88p6vFfC5t7DLbs|g' /app/pool_configs/zcash.json
11+
sed -i 's|blockRefreshInterval": 500|blockRefreshInterval": 2000|g' /app/config.json
12+
fi
13+
14+
exec node init.js

0 commit comments

Comments
 (0)