The Problem with Plaintext Keys

When setting up OpenClaw, you’re dealing with sensitive credentials:

  • Discord Bot Tokens
  • AI API Keys (Kimi, OpenAI, etc.)
  • Service credentials

The temptation: Just paste them into openclaw.json

The risk: One accidental git commit, and your keys are public.


The Solution: Environment Variables

OpenClaw supports referencing environment variables in configuration. Your config file only contains placeholders, actual values live in environment variables.

How It Works

{
  "channels": {
    "discord": {
      "token": "${env:DISCORD_BOT_TOKEN}"
    }
  }
}

The ${env:VAR_NAME} syntax tells OpenClaw to read from environment variables at runtime.


Supported Environment Variables

Based on OpenClaw source code, these are officially supported:

ServiceVariable NameConfig Path
DiscordDISCORD_BOT_TOKENchannels.discord.token
Kimi AIKIMI_API_KEYAuth profiles
MoonshotMOONSHOT_API_KEYAuth profiles
OpenAIOPENAI_API_KEYModel providers
AnthropicANTHROPIC_API_KEYModel providers
GatewayOPENCLAW_GATEWAY_TOKENgateway.auth.token

Full list from source:

OPENAI_API_KEY, ANTHROPIC_API_KEY, ANTHROPIC_OAUTH_TOKEN,
GEMINI_API_KEY, ZAI_API_KEY, OPENROUTER_API_KEY,
AI_GATEWAY_API_KEY, MINIMAX_API_KEY, SYNTHETIC_API_KEY,
KILOCODE_API_KEY, ELEVENLABS_API_KEY, TELEGRAM_BOT_TOKEN,
DISCORD_BOT_TOKEN, SLACK_BOT_TOKEN, SLACK_APP_TOKEN,
OPENCLAW_GATEWAY_TOKEN, OPENCLAW_GATEWAY_PASSWORD,
KIMI_API_KEY, MOONSHOT_API_KEY

Setup Methods

Method 1: Shell Environment

export DISCORD_BOT_TOKEN="your-token-here"
export KIMI_API_KEY="your-key-here"
openclaw gateway restart

Pros: Quick, good for testing
Cons: Lost on shell exit, not persistent

Create ~/.openclaw/.env:

DISCORD_BOT_TOKEN=your-token-here
KIMI_API_KEY=your-key-here

OpenClaw automatically loads this on startup.

Pros: Persistent, organized, no shell pollution
Cons: File permissions matter

Secure the file:

chmod 600 ~/.openclaw/.env

Method 3: Systemd Service

For systemd-managed gateway, edit the service file:

[Service]
EnvironmentFile=/home/warwick/.openclaw/.env

Then reload:

systemctl --user daemon-reload
systemctl --user restart openclaw-gateway

Complete Configuration Example

1. Create Environment File

~/.openclaw/.env:

# Discord
DISCORD_BOT_TOKEN=MTQ2Njc4MDY2NzgwNjIyMDM2NA.GvboSs.xxxxxxxxxxxxxxxxxxxxx

# AI Services
KIMI_API_KEY=sk-kimi-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# Gateway Auth
OPENCLAW_GATEWAY_TOKEN=$(openssl rand -hex 32)

2. Update openclaw.json

{
  "channels": {
    "discord": {
      "enabled": true,
      "token": "${env:DISCORD_BOT_TOKEN}"
    }
  },
  "gateway": {
    "auth": {
      "mode": "token",
      "token": "${env:OPENCLAW_GATEWAY_TOKEN}"
    }
  }
}

3. Restart Gateway

openclaw gateway restart

Security Best Practices

1. Never Commit .env Files

Add to .gitignore:

.env
.env.local
*.env
openclaw.json.bak

2. Use Different Tokens for Different Environments

# Production
DISCORD_BOT_TOKEN_PROD=xxx

# Development  
DISCORD_BOT_TOKEN_DEV=yyy

3. Rotate Keys Regularly

Set a calendar reminder every 90 days to regenerate tokens.

4. Audit Your Config

openclaw secrets audit

This shows which keys are still in plaintext.

5. Backup Strategy

# Backup config (without secrets)
cp ~/.openclaw/openclaw.json ~/backup/

# Backup .env separately (encrypt it)
gpg -c ~/.openclaw/.env

Migration Guide

From Plaintext to Environment Variables

Step 1: Extract current keys

grep -E '"token"|"key"|"password"' ~/.openclaw/openclaw.json

Step 2: Create .env file

cat > ~/.openclaw/.env << 'EOF'
DISCORD_BOT_TOKEN=your-extracted-token
KIMI_API_KEY=your-extracted-key
EOF
chmod 600 ~/.openclaw/.env

Step 3: Update config to use env vars Replace "token": "actual-token" with "token": "${env:DISCORD_BOT_TOKEN}"

Step 4: Verify

openclaw secrets audit
# Should show no plaintext keys

Step 5: Restart

openclaw gateway restart

Troubleshooting

“Cannot resolve env variable”

Check: Variable is actually set

echo $DISCORD_BOT_TOKEN

Check: No spaces around = in .env file

# Wrong
DISCORD_BOT_TOKEN = token-here

# Right  
DISCORD_BOT_TOKEN=token-here

Gateway can’t find .env

Check: File location

ls -la ~/.openclaw/.env

Check: File permissions

chmod 600 ~/.openclaw/.env

Environment variables not loading

For systemd:

# Check if EnvironmentFile is set
systemctl --user cat openclaw-gateway.service | grep Environment

# Reload and restart
systemctl --user daemon-reload
systemctl --user restart openclaw-gateway

Alternative: Password Store

For even better security, use a password manager:

With pass

# Store token
pass insert openclaw/discord-token

# Retrieve in script
export DISCORD_BOT_TOKEN=$(pass openclaw/discord-token)
openclaw gateway restart

With 1Password CLI

export DISCORD_BOT_TOKEN=$(op read "op://Private/OpenClaw/discord-token")

Summary

ApproachSecurityConvenienceBest For
Plaintext config❌ Poor✅ EasyNever
Environment variables✅ Good✅ EasyMost users
.env file✅ Good✅ EasyDevelopment
Password store✅ Excellent⚠️ SetupSecurity-focused

Recommendation: Use .env file for most setups, password store for high-security environments.


Remember: Security is about trade-offs. Environment variables hit the sweet spot between security and convenience for most OpenClaw deployments.