Deployment Guide

Deployment Guide

This guide covers two deployment methods for WAIaaS: npm global install (recommended for development and single-host setups) and Docker Compose (recommended for production).

Prerequisites

Requirement npm Install Docker
Node.js 22 LTS Required -
Docker Engine 24+ - Required
Docker Compose v2 - Required
2 GB RAM minimum Required Required

Option A: npm Global Install

1. Install the CLI

npm install -g @waiaas/cli

2. Initialize

Auto-provision (recommended for AI agents -- no human interaction):

waiaas init --auto-provision

This creates the data directory at ~/.waiaas/ with:

Manual (human-guided password setup):

waiaas init

You will be prompted to set a master password. This password protects all wallet private keys via Argon2id key derivation. Store it securely -- it cannot be recovered.

3. Start the Daemon

waiaas start

The daemon starts at http://127.0.0.1:3100 by default. If initialized manually, you will be prompted for the master password. If auto-provisioned, no prompt is needed.

4. Verify

waiaas status

Or:

curl http://127.0.0.1:3100/health

Expected response:

{
  "status": "ok",
  "version": "1.8.0",
  "schemaVersion": 16,
  "uptime": 42,
  "timestamp": 1771300000
}

5. Stop

waiaas stop

6. Update

# Recommended: built-in update command (7-step process with backup)
waiaas update

# Alternative: manual npm update
npm install -g @waiaas/cli@latest

The waiaas update command checks for new versions, creates a backup, downloads the update, runs database migrations, and restarts the daemon.

Data Directory Structure

~/.waiaas/
  config.toml          # Configuration file
  data/
    waiaas.db          # SQLite database
    waiaas.db-wal      # WAL journal
  keystore/
    *.enc              # Encrypted private keys
  tokens/              # MCP session token files
  backups/             # Automatic backup archives

Option B: Docker Compose

1. Create Project Directory

mkdir waiaas && cd waiaas

2. Create docker-compose.yml

services:
  daemon:
    image: ghcr.io/minho-yoo/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

3. Configure Environment

Create a .env file with your settings:

With auto-provision (no password hash needed):

# Auto-provision: generates master password on first start
WAIAAS_AUTO_PROVISION=true

# Optional: RPC endpoints (or configure later via Admin Settings)
WAIAAS_RPC_SOLANA_MAINNET=https://api.mainnet-beta.solana.com
WAIAAS_RPC_SOLANA_DEVNET=https://api.devnet.solana.com
# WAIAAS_RPC_EVM_ETHEREUM_MAINNET=https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY

# Optional: Daemon settings
WAIAAS_DAEMON_PORT=3100
WAIAAS_DAEMON_LOG_LEVEL=info

With pre-set password hash:

# Required: Master password hash (Argon2id)
# Generate with: npx @waiaas/cli hash-password
WAIAAS_SECURITY_MASTER_PASSWORD_HASH=$argon2id$v=19$m=65536,t=3,p=4$...

# Optional: RPC endpoints (or configure later via Admin Settings)
WAIAAS_RPC_SOLANA_MAINNET=https://api.mainnet-beta.solana.com
WAIAAS_RPC_SOLANA_DEVNET=https://api.devnet.solana.com
# WAIAAS_RPC_EVM_ETHEREUM_MAINNET=https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY

# Optional: Daemon settings
WAIAAS_DAEMON_PORT=3100
WAIAAS_DAEMON_LOG_LEVEL=info

# Optional: Notifications (or configure later via Admin Settings)
WAIAAS_NOTIFICATIONS_ENABLED=true
WAIAAS_NOTIFICATIONS_TELEGRAM_BOT_TOKEN=123456:ABC-DEF...
WAIAAS_NOTIFICATIONS_TELEGRAM_CHAT_ID=987654321

4. Using Docker Secrets (Recommended for Production)

For sensitive values, use Docker secrets instead of environment variables. Create secret files:

mkdir -p secrets
echo "your_master_password" > secrets/master_password.txt
chmod 600 secrets/master_password.txt

# Optional: Telegram bot token
echo "your_bot_token" > secrets/telegram_bot_token.txt
chmod 600 secrets/telegram_bot_token.txt

Create docker-compose.secrets.yml:

services:
  daemon:
    secrets:
      - waiaas_master_password
      - waiaas_telegram_bot_token
    environment:
      - WAIAAS_MASTER_PASSWORD_FILE=/run/secrets/waiaas_master_password
      - WAIAAS_TELEGRAM_BOT_TOKEN_FILE=/run/secrets/waiaas_telegram_bot_token

secrets:
  waiaas_master_password:
    file: ./secrets/master_password.txt
  waiaas_telegram_bot_token:
    file: ./secrets/telegram_bot_token.txt

Start with secrets:

docker compose -f docker-compose.yml -f docker-compose.secrets.yml up -d

5. Start

docker compose up -d

6. View Logs

docker compose logs -f waiaas

7. Update

docker compose pull
docker compose up -d

Database migrations run automatically on startup. The Docker image supports Watchtower auto-update via the com.centurylinklabs.watchtower.enable=true label.

Docker Auto-Provision

For fully autonomous Docker deployments (no pre-set password), add WAIAAS_AUTO_PROVISION=true to your environment:

services:
  daemon:
    image: ghcr.io/minho-yoo/waiaas:latest
    environment:
      - WAIAAS_AUTO_PROVISION=true
      - WAIAAS_DATA_DIR=/data
      - WAIAAS_DAEMON_HOSTNAME=0.0.0.0
    volumes:
      - waiaas-data:/data
    ports:
      - "127.0.0.1:3100:3100"

On first start (when /data/config.toml does not exist), the entrypoint automatically runs waiaas init --auto-provision. The generated master password is saved to /data/recovery.key.

Retrieve the recovery key after first start:

docker compose exec daemon cat /data/recovery.key

After retrieving, harden the password with waiaas set-master and delete the recovery key.

Docker Image Details


Configuration

config.toml

The configuration file is located at ~/.waiaas/config.toml (npm install) or mounted into the container at /data/config.toml (Docker). All sections are flat (no nesting allowed).

[daemon]
port = 3100                     # Listening port
hostname = "127.0.0.1"          # Bind address (keep localhost for security)
log_level = "info"              # trace | debug | info | warn | error
admin_ui = true                 # Enable Admin Web UI
admin_timeout = 900             # Admin session timeout (seconds)

[rpc]
solana_mainnet = "https://api.mainnet-beta.solana.com"
solana_devnet = "https://api.devnet.solana.com"
# ethereum_mainnet = "https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY"
# ethereum_sepolia = "https://eth-sepolia.g.alchemy.com/v2/YOUR_KEY"

[security]
session_ttl = 86400                     # Session lifetime (seconds, default 24h)
max_sessions_per_wallet = 5             # Max sessions per wallet
policy_defaults_delay_seconds = 300     # DELAY tier wait time (seconds)
policy_defaults_approval_timeout = 3600 # APPROVAL tier timeout (seconds)

[keystore]
argon2_memory = 65536           # Argon2id memory (KB)
argon2_time = 3                 # Argon2id iterations
argon2_parallelism = 4          # Argon2id parallelism

[database]
path = "data/waiaas.db"         # SQLite file path (relative to data dir)

[walletconnect]
project_id = ""                 # Reown Cloud project ID (optional)

[notifications]
enabled = false
telegram_bot_token = ""
telegram_chat_id = ""
discord_webhook_url = ""
ntfy_topic = ""
ntfy_server = "https://ntfy.sh"

Environment Variable Override

Any config value can be overridden with environment variables using the pattern WAIAAS_{SECTION}_{KEY}:

WAIAAS_DAEMON_PORT=4000
WAIAAS_DAEMON_LOG_LEVEL=debug
WAIAAS_RPC_SOLANA_MAINNET="https://my-rpc.example.com"
WAIAAS_SECURITY_SESSION_TTL=43200

Admin Settings (Preferred for Runtime Configuration)

Prefer Admin Settings over config.toml. Most settings can be changed at runtime through the Admin Settings API, Admin UI, or CLI commands without restarting the daemon:

# View all current settings
curl http://127.0.0.1:3100/v1/admin/settings \
  -H "X-Master-Password: <password>"

# Update settings (hot-reload, no restart needed)
curl -X PUT http://127.0.0.1:3100/v1/admin/settings \
  -H "X-Master-Password: <password>" \
  -H "Content-Type: application/json" \
  -d '{"settings":[{"key": "display.currency", "value": "KRW"}]}'

Admin Settings covers: notifications, RPC endpoints, security parameters, display currency, monitoring, autostop, signing SDK, WalletConnect, oracle, and daemon log level.

Only infrastructure settings (port, hostname, database path, master_password_hash) require a daemon restart and remain config.toml-only. For everything else, use Admin Settings, CLI commands, or the Admin UI.


Post-Installation

1. Harden Master Password (Auto-Provision Only)

If you used --auto-provision or WAIAAS_AUTO_PROVISION=true, change the auto-generated password to a strong human-chosen password:

waiaas set-master

Or via REST API:

curl -s -X PUT http://127.0.0.1:3100/v1/admin/master-password \
  -H "Content-Type: application/json" \
  -H "X-Master-Password: $(cat ~/.waiaas/recovery.key)" \
  -d '{"newPassword": "<your-strong-password>"}'

After changing, delete the recovery key:

rm ~/.waiaas/recovery.key

2. Access Admin UI

Open your browser and navigate to:

http://127.0.0.1:3100/admin

Log in with your master password to access the dashboard, wallet management, session management, policy configuration, and notification settings.

3. Create Your First Wallet

curl -X POST http://127.0.0.1:3100/v1/wallets \
  -H "Content-Type: application/json" \
  -H "X-Master-Password: <your-master-password>" \
  -d '{
    "name": "my-wallet",
    "chain": "solana",
    "environment": "mainnet"
  }'

Response:

{
  "id": "01234567-89ab-cdef-0123-456789abcdef",
  "name": "my-wallet",
  "chain": "solana",
  "network": "mainnet",
  "environment": "mainnet",
  "publicKey": "ABC123...",
  "status": "ACTIVE",
  "ownerState": "NONE"
}

4. Create a Session Token

curl -X POST http://127.0.0.1:3100/v1/sessions \
  -H "Content-Type: application/json" \
  -H "X-Master-Password: <your-master-password>" \
  -d '{"walletId": "<wallet-id-from-above>"}'

The response includes a token field (wai_sess_...) that AI agents use to authenticate.

5. Set Up MCP (for AI Agents)

# Automatic: registers MCP server with Claude Desktop
waiaas mcp setup

# For a specific wallet
waiaas mcp setup --wallet <wallet-id>

# For all wallets
waiaas mcp setup --all

This automatically creates session tokens and configures Claude Desktop's MCP server settings.

6. Install Skill Files (Optional)

Skill files teach AI agents how to interact with the WAIaaS API. They are plain Markdown files that can be included in the AI agent's context.

# List available skills
npx @waiaas/skills list

# Add a specific skill to your project
npx @waiaas/skills add wallet

# Add all skills
npx @waiaas/skills add all

This copies .skill.md files to your current directory. Include them in your AI agent's prompt or context window for API-aware conversations.


Notifications Setup

WAIaaS supports four notification channels: Telegram, Discord, ntfy, and Slack. Notifications fire on 8 event types including transaction execution, approval requests, and kill switch activation.

Channel Config Key Setup
Telegram telegram_bot_token + telegram_chat_id Create bot via @BotFather
Discord discord_webhook_url Server Settings > Integrations > Webhooks
ntfy ntfy_topic + ntfy_server Choose topic, subscribe via app
Slack slack_webhook_url Create incoming webhook

Via Admin Settings (Recommended)

Use the Admin Settings API for runtime configuration without editing config.toml:

# Configure Telegram notifications via Admin Settings
curl -s -X PUT http://127.0.0.1:3100/v1/admin/settings \
  -H "Content-Type: application/json" \
  -H "X-Master-Password: <password>" \
  -d '{"settings":[
    {"key":"notifications.telegram_bot_token","value":"<bot-token>"},
    {"key":"notifications.telegram_chat_id","value":"<chat-id>"},
    {"key":"notifications.enabled","value":"true"}
  ]}'

Or use the CLI:

waiaas notification setup --bot-token <TOKEN> --chat-id <ID> --test

Via Admin UI

Open http://127.0.0.1:3100/admin, navigate to Notifications, and configure channels through the visual interface.

Test Notifications

curl -X POST http://127.0.0.1:3100/v1/admin/notifications/test \
  -H "X-Master-Password: <your-master-password>" \
  -H "Content-Type: application/json" \
  -d '{"channel": "telegram"}'

Security Checklist

Before running in production, verify these security settings:


Troubleshooting

Port Already in Use

Error: listen EADDRINUSE :::3100

Another process is using port 3100. Either stop it or change the port:

WAIAAS_DAEMON_PORT=3200 waiaas start

Permission Denied (Keystore)

Error: EACCES: permission denied, open '~/.waiaas/keystore/...'

Fix file ownership:

sudo chown -R $(whoami) ~/.waiaas/
chmod -R 700 ~/.waiaas/keystore/

Database Migration

Database migrations run automatically on daemon startup. If you see migration errors:

  1. Check the daemon logs for the specific migration version that failed.
  2. Ensure you are running the latest version of WAIaaS.
  3. Restore from backup if necessary: waiaas restore --backup <path>.

The daemon tracks schema versions in the schema_version table. Current schema version: 16.

Docker: Container Exits Immediately

Check logs for the error:

docker compose logs waiaas

Common causes:

Admin UI Not Loading

RPC Connection Errors

Error: Failed to connect to Solana RPC

Related