Deploy
Pipeline
scripts/deploy.sh runs the full deploy from bt (build node) to gd (production VPS):
[0/5] cargo audit gate — 0 unignored advisories required
[1/5] cargo build --release — builds on bt (12 cores, 46G RAM)
[2/5] scp binary bt → gd — ships to /tmp/cochranblock-new, then mv -f to target
[3/5] hot reload on gd — nohup restart; new binary kills old via PID lockfile
[4/5] Cloudflare cache purge — approuter purge-cache across all 10 domains
[5/5] IndexNow ping — notifies search engines of updated URLs
Run It
bash scripts/deploy.sh
The script sets PATH explicitly to avoid Mac mount paths on the bt Linux node.
Hot Reload
The binary uses a PID lockfile at startup. On restart, the new process reads the lockfile, sends SIGTERM to the old process, waits, then takes the port. Zero-downtime on clean restarts.
Build Node (bt)
bt is the IRONHIVE cluster node: 12 cores, 46G RAM, x86_64 Debian. The release build takes ~60 seconds. The binary is compiled locally and shipped to gd — gd never compiles.
Production Node (gd)
gd is the serving node: ~$10/month VPS with a Cloudflare Tunnel. The tunnel terminates at approuter (:8080) which proxies to cochranblock (:8081).
Environment
Deploy reads .env from the approuter monorepo for Cloudflare credentials. The binary reads its own env vars at startup for redb path, SMTP config, etc.
Expected Deploy Output
[0/5] cargo audit gate
Scanning Cargo.lock for vulnerabilities (119 crate dependencies)
not found — 0 advisories
[1/5] cargo build --release
Finished `release` profile [optimized] target(s) in 58.3s
[2/5] scp binary to gd
cochranblock-new: 100% 13MB
[3/5] hot reload on gd
INFO cochranblock: sent SIGTERM to old PID 12847
INFO cochranblock: old PID 12847 exited cleanly
INFO cochranblock: cochranblock listening on http://127.0.0.1:8081
[4/5] Cloudflare cache purge — 10 domains purged
[5/5] IndexNow ping — 200 OK
deploy complete
Gotchas
PATH on bt — The bt node’s default PATH includes Mac mount paths that shadow the real cargo. scripts/deploy.sh sets PATH explicitly. If running cargo by hand on bt, prefix with:
export PATH="/home/mcochran/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
REDB_PATH is required at runtime — If unset, the binary panics on first intake or analytics write. Set it before starting:
REDB_PATH=/var/lib/cochranblock/db.redb ./cochranblock
Or put it in .env.
No auto-rollback — The mv -f that replaces the binary is atomic, but if the new binary fails to bind (port conflict, bad env), the old one is already gone. Keep the previous binary at /tmp/cochranblock-prev manually if deploying a risky change.
Hot reload only on clean restarts — SIGTERM is sent to the old PID. If the old binary hung or was force-killed without cleaning the lockfile, the new binary may send SIGTERM to a stale PID and wait 5 seconds before binding. Safe, but slow.
▸ THE COCHRAN BLOCK, LLC · CAGE 1CQ66 · UEI W7X3HAQL9CF9 · UNLICENSE · cochranblock.org