Skip to content

Deployment

This page is for operators running walletrs in production or staging. For local development on regtest, the Quickstart is enough.

The shipped docker-compose.yml brings up a regtest stack — bitcoind + electrs + walletrs — in one command:

Terminal window
docker compose up --build

walletrs exposes both surfaces on the host: 127.0.0.1:50051 (gRPC) and 127.0.0.1:8080 (HTTP / JSON). Both share the same handlers and the same bearer token. The first start logs a STORE THIS — generated auth token: <token> line; copy it into your client.

To pin a known token across restarts, drop a .env next to the compose file:

Terminal window
WALLETRS_AUTH_TOKEN=$(openssl rand -hex 32)
WALLETRS_KEK=$(openssl rand -base64 32) # required if you create system-managed keys

Switch networks by editing the bitcoind / electrs flags and the BITCOIN_NETWORK env in the walletrs service.

Pull the published image:

Terminal window
docker run --rm -p 50051:50051 -p 8080:8080 \
-v walletrs-data:/data \
-e BITCOIN_NETWORK=signet \
-e ELECTRS_URL=tcp://your-electrs:50001 \
-e WALLETRS_AUTH_TOKEN=$(openssl rand -hex 32) \
-e WALLETRS_KEK=$(openssl rand -base64 32) \
ghcr.io/n1rna/walletrs:latest

Released images are tagged on every v* git tag — :0.1.0, :0.1, :latest. Multi-arch (linux/amd64 + linux/arm64).

Terminal window
cargo build --release --bin walletrs
./target/release/walletrs

Pre-built binaries are also attached to GitHub releases for x86_64-unknown-linux-gnu, x86_64-apple-darwin, and aarch64-apple-darwin.

walletrs serves plaintext gRPC and plaintext HTTP. Native TLS on either layer is not in v0.1.0 — terminate TLS at a reverse proxy.

walletrs-grpc.example.com {
reverse_proxy h2c://127.0.0.1:50051
}
walletrs-api.example.com {
reverse_proxy 127.0.0.1:8080
}

(Caddy serves HTTP/2 cleartext upstreams via h2c:// for the gRPC port; the HTTP/JSON port is plain HTTP/1.1. Traefik / nginx need analogous configuration.) Point the certificate’s hostname at whichever public subdomain you’ve chosen and have your client trust that proxy.

What to back up:

  • WALLETRS_KEK — without it, system-managed keys are dead weight. Highest-criticality secret; offsite, encrypted, multiple copies.
  • The storage tier — local filesystem under WALLETRS_STORAGE_PATH, or the S3 / R2 bucket. Snapshot daily for the first week, weekly after that.
  • Customer xpubs — these are also stored in the wallet bucket but you should keep an out-of-band record so you can re-create wallets if storage is destroyed.
  • proto/walletrpc.proto at the version your clients depend on — pinned via tag in the walletrs git history.

What you don’t need to back up:

  • The walletrs binary itself (rebuild from source / pull image).
  • The auth token (regenerate; just push a new value to clients).

WALLETRS_KEK is a base64-encoded 32-byte key wrapping system-managed private key material. There is no built-in rotation flow today. The pragmatic procedure:

  1. Stop walletrs.
  2. Decrypt every StoredManagedKey blob with the old KEK (e.g. via a one-off script using crates/server/src/storage/crypto.rs).
  3. Re-encrypt under the new KEK.
  4. Set the new WALLETRS_KEK and start.

Until rotation lands as a first-class flow, treat the KEK as a long-lived secret and store it in your secrets manager (AWS KMS, GCP KMS, HashiCorp Vault, 1Password Connect).

If you lose the KEK, system-managed private material is unrecoverable — wallets remain valid for receive-only use, but signing requires re-creating new system keys and migrating funds.

  • Logs. RUST_LOG=info,walletrs=debug is the default. Crank to walletrs=trace for verbose PSBT and BDK logs while debugging signing flows. Output is human-readable env_logger format — JSON logs are on the roadmap.
  • Metrics. No built-in metrics. Use a sidecar gRPC reflection scraper or front the service with an Envoy / Linkerd proxy if you need per-RPC latency histograms.
  • Liveness. Hit POST /wallet/ping (HTTP) or walletrpc.WalletService/Ping (gRPC). Both bypass auth.

walletrs follows BDK + miniscript + bitcoin crate versions. When Bitcoin Core ships a soft fork that changes descriptor semantics (rare), check the release notes of those upstream crates and update.

For walletrs version pinning:

  • Pin a specific tag (ghcr.io/n1rna/walletrs:0.1.0) in production, not :latest.
  • Subscribe to GitHub releases for new-tag notifications.
  • The proto/walletrpc.proto contract is additive in the spirit of semver — new RPCs / fields land without removing old ones inside a minor series.