Complete Self-Hosting Guide: 20 CLI Commands + Docker for AI Agent Wallets
Complete Self-Hosting Guide: 20 CLI Commands + Docker for AI Agent Wallets
Self-hosting your AI agent's wallet infrastructure means your private keys never leave your server — and with WAIaaS, you can have the whole stack running in a single Docker command. If you've ever asked yourself whether you'd trust a third-party service with the keys that control your autonomous agent's funds, this guide is for you. We'll walk through every CLI command, the Docker setup, and the policy engine that keeps your agent from going rogue.
Why Self-Custody for AI Agents Actually Matters
There's a meaningful difference between self-hosting a blog and self-hosting financial infrastructure. When an AI agent can autonomously send transactions, the question of who controls the keys becomes genuinely important — not just philosophically, but operationally.
With a hosted wallet service, you're trusting a third party to hold private keys on behalf of your agent, enforce your spending rules, and keep your transaction history private. Every request you make passes through their infrastructure, subject to their rate limits, their uptime SLAs, and their terms of service. Self-hosting flips this entirely: your keys are generated and stored on your own hardware, your policies run in your own process, and the only rate limits you face are the ones your server can handle. It's the crypto equivalent of running your own email server — except in 2026, WAIaaS makes it genuinely practical rather than a masochistic weekend project.
What You're Actually Installing
WAIaaS is a 15-package monorepo organized as a Wallet-as-a-Service designed specifically for AI agents. The core daemon exposes 39 REST API route modules, provides 45 MCP tools for AI agent integration, supports 18 networks across both Solana and EVM chains, and integrates 15 DeFi protocol providers. It ships as two Docker images: the main WAIaaS daemon and a push-relay service for mobile notifications.
The architecture is built around three distinct principals:
- Master password — system administrator, creates wallets and sessions
- Session tokens — what your AI agent actually uses to transact
- Owner auth — you, the human, approving high-value transactions via WalletConnect or Telegram
This separation means your AI agent has just enough access to do its job, and nothing more.
Installation: One Command or the Full CLI Path
The Docker Fast Lane
If you want to be running in under two minutes:
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
The WAIAAS_AUTO_PROVISION=true flag tells the entrypoint to generate a master password on first start and write it to /data/recovery.key. Notice the port binding: 127.0.0.1:3100:3100 — by default, the daemon only listens on localhost. This is a deliberate choice. You don't want an AI wallet daemon accidentally exposed to the public internet.
For a more production-ready setup, the included Docker Compose file handles health checks, restart policies, and environment configuration:
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
Start it with:
git clone https://github.com/waiaas/WAIaaS.git
cd WAIaaS
docker compose up -d
For production deployments where you want to keep secrets out of environment variables entirely, there's a secrets overlay:
mkdir -p secrets
echo "your-secure-password" > secrets/master_password.txt
chmod 600 secrets/master_password.txt
docker compose -f docker-compose.yml -f docker-compose.secrets.yml up -d
The docker-compose.secrets.yml overlay uses Docker Secrets to inject credentials into the container without exposing them in docker inspect output or shell history. This is the pattern you want for anything running in a homelab that faces even semi-public networks.
The CLI Path (All 20 Commands)
If you prefer installing locally or want more granular control, the CLI gives you everything:
npm install -g @waiaas/cli
waiaas init # Create data directory + config.toml
waiaas start # Start daemon
waiaas quickset --mode mainnet # Create wallets + MCP sessions in one step
The full CLI ships with exactly 20 commands:
| Command | What it does |
|---|---|
init |
Create data directory and config.toml |
start |
Start the daemon process |
stop |
Stop the daemon |
status |
Check daemon health |
quickstart |
Opinionated first-run setup |
quickset |
Create wallets + sessions in one step |
set-master |
Harden master password after auto-provision |
wallet create |
Create a new wallet |
wallet info |
Display wallet details and address |
session prompt |
Open interactive session management |
owner connect |
Link owner wallet via WalletConnect |
owner disconnect |
Unlink owner wallet |
owner status |
Show owner connection status |
mcp setup |
Register wallets with Claude Desktop |
notification setup |
Configure push/Telegram notifications |
backup create |
Create encrypted backup |
backup inspect |
Read backup metadata without restoring |
backup list |
List available backups |
restore |
Restore from backup |
update |
Update WAIaaS to latest version |
The recommended self-hosted workflow uses auto-provision to avoid typing a password during setup, then hardens it afterward:
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: set a real password, then delete recovery.key
Creating Wallets and Sessions
Once the daemon is running, wallet creation goes through 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"}'
Then create a session token for your AI agent to use:
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>"}'
That session token (wai_sess_...) is what your agent gets. It can check balances, send transactions, and call DeFi actions — but it cannot create new wallets, modify policies, or access the master password. Sessions support per-token TTL, maxRenewals, and absoluteLifetime configuration, so you can scope exactly how long an agent credential stays valid.
The Policy Engine: Where Self-Hosting Really Pays Off
This is where running your own WAIaaS instance genuinely shines. The policy engine has 21 policy types, 4 security tiers, and enforces default-deny: if ALLOWED_TOKENS or CONTRACT_WHITELIST aren't configured, transactions are blocked by default. You're not opting into restrictions — you're explicitly opting out of the safest state.
The four security tiers determine what happens when a transaction comes in:
- INSTANT — Execute immediately, no notification
- NOTIFY — Execute immediately, send you a notification
- DELAY — Queue for N seconds, giving you time to cancel
- APPROVAL — Hold until you explicitly approve via WalletConnect or Telegram
A spending limit policy that uses all four tiers 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
}
}'
Under this policy: transactions under $100 go straight through, $100–$500 trigger a notification to your phone, $500–$2,000 are queued for 15 minutes (cancellable), and anything above $2,000 requires your explicit approval. The transaction pipeline runs through 7 stages — validate, auth, policy, wait, execute, confirm — so the delay and approval mechanics are enforced at the infrastructure level, not in application code you wrote.
Beyond spending limits, you have policies like:
ALLOWED_TOKENS— whitelist which tokens the agent can touchCONTRACT_WHITELIST— whitelist which contracts it can callPERP_MAX_LEVERAGE— cap leverage for Hyperliquid perp tradingX402_ALLOWED_DOMAINS— control which APIs the agent can autonomously payREPUTATION_THRESHOLD— require minimum ERC-8004 onchain reputation score before transacting
The full list of 21 types covers everything from TIME_RESTRICTION (only allow transactions during business hours) to LENDING_LTV_LIMIT (max loan-to-value ratio for Aave positions).
Connecting Your AI Agent
Once you have a session token, connecting Claude or any MCP-compatible agent takes about 30 seconds:
waiaas mcp setup --all # Auto-register all wallets with Claude Desktop
Or configure manually in claude_desktop_config.json:
{
"mcpServers": {
"waiaas": {
"command": "npx",
"args": ["-y", "@waiaas/mcp"],
"env": {
"WAIAAS_BASE_URL": "http://127.0.0.1:3100",
"WAIAAS_SESSION_TOKEN": "wai_sess_<your-token>",
"WAIAAS_DATA_DIR": "~/.waiaas"
}
}
}
}
The MCP server exposes 45 tools covering wallet operations, transfers, DeFi actions, NFT management, and x402 HTTP payments. After setup, you can tell Claude to check your balance, swap SOL for USDC on Jupiter, or show your DeFi positions across all 15 integrated protocols — and every one of those transactions flows through the policy engine you configured on your own server.
For agents built with the TypeScript SDK instead of MCP:
import { WAIaaSClient } from '@waiaas/sdk';
const client = new WAIaaSClient({
baseUrl: 'http://127.0.0.1:3100',
sessionToken: process.env.WAIAAS_SESSION_TOKEN,
});
const balance = await client.getBalance();
console.log(`${balance.balance} ${balance.symbol}`);
const tx = await client.sendToken({
to: 'recipient-address...',
amount: '0.1',
});
A Python SDK (pip install waiaas) is also available with async/await support, using the same session token for auth.
Keeping Things Running
A few operational notes for self-hosters:
Backups: Use waiaas backup create before any major changes. The backup inspect command lets you read metadata from a backup file without actually restoring it — useful for verifying that your automated backup job is producing valid files.
Updates: waiaas update handles pulling the latest version. If you're running Docker Compose, you can also use Watchtower for automatic image updates — the daemon image supports this pattern.
RPC endpoints: By default you'll want to configure your own RPC endpoints rather than relying on public nodes:
WAIAAS_RPC_SOLANA_MAINNET=<your-rpc-url>
WAIAAS_RPC_EVM_ETHEREUM_MAINNET=<your-rpc-url>
Dry-run before you commit: The simulate endpoint lets you preview a transaction's outcome before actually executing it:
curl -X POST http://127.0.0.1:3100/v1/transactions/send \
-H "Content-Type: application/json" \
-H "Authorization: Bearer wai_sess_<token>" \
-d '{
"type": "TRANSFER",
"to": "recipient-address",
"amount": "0.1",
"dryRun": true
}'
API docs: Once the daemon is running, hit http://127.0.0.1:3100/reference for the interactive Scalar API reference UI, or download the full OpenAPI 3.0 spec at /doc. With 39 route modules, having searchable docs locally is genuinely useful.
The Self-Hosted Philosophy in Practice
There's a particular type of developer who runs their own Nextcloud instead of Dropbox, their own Gitea instead of a hosted alternative, their own Vaultwarden instead of a hosted password manager. The motivation isn't that hosted services are bad — it's that sovereignty over your own data and infrastructure is worth the operational overhead.
AI agent wallets fit this mindset naturally. The agent is acting on your behalf, with your funds, following your rules. Having that entire system run on hardware you control — with private keys that never leave your server, policies enforced by your own process, and transaction logs stored in your own database — is simply the consistent application of the same principle you already apply to the rest of your stack.
WAIaaS is built for exactly this use case: open-source, self-hostable, with a 683+ test file codebase and a Docker image that runs as a non-root user (UID 1001) by default.
What's Next
The best next step is getting the daemon running and creating your first wallet — the quickstart flow takes about five minutes from zero. From there, spend time with the policy engine before connecting any live funds: understanding the 21 policy types and how the 4 security tiers compose gives you real confidence in what your agent can and cannot do autonomously.
- GitHub: https://github.com/waiaas/WAIaaS
- Official site: https://waiaas.ai