Skip to content

feat: bitcoind-backend preset for split-deployment hosts#3

Merged
josibake merged 3 commits into
mainfrom
refactor/bitcoind-backend
May 19, 2026
Merged

feat: bitcoind-backend preset for split-deployment hosts#3
josibake merged 3 commits into
mainfrom
refactor/bitcoind-backend

Conversation

@josibake
Copy link
Copy Markdown
Member

@josibake josibake commented May 19, 2026

Summary

A bitcoind-backend preset: same bitcoind + fulcrum + ZMQ stack public-frigate configures, exposed on a private interface, but with no frigate process. Pairs with frigate-edge on a separate consumer host. Lets you put the backend services close to the consumer when they need to live in different DCs (e.g. avoid ~25ms inter-DC RTT for the latency-sensitive RPC path) without making the consumer carry the ~950 GB of bitcoind+txindex+fulcrum storage.

Two logical commits:

  1. refactor: extract bitcoind + fulcrum into a shared internal helper — moves the inline bitcoind/fulcrum/ZMQ/exposeBackends logic out of public-frigate.nix into a new _internal/bitcoin-stack.nix, mirroring the pattern already used for frigate-tls-acme. No behavior change; regtest-preset continues to pass against the refactored module.

  2. feat: add bitcoind-backend preset for split-deployment backend host — the new preset itself. Reuses bitcoin-stack. Adds:

    • nixosModules.bitcoind-backend — the preset alone (consumer brings nix-bitcoin)
    • nixosModules.bitcoind-backend-host — batteries-included (nix-bitcoin + preset)
    • test/regtest-backend.nix — single-VM nixosTest validating bindings, auth, and 401 on bad password

On bitcoin-implementation flexibility

The preset's external contract is "Bitcoin Core RPC + ZMQ sequence on a private interface." The current implementation uses nix-bitcoin's services.bitcoind. To swap to a Core fork like Knots: just set services.bitcoind.package in the consumer's host config — no preset change. For a non-Core implementation that speaks the same RPC + ZMQ contract (e.g. btcd), a sibling preset (btcd-backend?) would provide the same exposed interface via different internals; frigate-edge doesn't know the difference.

Test plan

  • CI: `nix flake check` green (all five nixosTests: regtest-e2e, regtest-preset, regtest-edge, regtest-backend, wireguard-mesh)
  • CI: `nix fmt --ci` green
  • Local: `nix flake check --all-systems --no-build` clean, formatter clean. The new regtest-backend test exercises the preset's full surface: bindings, rpcauth round-trip, wrong-password rejection.

🤖 Generated with Claude Code

josibake and others added 3 commits May 19, 2026 18:27
`public-frigate` configured bitcoind + fulcrum + ZMQ + optional mesh
exposure inline. Once a backend-only preset becomes necessary (a host
that runs the same stack for a remote `frigate-edge` consumer, with
no frigate of its own — see following commit), both presets need the
same wiring. Move it to a private `_internal/bitcoin-stack.nix`
helper, mirroring the pattern already used for `frigate-tls-acme`.

The helper takes options under `services._roost.bitcoin-stack` (an
internal namespace, marked `internal = true` throughout), and parent
presets wire them from their own typed options.

No behavior change for existing consumers — `public-frigate`'s
external surface is identical (same options, same defaults, same
runtime config). Verified by `regtest-preset`, which exercises the
full preset and continues to pass against the refactored module.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`bitcoind-backend` is the sibling preset to `public-frigate`: bitcoind
+ fulcrum + ZMQ sequence publisher, exposed on a private interface,
with no frigate process on this box. Pairs with `frigate-edge` on
remote consumer hosts. Useful when the latency-sensitive consumer is
in a different DC from the existing public-frigate host (the
loopback cost is loopback; the remote-backend cost is per-call RTT)
and the consumer host can't afford the ~950 GB storage that
bitcoind+fulcrum needs.

Shares the bitcoind+fulcrum+expose logic with `public-frigate` via
the `_internal/bitcoin-stack.nix` helper from the preceding commit;
this preset is mostly an options surface and a small `mkIf` that
wires the helper.

Also adds:
  - `nixosModules.bitcoind-backend-host` — a batteries-included
    bundle (nix-bitcoin + the preset), so consumers needing only
    `roost` in their flake inputs can deploy a backend host.
  - `test/regtest-backend.nix` — single-VM nixosTest that boots
    `bitcoind-backend`, mines 101 regtest blocks, and verifies the
    backend ports listen on the configured mesh address, the
    configured rpcauth user can authenticate, and a wrong password
    is rejected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Ruff F541 fired in CI because the curl invocation in regtest-backend
was f-stringed but the only interpolations were Nix `${...}`, which
are resolved at Nix eval time. By the time Python sees the lines,
there are no `{}` placeholders left — drop the `f` prefix, and
collapse `{{ }}` back to `{ }` in the JSON bodies (those were only
escaped to survive f-string syntax).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@josibake josibake merged commit ac318bb into main May 19, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant