DEV Community

Cover image for Complete Self-Hosting Guide: 20 CLI Commands + Docker for AI Agent Wallets
Wallet Guy
Wallet Guy

Posted on

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Start it with:

git clone https://github.com/waiaas/WAIaaS.git
cd WAIaaS
docker compose up -d
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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"}'
Enter fullscreen mode Exit fullscreen mode

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>"}'
Enter fullscreen mode Exit fullscreen mode

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
    }
  }'
Enter fullscreen mode Exit fullscreen mode

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 touch
  • CONTRACT_WHITELIST — whitelist which contracts it can call
  • PERP_MAX_LEVERAGE — cap leverage for Hyperliquid perp trading
  • X402_ALLOWED_DOMAINS — control which APIs the agent can autonomously pay
  • REPUTATION_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
Enter fullscreen mode Exit fullscreen mode

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"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

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',
});
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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
  }'
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)