Zero-Config Docker Deployment: Auto-Provisioning Your Self-Hosted Crypto Wallet
Docker makes running your own self-hosted crypto wallet infrastructure surprisingly approachable — no third-party custody, no rate limits, no one else holding your AI agent's private keys. If you've ever asked yourself whether you'd trust a hosted service with keys that control real funds on behalf of an autonomous agent, you already know the answer. This post walks through how WAIaaS handles the hardest part of self-hosting: that first-run setup that usually trips people up.
Would You Hand a Stranger Your Keys?
Here's the uncomfortable truth about most "Wallet-as-a-Service" offerings: when you use a hosted provider, someone else generates, stores, and ultimately controls the cryptographic keys that sign your transactions. For personal wallets, that's a familiar trade-off. For AI agents that transact autonomously — potentially 24/7, across DeFi protocols, with real funds — it's a much bigger bet.
The self-hosted alternative has traditionally meant accepting a painful setup process: generating keys manually, configuring secure storage, wiring up RPC endpoints, building your own policy layer. Most developers give up and go back to the hosted option. WAIaaS is designed to eliminate that gap. You get the sovereignty of self-hosting with a setup experience that doesn't require a weekend.
The Self-Hosting Philosophy
Running your own infrastructure is the crypto equivalent of hosting your own email server — except in 2026, Docker has made this actually practical rather than aspirational. When you self-host WAIaaS:
- Your private keys never leave your machine
- No third party can rate-limit, suspend, or inspect your agent's transactions
- You control the upgrade cycle — nothing changes unless you choose to update
- Your data (transaction history, policy configs, session tokens) stays on your hardware
This matters especially for AI agents. An autonomous trading agent or a workflow bot that handles payments needs a wallet backend it can rely on without external dependencies introducing latency, outages, or policy changes outside your control.
WAIaaS is open-source and built as a 15-package monorepo. The Docker image — ghcr.io/minhoyoo-iotrust/waiaas:latest — packages the daemon that handles everything: key management, policy enforcement, DeFi protocol integrations, MCP tools for AI frameworks, and the REST API your agents call.
The Auto-Provision Feature: Zero First-Run Friction
The single biggest barrier to self-hosting any secrets-management service is the bootstrap problem: you need a master password before you can do anything, but generating and storing that password securely is exactly the kind of thing people get wrong.
WAIaaS solves this with WAIAAS_AUTO_PROVISION. When this environment variable is set to true, the daemon generates a cryptographically random master password on first start, writes it to /data/recovery.key, and continues without waiting for human input. You retrieve the password after startup and store it somewhere safe.
Here's the single-container version:
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 auto-generated master password
docker exec waiaas cat /data/recovery.key
Notice the port binding: 127.0.0.1:3100:3100. This is intentional — the daemon listens only on localhost by default, so it's not exposed to the network until you explicitly decide otherwise. That's the right default for a service that controls signing keys.
Docker Compose: The Practical Setup
For anything beyond a quick test, Docker Compose is the right approach. WAIaaS ships a docker-compose.yml you can use directly:
services:
daemon:
image: ghcr.io/minhoyoo-iotrust/waiaas:latest
container_name: waiaas-daemon
ports:
- "127.0.0.1:3100:3100"
volumes:
- waiaas-data:/data
environment:
- WAIAAS_DATA_DIR=/data
- WAIAAS_DAEMON_HOSTNAME=0.0.0.0
env_file:
- path: .env
required: false
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3100/health"]
interval: 30s
timeout: 5s
start_period: 10s
retries: 3
volumes:
waiaas-data:
driver: local
A few things worth noting here:
Named volume for data persistence. waiaas-data is a Docker-managed named volume. This means docker compose down preserves your wallets and transaction history. You'd need docker compose down -v to actually delete data — a deliberate extra step that prevents accidental key loss.
Built-in healthcheck. The compose file includes a healthcheck that polls /health every 30 seconds. This integrates naturally with Docker's restart policies and with monitoring tools in a homelab setup.
The daemon runs as UID 1001 (non-root). This is a security default baked into the Docker image — the process doesn't have root privileges inside the container.
Getting started with Compose is three commands:
git clone https://github.com/minhoyoo-iotrust/WAIaaS.git
cd WAIaaS
docker compose up -d
Production Secrets: Docker Secrets Overlay
For a homelab or production deployment where you want proper secrets management, WAIaaS supports Docker Secrets via a docker-compose.secrets.yml overlay. This keeps your master password out of environment variables entirely:
# 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 secrets overlay pattern means your actual credentials never appear in docker inspect output, shell history, or .env files that might accidentally get committed to version control. For anyone running a homelab where the threat model includes shared machines or accidentally public repositories, this is worth the extra step.
Key Environment Variables
The daemon is configured entirely through environment variables — no config files to manually edit before first boot. The most important ones:
WAIAAS_AUTO_PROVISION=true # Auto-generate master password on first start
WAIAAS_DAEMON_PORT=3100 # Listening port
WAIAAS_DAEMON_HOSTNAME=0.0.0.0 # Bind address
WAIAAS_DAEMON_LOG_LEVEL=info # Log level (trace/debug/info/warn/error)
WAIAAS_DATA_DIR=/data # Data directory
WAIAAS_RPC_SOLANA_MAINNET=<url> # Solana mainnet RPC endpoint
WAIAAS_RPC_EVM_ETHEREUM_MAINNET=<url> # Ethereum mainnet RPC endpoint
The RPC endpoint variables are where you plug in your own node URLs — Alchemy, QuickNode, your own Geth instance, whatever fits your setup. This is another sovereignty point: you're not locked into any particular RPC provider.
From Container to Working Wallet: The Quick Path
Once the container is running, you need to create a wallet and give your AI agent a session token. This is where the three-layer auth model comes in. There's a master password (for admin operations like creating wallets and setting policies), owner auth (for approving high-stakes transactions via WalletConnect or similar), and session tokens (what your AI agent actually uses for day-to-day operations).
Create a wallet with the master password:
curl -X POST http://127.0.0.1:3100/v1/wallets \
-H "Content-Type: application/json" \
-H "X-Master-Password: my-secret-password" \
-d '{"name": "trading-wallet", "chain": "solana", "environment": "mainnet"}'
Create a session token for your agent:
curl -X POST http://127.0.0.1:3100/v1/sessions \
-H "Content-Type: application/json" \
-H "X-Master-Password: my-secret-password" \
-d '{"walletId": "<wallet-uuid>"}'
Now your agent can check its balance using just the session token — the master password never touches agent code:
curl http://127.0.0.1:3100/v1/wallet/balance \
-H "Authorization: Bearer wai_sess_eyJhbGciOiJIUzI1NiJ9..."
This separation matters. The session token is scoped to one wallet, subject to whatever policies you've set, and can be revoked without touching the underlying key material.
Policies: The Safety Layer You Set Once
Self-hosting means you're also responsible for setting the guardrails. WAIaaS has a policy engine with 21 policy types and a default-deny stance: if ALLOWED_TOKENS or CONTRACT_WHITELIST aren't configured, transactions are blocked by default.
A basic spending limit policy looks like this:
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
}
}'
This creates four tiers of behavior: under $100 executes immediately, $100-$500 executes and notifies you, $500-$2000 waits 15 minutes before executing (giving you a cancellation window), and anything over $2000 requires your explicit approval. You set this once and the daemon enforces it on every transaction your agent submits — no matter what the agent asks for.
The 4 security tiers — INSTANT, NOTIFY, DELAY, and APPROVAL — map to real threat scenarios. An agent that accidentally goes rogue, a bug that causes runaway transactions, or a prompt injection attack that tries to drain a wallet all get caught at different tiers depending on the amount involved.
CLI Alternative: Even Faster Setup
If you prefer the CLI over raw curl commands, the @waiaas/cli package wraps all of this into a few commands:
npm install -g @waiaas/cli
waiaas init --auto-provision # Generates random master password → recovery.key
waiaas start # No password prompt
waiaas quickset # Creates wallets + sessions automatically
waiaas set-master # (Later) Harden password, then delete recovery.key
The CLI has 20 commands covering everything from backup and restore to MCP setup and notification configuration. For anyone who finds curl-based setup tedious, this is the faster path.
Common Operations
docker compose up -d # Start daemon
docker compose logs -f # Follow logs
docker compose down # Stop (data preserved in named volume)
docker compose down -v # Stop + delete data volume
The interactive API reference is available at http://127.0.0.1:3100/reference once the daemon is running — useful for exploring the 39 REST API route modules without leaving the browser.
Why Self-Hosting Is Actually Practical Now
Three things have changed that make self-hosting crypto wallet infrastructure reasonable in 2026:
Docker has solved the environment problem. The same image runs the same way on a Raspberry Pi 5, a homelab server, or a cloud VPS. You're not debugging library versions or system dependencies.
Auto-provisioning has solved the bootstrap problem. The hardest part of setting up any secrets management service used to be the first run. WAIAAS_AUTO_PROVISION=true eliminates that entirely.
The policy layer handles the "what if the agent goes wrong" problem. The default-deny stance and the 4-tier spending limit system mean you can hand an agent a session token without losing sleep about what it might do with it.
The result is a setup that genuinely takes one afternoon, produces a running system you fully control, and doesn't require ongoing maintenance beyond occasional updates (which Docker handles automatically if you configure Watchtower).
Quick Start Summary
- Clone the repo and run
docker compose up -d - Add
WAIAAS_AUTO_PROVISION=trueto your environment or.envfile - Retrieve the generated master password from
/data/recovery.key - Create a wallet and session token via the REST API or CLI
- Set a spending limit policy before handing the session token to your agent
That's the full path from zero to a running, policy-enforced, self-hosted wallet backend.
What's Next
The REST API documentation is auto-generated and available at /reference on your running instance — it's the fastest way to explore what's available across all 39 route modules. If you're planning to connect an AI agent via Claude Desktop or another MCP-compatible framework, the 45 MCP tools in @waiaas/mcp are the next thing to look at. And if you want to go deeper on keeping your agent's spending within safe boundaries, the full policy engine — all 21 policy types — is worth reading through before you go to production.
The project is on GitHub at https://github.com/minhoyoo-iotrust/WAIaaS and the official site is at https://waiaas.ai. Both are good starting points depending on whether you want to read code or documentation first.
Top comments (0)