Production-Grade Self-Hosted Crypto Wallets: Healthcheck, Recovery, and Monitoring

Production-Grade Self-Hosted Crypto Wallets: Healthcheck, Recovery, and Monitoring

Self-hosted crypto wallet infrastructure for AI agents sounds intimidating — but the alternative is handing your agent's private keys to a third party and hoping their uptime holds. If you've ever run your own Nextcloud, your own email server, or your own VPN, you already understand the tradeoff: a bit more setup in exchange for complete sovereignty over your data and your keys. This post walks through how WAIaaS — an open-source, self-hosted Wallet-as-a-Service — handles the parts of self-hosting that actually matter in production: health monitoring, backup and recovery, and keeping your daemon running reliably.

Why Self-Hosting Wallet Infrastructure Actually Makes Sense Now

The case for self-hosting a wallet backend is stronger than it looks at first glance. When an AI agent controls a wallet — executing DeFi trades, paying for API calls, bridging tokens across chains — you need to know exactly where the private keys live, who can access them, and what policies govern every transaction.

With a hosted service, you're accepting a bundle of assumptions: their uptime, their key custody model, their rate limits, their data retention policies. That might be fine for a hobby project. But if you're running an agent in production that's executing real transactions against 15 DeFi protocols across 18 networks, those assumptions start to matter. Self-hosting with WAIaaS means your keys never leave your server, your transaction history stays in your volume, and your spending policies are enforced by code you can read and audit — not by a black-box API somewhere in the cloud.

The honest cost? You own the ops. You're responsible for healthchecks, backups, and keeping the daemon alive. This post is about making that as straightforward as possible.

Getting the Daemon Running

The fastest path to a running WAIaaS instance is Docker Compose. Clone the repo, run one command:

git clone https://github.com/minhoyoo-iotrust/WAIaaS.git
cd WAIaaS
docker compose up -d

The official image is ghcr.io/minhoyoo-iotrust/waiaas:latest, binding by default to 127.0.0.1:3100 — localhost only, which is the right default for a self-hosted setup. You're not exposing a wallet API to the public internet on first boot.

If you prefer a single docker run with auto-provisioning — useful when you want WAIaaS to generate its own master password on first start — that looks like this:

docker run -d \
  --name waiaas \
  -p 127.0.0.1:3100:3100 \
  -v waiaas-data:/data \
  -e WAIAAS_AUTO_PROVISION=true \
  ghcr.io/minhoyoo-iotrust/waiaas:latest

# Retrieve the auto-generated master password
docker exec waiaas cat /data/recovery.key

Keep that recovery.key somewhere safe. It's the system administrator credential — used for wallet creation, session management, and policy configuration. Once you've hardened it with waiaas set-master, delete the recovery file.

The Healthcheck — Your First Line of Monitoring

The Docker Compose file ships with a healthcheck out of the box:

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost:3100/health"]
  interval: 30s
  timeout: 5s
  start_period: 10s
  retries: 3

This is straightforward: every 30 seconds, Docker pings the /health endpoint. If it fails three times in a row, the container is marked unhealthy. Pair this with a restart: unless-stopped policy (already in the default compose file) and Docker will restart an unhealthy container automatically.

For a homelab or a single-server setup, that's often enough. The daemon comes back up, your named volume preserves all wallet data, and your agent picks up where it left off once the new session token is in place.

If you're running something more serious — say, an agent managing DeFi positions that need to be monitored around the clock — you'll want to feed that healthcheck signal to an external monitoring system. The /health endpoint returns a standard HTTP 200 on success, which makes it compatible with any uptime monitoring tool that can hit an HTTP URL.

Incoming Transaction Monitoring

Healthchecks tell you whether your daemon is alive. But for a wallet backend, you also need to know what's happening inside the wallet — specifically, whether funds are arriving as expected.

WAIaaS includes real-time incoming transaction monitoring with notifications for deposits (FEAT-INCOMING). From the agent's perspective, this means you can set up notification channels so that when your wallet receives tokens, something happens — a Telegram message, a push notification, or a custom webhook. The 7-stage transaction pipeline (stage1-validate → stage2-auth → stage3-policy → stage4-wait → stage5-execute → stage6-confirm) handles both outgoing and the event flow for incoming transactions.

There are 3 signing channels available: push-relay, Telegram, and wallet notification channel. These aren't just for transaction approvals — they're your real-time signal path for anything that touches your wallet.

To configure notifications via the CLI:

waiaas notification setup

This is one of the 20 CLI commands available in WAIaaS. For self-hosters, the CLI is often the most comfortable interface — it's where you do initial setup, manage backups, and check status without needing to remember curl syntax.

Backup and Recovery — Don't Skip This

This is the part most self-hosters defer until something breaks. Don't.

WAIaaS has dedicated CLI commands for backup management:

waiaas backup create      # Create a backup
waiaas backup list        # List available backups
waiaas backup inspect     # Inspect a backup file
waiaas restore            # Restore from backup

Your wallet data lives in a named Docker volume (waiaas-data). The backup commands let you snapshot that state and inspect it before restoring — which matters when you need to verify a backup is actually valid before trusting it.

A practical backup strategy for a self-hosted setup:

  1. Run waiaas backup create on a cron schedule (daily minimum for active wallets)
  2. Copy backup files off the host — to an S3-compatible store, a NAS, wherever your cold storage is
  3. Periodically run waiaas backup inspect on a recent backup to verify it's not corrupt
  4. Test waiaas restore in a staging environment at least once, before you need it in production

The worst time to discover your backups don't work is when you're already in recovery mode.

Secrets Management in Production

For a personal homelab, storing the master password in an environment variable is fine. For anything running real money, use the Docker Secrets overlay.

WAIaaS supports Docker Secrets via the docker-compose.secrets.yml overlay file. Setup looks like this:

# Create secret files
mkdir -p secrets
echo "your-secure-password" > secrets/master_password.txt
chmod 600 secrets/master_password.txt

# Deploy with secrets overlay
docker compose -f docker-compose.yml -f docker-compose.secrets.yml up -d

The entrypoint script (docker/entrypoint.sh) handles reading from Docker Secrets automatically. Your master password never appears in docker inspect output, environment variable dumps, or compose logs.

The daemon also runs as a non-root user (UID 1001), which is the right default for a service that's handling signing operations.

Policy Engine as a Safety Net

Self-hosting gives you control, but control without constraints is how agents accidentally drain wallets. The policy engine is what makes WAIaaS safe to leave running autonomously.

There are 21 policy types, organized around 4 security tiers:

The policy system is default-deny: if you haven't configured ALLOWED_TOKENS or CONTRACT_WHITELIST, transactions are blocked. This is the right default for a self-hosted setup where you want to know exactly what your agent is allowed to do.

A basic spending limit policy:

curl -X POST http://127.0.0.1:3100/v1/policies \
  -H "Content-Type: application/json" \
  -H "X-Master-Password: my-secret-password" \
  -d '{
    "walletId": "<wallet-uuid>",
    "type": "SPENDING_LIMIT",
    "rules": {
      "instant_max_usd": 100,
      "notify_max_usd": 500,
      "delay_max_usd": 2000,
      "delay_seconds": 900,
      "daily_limit_usd": 5000
    }
  }'

With this policy: transactions under $100 go through immediately, transactions between $100-$500 execute but send you a notification, transactions between $500-$2000 wait 15 minutes before executing (giving you a cancellation window), and anything over $2000 requires your explicit approval. All of this is enforced server-side — the agent can't bypass it.

For DeFi-specific guardrails, there are policy types like PERP_MAX_LEVERAGE, LENDING_LTV_LIMIT, and PERP_MAX_POSITION_USD that let you put hard limits on what your agent can do in perpetual futures or lending protocols.

Auto-Update with Watchtower

One of the maintenance costs of self-hosting is keeping software updated. The WAIaaS Docker setup supports Watchtower for automatic image updates. When a new ghcr.io/minhoyoo-iotrust/waiaas:latest is published, Watchtower pulls it and restarts the container with zero intervention.

Whether you want fully automatic updates or just automatic notifications of available updates is a personal preference — the privacy-conscious self-hoster in r/homelab will have opinions either way. The point is that the infrastructure supports it.

Quick Start Summary

Here's the minimal path to a production-grade self-hosted wallet backend:

Step 1: Start the daemon

git clone https://github.com/minhoyoo-iotrust/WAIaaS.git
cd WAIaaS
docker compose up -d

Step 2: Initialize with auto-provision

npm install -g @waiaas/cli
waiaas init --auto-provision
waiaas start

Step 3: Create wallets and sessions

waiaas quickset --mode mainnet

Step 4: Set up notifications and backup

waiaas notification setup
waiaas backup create

Step 5: Harden secrets

waiaas set-master
# Then delete recovery.key

At this point you have: a running daemon with healthcheck, incoming transaction monitoring, a backup you can restore from, and notification channels for approval workflows. That's production-grade self-hosted wallet infrastructure.

Checking Status

The CLI gives you waiaas status and waiaas owner status for quick operational checks. For the API:

# Check the daemon is alive
curl http://127.0.0.1:3100/health

# Check your wallet balance
curl http://127.0.0.1:3100/v1/wallet/balance \
  -H "Authorization: Bearer wai_sess_eyJhbGciOiJIUzI1NiJ9..."

The interactive API reference lives at http://127.0.0.1:3100/reference once your daemon is running — OpenAPI 3.0 spec auto-generated from 39 REST API route modules, with a Scalar UI for exploring endpoints without writing curl commands.

Your Keys, Your Server, Your Rules

The philosophy here is simple: if your AI agent is managing real funds, you should know exactly where the keys are, who has access to them, and what rules govern every transaction. Self-hosting is how you get that certainty.

WAIaaS gives you the operational primitives — healthchecks, backup/restore, notification channels, secrets management, policy enforcement — to run wallet infrastructure that you actually trust, because you built and operate it yourself. The 683+ test files in the codebase and the 15-package monorepo structure mean you can read, audit, and understand what you're running.

The crypto equivalent of running your own email server used to mean weeks of pain. With Docker Compose and a single docker compose up -d, it's an afternoon project.


Get started: The full source is at https://github.com/minhoyoo-iotrust/WAIaaS — stars and issues welcome. Documentation and the official site are at https://waiaas.ai.