A NixOS configuration that deploys a Bitcoin Core node with IPC-based monitoring. A Rust exporter connects to bitcoind's multiprocess IPC socket, exports metrics to Prometheus, and visualizes them on a public Grafana dashboard over HTTPS.
bitcoind (-ipcbind=unix)
|
v Unix socket (Cap'n Proto IPC)
ipc-exporter-rust :9332
|
v Prometheus scrape
Prometheus :9090
|
v data source
Grafana :3000 (anonymous read-only)
|
v reverse proxy
Caddy :443 (Cloudflare DNS ACME)
- A VPS running NixOS (tested on Hetzner Cloud CX22)
- sops and age installed locally
- A Cloudflare API token with DNS edit permissions for your domain
- just command runner
git clone <this-repo>
cd ipc-dashEdit the settings block in flake.nix to match your server:
hostName-- your hostnamedomain-- your domain (used for Caddy and Grafana)networkInterface-- your server's network interfaceipAddress/prefixLength-- your server's IPgateway-- your provider's gatewaysshKeys-- your SSH public key(s)
In justfile, set host to your server's IP or hostname.
The included secrets.yaml is encrypted with keys you can't decrypt. Delete it and create your own:
# Generate a local age key (skip if you already have one)
age-keygen -o ~/.config/sops/age/keys.txt
# Get your local public key
age-keygen -y ~/.config/sops/age/keys.txtEdit .sops.yaml and replace both keys:
&local-- your local age public key&server-- leave as placeholder for now (filled after first deploy)
keys:
- &local age1your-local-key-here
- &server age1your-server-key-here
creation_rules:
- path_regex: secrets\.yaml$
key_groups:
- age:
- *local
- *serverFor the initial deploy, temporarily comment out the &server key and its reference so you can encrypt with just your local key:
rm secrets.yaml
# Create plaintext, then encrypt in-place
cat > secrets.yaml <<'EOF'
caddy-cloudflare-token: your-cloudflare-api-token
grafana-secret-key: some-random-hex-string
EOF
sops --encrypt --in-place secrets.yamljust deployThis uses nixos-anywhere to wipe and install NixOS on the target.
sops-nix automatically derives an age key from the server's SSH host key for decryption -- no manual key generation needed on the server. But you need the corresponding public key in .sops.yaml so that sops can encrypt secrets the server can read.
Get the age public key from the server's SSH host key:
ssh root@<your-server> "cat /etc/ssh/ssh_host_ed25519_key.pub" | nix-shell -p ssh-to-age --run ssh-to-agePaste the output into .sops.yaml as the &server key, uncomment it, then re-encrypt:
echo y | sops updatekeys secrets.yamljust switchThis builds locally and runs nixos-rebuild switch on the remote.
After deploy, verify:
# Check service status
just status
# Check metrics endpoint
ssh root@<your-server> curl -s localhost:9332/metrics | head -20| File | Purpose |
|---|---|
flake.nix |
Nix flake with nixpkgs, disko, sops-nix, and ipc-exporter inputs |
configuration.nix |
All NixOS services: bitcoind, ipc-exporter, tor, prometheus, grafana, caddy, sops |
disk-config.nix |
Disk partitioning layout (disko) |
hardware-configuration.nix |
Hardware-specific config (generated by nixos-anywhere) |
grafana/bitcoin-ipc.json |
Grafana dashboard for IPC-exported Bitcoin Core metrics |
grafana/node-dashboard.json |
Grafana dashboard for system/node metrics |
.sops.yaml |
sops encryption key configuration |
secrets.yaml |
Encrypted secrets (Cloudflare token, Grafana secret key) |
justfile |
Command runner recipes for deploy, switch, sync, etc. |