Open source: github.com/FlipThisCrypto/plot-butler
Operations console and transfer scheduler for Gigahorse Chia plotting with a reserved GPU for chia_recompute_server. Plot rsync shares the network path with farming recompute — farming wins.
Bulk plot shipping can starve recompute / harvester latency and cause stale shares. Plot Butler:
- Caps and serializes plot transfers
- Pauses shipping when recompute or harvester quality latency is dangerous
- Surfaces farming health on a local dashboard and Prometheus metrics
- Cleans orphan Gigahorse temp files before they fill the plot NVMe
git clone https://github.com/FlipThisCrypto/plot-butler.git
cd plot-butler
# Edit paths/REMOTE/plotter args in plot_butler.py, plotter_loop.sh, and unit files for your hosts
./install-systemd.sh
sudo systemctl restart chia-recompute.service plot-butler.serviceDashboard default: http://<host>:8088
make test
./scripts/smoke_check.sh
make healthPlot rsync and farming recompute often share the same path to the farmer (e.g. Tailscale).
Farming wins. Transfers throttle and pause when recompute or harvester quality latency enters stale-share range.
| Unit | Role |
|---|---|
plot-butler.service |
Dashboard + transfer scheduler + temp cleanup |
gigahorse-plotter.service |
Plot loop (typically GPU 0) |
chia-recompute.service |
Farming recompute (typically GPU 1, port 11989) |
Install/update units and priority drop-ins:
./install-systemd.sh
sudo systemctl restart chia-recompute.service plot-butler.service| Knob | Default | Env override |
|---|---|---|
| Max concurrent rsync | 1 | PLOT_BUTLER_MAX_TRANSFERS |
| Bandwidth cap | 12 MiB/s | PLOT_BUTLER_BWLIMIT_KBPS |
| Warm start after pause | 6 MiB/s | PLOT_BUTLER_BWLIMIT_WARM_KBPS |
| Pause on recompute p90 | 5000 ms | PLOT_BUTLER_RECOMPUTE_PAUSE_P90_MS |
| Pause on harvester max | 15 s | PLOT_BUTLER_HARVESTER_PAUSE_S |
Other:
- Prefer destinations away from the mount of the worst recent quality lookup
- SIGTERM in-flight rsync when farming gate trips (
--partialresumes later) - Orphan
cuda_plot_tmp*cleanup every 5 minutes - Optional
PLOT_BUTLER_API_TOKENfor POST controls - Optional
PLOT_BUTLER_BIND(default0.0.0.0)
| Path | Description |
|---|---|
GET / |
Dashboard |
GET /api/state |
Full telemetry JSON |
GET /api/health |
Compact health (200 / 503) |
GET /api/metrics |
Prometheus text metrics |
POST /api/pause-transfers |
Manual pause |
POST /api/resume-transfers |
Manual resume |
POST /api/start-plotting |
Start plotter unit |
POST /api/start-recompute |
Start recompute unit |
This repository ships with paths and hostnames for a reference deployment. Before production use, set:
- Staging / spool / temp directories in
plot_butler.py - SSH remote farmer host (
REMOTE) - Plotter binary and keys in
plotter.env(copy fromplotter.env.example; never commit secrets) - Systemd unit user and working directories
python3 -m unittest discover -s tests -v
# or
make testplot-butler-events.log— JSON events (pause/resume/transfer/cleanup)journalctl -u plot-butler.servicejournalctl -u chia-recompute.service
sudo cp logrotate-plot-butler.conf /etc/logrotate.d/plot-butler- Check
GET /api/healthand dashboard recompute/harvester latency. - If degraded: transfers auto-pause; confirm with
POST /api/pause-transfers. - Watch
journalctl -u chia-recompute.service -ffor request times (want << 5s). - On farmer: quality lookups in the harvester debug log should be << 20s.
- Free NVMe if staging full: plot-butler cleans orphan
cuda_plot_tmp*; verifydf -h /. - When healthy:
POST /api/resume-transfers(warm bandwidth applies for 30m).
See VERSION in plot_butler.py and CHANGELOG.md.
MIT — see LICENSE.