Skip to content

Commit cb83c32

Browse files
committed
Add Docker Compose setup for Zebra and S-NOMP mining pool
1 parent 7d8f3d6 commit cb83c32

File tree

3 files changed

+386
-0
lines changed

3 files changed

+386
-0
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: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
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+
- Pool hashrate
124+
- Connected workers
125+
- Found blocks
126+
- Per-worker statistics
127+
128+
API endpoint: `http://<host>:8080/api/stats`
129+
130+
## Ports
131+
132+
| Port | Service | Purpose |
133+
|------------|---------|-------------------------------|
134+
| 3333 | S-NOMP | Stratum (miners connect here) |
135+
| 8080 | S-NOMP | Web UI and API |
136+
| 18233/8233 | Zebra | P2P network (Testnet/Mainnet) |
137+
138+
Internal only (not exposed):
139+
- 18232/8232: Zebra RPC
140+
- 6379: Redis
141+
142+
## Operations
143+
144+
```bash
145+
# Start all services (without miner)
146+
docker compose up -d
147+
148+
# Start all services including miner
149+
docker compose --profile miner up -d
150+
151+
# Stop all services
152+
docker compose down
153+
154+
# View logs
155+
docker compose logs -f # All services
156+
docker compose logs -f zebra # Zebra only
157+
docker compose logs -f s-nomp # S-NOMP only
158+
docker compose logs -f nheqminer # Miner only
159+
160+
# Restart a service
161+
docker compose restart s-nomp
162+
163+
# Rebuild after updates
164+
docker compose build --no-cache s-nomp
165+
docker compose build --no-cache nheqminer
166+
docker compose up -d s-nomp
167+
168+
# Check service status
169+
docker compose ps
170+
docker compose --profile miner ps # Include miner
171+
172+
# Shell into container
173+
docker compose exec zebra bash
174+
docker compose exec s-nomp bash
175+
docker compose exec nheqminer bash
176+
```
177+
178+
## Data Persistence
179+
180+
Zebra chain data is stored in a Docker volume (`zebra-data`). This persists across container restarts.
181+
182+
```bash
183+
# View volume
184+
docker volume ls | grep mining
185+
186+
# Remove all data (will require full resync!)
187+
docker compose down -v
188+
```
189+
190+
## Troubleshooting
191+
192+
### S-NOMP: "mempool is not active"
193+
194+
Zebra is still syncing. Wait for sync to complete.
195+
196+
```bash
197+
docker compose logs zebra | tail -20
198+
```
199+
200+
### S-NOMP keeps restarting
201+
202+
Check logs for errors:
203+
204+
```bash
205+
docker compose logs s-nomp | tail -50
206+
```
207+
208+
### Miners can't connect
209+
210+
1. Check S-NOMP is running: `docker compose ps`
211+
2. Check port is open: `nc -zv <host> 3333`
212+
3. Check firewall allows port 3333
213+
214+
### Zebra not syncing
215+
216+
1. Check peer connections:
217+
```bash
218+
docker exec zebra curl -s -H "Content-Type: application/json" \
219+
localhost:18232 -d '{"jsonrpc":"2.0","id":1,"method":"getinfo","params":[]}' \
220+
| grep connections
221+
```
222+
2. Ensure port 18233 (Testnet) or 8233 (Mainnet) is accessible
223+
224+
### Reset everything
225+
226+
```bash
227+
docker compose down -v
228+
docker compose up -d
229+
```
230+
231+
## Switching Networks
232+
233+
To switch between Testnet and Mainnet:
234+
235+
1. Stop services: `docker compose down`
236+
2. Edit `.env`:
237+
```bash
238+
NETWORK=Mainnet
239+
MINER_ADDRESS=t1YourMainnetAddress
240+
```
241+
3. Start: `docker compose up -d`
242+
243+
## Security Notes
244+
245+
- RPC port is internal only (not exposed to host)
246+
- Cookie authentication is disabled for S-NOMP compatibility

docker/mining/docker-compose.yml

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
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+
24+
redis:
25+
image: redis:7-alpine
26+
container_name: redis
27+
networks:
28+
- mining
29+
restart: unless-stopped
30+
31+
s-nomp:
32+
build:
33+
context: https://github.com/ZcashFoundation/s-nomp.git
34+
dockerfile: Dockerfile.arch
35+
container_name: s-nomp
36+
environment:
37+
- ZEBRA_HOST=zebra
38+
- ZEBRA_RPC_PORT=${RPC_PORT:-18232}
39+
- REDIS_HOST=redis
40+
- STRATUM_PORT=${STRATUM_PORT:-3333}
41+
- NETWORK=${NETWORK:-Testnet}
42+
- POOL_ADDRESS=${MINER_ADDRESS}
43+
ports:
44+
- "${STRATUM_PORT:-3333}:${STRATUM_PORT:-3333}"
45+
- "8080:8080"
46+
depends_on:
47+
- zebra
48+
- redis
49+
networks:
50+
- mining
51+
restart: unless-stopped
52+
entrypoint: >
53+
/bin/bash -c '
54+
/app/docker-entrypoint.sh true &&
55+
sed -i "s/}$$/,\"switching\":{}}/g" /app/config.json &&
56+
sed -i "s/\"diff\": 0.05/\"tls\": false, \"diff\": 0.05/g" /app/pool_configs/zcash.json &&
57+
if [ "$$NETWORK" = "Mainnet" ]; then
58+
sed -i "s|tmRGc4CD1UyUdbSJmTUzcB6oDqk4qUaHnnh|t1Hsc1LR8yKnbbe3twRp88p6vFfC5t7DLbs|g" /app/pool_configs/zcash.json
59+
sed -i "s|blockRefreshInterval\": 500|blockRefreshInterval\": 2000|g" /app/config.json
60+
fi &&
61+
echo "Waiting for Zebra RPC to be ready..." &&
62+
while true; do
63+
RESP=$$(curl -s http://$$ZEBRA_HOST:$$ZEBRA_RPC_PORT -X POST -H "content-type: application/json" -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"getinfo\",\"params\":[]}" 2>/dev/null)
64+
if echo "$$RESP" | grep -q result; then
65+
echo "Zebra is ready, starting s-nomp..."
66+
break
67+
fi
68+
echo "Zebra not ready, waiting 5s..."
69+
sleep 5
70+
done &&
71+
exec node init.js
72+
'
73+
74+
nheqminer:
75+
build:
76+
context: https://github.com/ZcashFoundation/nheqminer.git
77+
dockerfile: Dockerfile
78+
container_name: nheqminer
79+
environment:
80+
- POOL_HOST=s-nomp
81+
- POOL_PORT=${STRATUM_PORT:-3333}
82+
- WORKER_ADDRESS=${MINER_ADDRESS}
83+
- WORKER_NAME=${WORKER_NAME:-docker}
84+
- CPU_THREADS=${CPU_THREADS:-1}
85+
command: >
86+
-l ${POOL_HOST:-s-nomp}:${STRATUM_PORT:-3333}
87+
-u ${MINER_ADDRESS}.${WORKER_NAME:-docker}
88+
-t ${CPU_THREADS:-1}
89+
depends_on:
90+
- s-nomp
91+
networks:
92+
- mining
93+
restart: unless-stopped
94+
profiles:
95+
- miner
96+
97+
networks:
98+
mining:
99+
driver: bridge
100+
101+
volumes:
102+
zebra-data:

0 commit comments

Comments
 (0)