Back to Article List

Keep your API keys safe in OpenClaw: A guide to secrets

Keep your API keys safe in OpenClaw: A guide to secrets - Keep your API keys safe in OpenClaw: A guide to secrets

By default, OpenClaw stores API keys and bot tokens in plaintext inside ~/.openclaw/openclaw.json and related credential files. For local personal use, that's probably fine. For anything running on a VPS, shared with others, or connected to services that cost real money, it's a genuine risk. Exposed tokens have caused bill spikes from stolen API keys, channel hijacks via leaked Telegram and Discord tokens, and data exfiltration through agents with read/write tool access.

The good news is OpenClaw has a native secrets management system built in that most people never configure, because the onboarding flow doesn't require it. This guide covers the full picture: where secrets currently live, how to move them out of plaintext config, integrating with external secret stores, rotating credentials safely, and detecting leaks before they cause damage.

How your secrets end up exposed

Understanding the attack surface makes the mitigations easier to prioritize. There are a few common ways OpenClaw credentials get exposed in practice, and they're mostly not dramatic hacks.

Git commits. Someone puts their ~/.openclaw/ directory under version control or copies openclaw.json into a repo for backup purposes. Even a private repo is one misconfigured permission setting away from being public. Pre-commit hooks that scan for token patterns catch this, but most people don't have them.

Backup archives. The standard backup advice is to tar up ~/.openclaw/. An unencrypted tar sitting on an S3 bucket or transferred over an unencrypted connection contains every token you have in plaintext. The upgrade guide recommends encrypting backups with GPG for exactly this reason.

Debug logs. Running the Gateway at debug log level is the right move for troubleshooting. It's also a way to get API keys into log files if environment variable resolution logging is verbose. Check that your log files don't contain raw token values before sharing them anywhere.

MEMORY.md. This one is less obvious. If an agent is prompted (intentionally or via injection) to write its configuration context into memory files, tokens from its auth profile can end up in MEMORY.md. This is a prompt injection risk more than a config risk, but the consequence is the same: plaintext tokens in a file that might get backed up, synced, or indexed somewhere.

World-readable files. Fresh installs on Linux sometimes leave ~/.openclaw/ with permissions that any user on the system can read. On a shared VPS or any multi-user system, this is a straightforward credential leak.

Environment variables and .env files

The first step up from plaintext config is moving tokens to environment variables. OpenClaw resolves ${VAR} references in config strings at startup, and reloads them atomically when the Gateway restarts. This means you can keep the structure of your config while removing the actual values from it.

The .env loading order

OpenClaw looks for environment variable values in this order, with earlier sources taking priority:

  1. Process environment (set by systemd, Docker, or the shell that launched the Gateway)
  2. .env in the current working directory
  3. ~/.openclaw/.env (the daemon's own env file)
  4. An inline env block in the config itself

For most setups, ~/.openclaw/.env is the right place to put secrets. It stays close to the config it supports, it's not in a working directory that might get version controlled, and it's easy to reason about. A basic example:

ANTHROPIC_API_KEY=sk-ant-...
TELEGRAM_BOT_TOKEN=123456:ABC-...
DISCORD_BOT_TOKEN=...
OPENAI_API_KEY=sk-...

Then in your config, reference them:

models:
  providers:
    anthropic:
      apiKey: ${ANTHROPIC_API_KEY}
channels:
  telegram:
    token: ${TELEGRAM_BOT_TOKEN}

File hygiene for .env

The .env file itself needs to be protected. Permissions first:

chmod 600 ~/.openclaw/.env
chown youruser:youruser ~/.openclaw/.env

If you have anything in ~/.openclaw/ under version control (skills, custom tools, workspace templates), make sure .env is in .gitignore. A pre-commit hook that scans for obvious token patterns is worth adding to any repo that touches OpenClaw config:

# Install truffleHog or gitleaks as a pre-commit hook
pip install pre-commit
# Or: brew install gitleaks

For systemd service deployments, avoid loading the .env file through a shell that inherits the daemon's environment into child processes. Use systemd's EnvironmentFile directive instead, which loads the file directly without shell interpolation:

[Service]
EnvironmentFile=/secure/path/openclaw.env

Keep that file outside of ~/.openclaw/ if you're on a shared server and restrict its permissions to the service user.

OpenClaw's native SecretRef system

Moving from plaintext to environment variables is a good first step. The full solution is OpenClaw's SecretRef system, which lets you define named secret providers and reference secrets by ID rather than value anywhere in your config. The Gateway resolves the references at startup and fails fast if any are unresolvable, which means misconfigured secrets surface immediately rather than causing runtime failures.

Provider types

There are three built-in provider types: env, file, and exec. Each covers a different deployment scenario.

env provider reads from environment variables with an optional allowlist to restrict which variables can be accessed:

secrets:
  providers:
    default:
      source: "env"
      allowlist:
        - "ANTHROPIC_*"
        - "TELEGRAM_*"
        - "DISCORD_*"

file provider reads from a JSON file or a file containing a single value. Useful when you want to keep secrets in a location managed separately from your OpenClaw config:

secrets:
  providers:
    key_file:
      source: "file"
      path: "/secure/openclaw-keys.json"
      mode: "json"

The JSON file format is straightforward: keys are the secret IDs you'll reference, values are the actual secrets.

exec provider runs a command and uses its stdout as the secret value. This is what enables integration with external secret managers:

secrets:
  providers:
    onepassword:
      source: "exec"
      command: "/opt/homebrew/bin/op"
      allowSymlinkCommand: true
      trustedDirs:
        - "/opt/homebrew"
      args: ["read", "op://Personal/OpenClaw/anthropic_key"]

Referencing secrets in config

Once providers are defined, you reference secrets in config using a keyRef object instead of a literal value:

profiles:
  main:
    type: "api_key"
    keyRef:
      source: "env"
      id: "ANTHROPIC_API_KEY"
  telegram_prod:
    type: "bot_token"
    keyRef:
      source: "exec"
      provider: "onepassword"
      id: "telegram_prod_token"

If you have an existing setup with plaintext tokens in auth-profiles.json, OpenClaw provides a migration command that scrubs them and rewrites the file to use references:

openclaw secrets configure --skip-provider-setup

Integrating external secret stores

The exec provider is the bridge to any external secret manager. The pattern is always the same: configure the provider to call the external tool's CLI, and reference secrets by their path or ID in that store.

HashiCorp Vault

secrets:
  providers:
    vault:
      source: "exec"
      command: "vault"
      args:
        - "kv"
        - "get"
        - "-field=token"
        - "secret/openclaw/anthropic"

This assumes the Vault CLI is installed and authenticated (via VAULT_TOKEN or a Vault agent). The Gateway process needs to be able to reach Vault at runtime, which means either running Vault locally or ensuring network access from wherever the Gateway runs.

AWS Secrets Manager

secrets:
  providers:
    aws_secrets:
      source: "exec"
      command: "aws"
      args:
        - "secretsmanager"
        - "get-secret-value"
        - "--secret-id"
        - "openclaw/anthropic"
        - "--query"
        - "SecretString"
        - "--output"
        - "text"

The AWS CLI needs credentials to authenticate, ideally via an IAM role attached to the EC2 instance or ECS task rather than static access keys. The IAM policy should grant only secretsmanager:GetSecretValue on the specific secret ARNs that OpenClaw needs, nothing broader.

1Password CLI

secrets:
  providers:
    onepassword:
      source: "exec"
      command: "op"
      allowSymlinkCommand: true
      trustedDirs:
        - "/usr/local/bin"
        - "/opt/homebrew/bin"
      args:
        - "read"
        - "op://Personal/OpenClaw API Keys/anthropic"

The allowSymlinkCommand: true and trustedDirs settings are security constraints that prevent the exec provider from being redirected to arbitrary commands. Only commands in trusted directories can be executed as providers, which matters because an exec provider with a tampered command path is a code execution vulnerability.

Bitwarden / BWS

secrets:
  providers:
    bitwarden:
      source: "exec"
      command: "bw"
      args:
        - "get"
        - "password"
        - "OpenClaw Anthropic Key"

Bitwarden Secrets Manager (BWS) also works and is worth considering if you want a purpose-built secrets tool rather than a password manager.

Docker and Kubernetes secrets

For containerized deployments, use the file provider pointing at the mounted secrets path. Docker Swarm and Kubernetes both mount secrets at /run/secrets/ by default:

secrets:
  providers:
    container_secrets:
      source: "file"
      path: "/run/secrets/anthropic_key"
      mode: "singleValue"

This works cleanly with Docker Compose's secrets: block and Kubernetes Secret volumes. See the clustering guide for how secrets fit into a multi-replica Kubernetes deployment.

Rotating credentials

Rotating a compromised or expired credential is stressful if you've never done it on a running system. Doing it in advance, on a schedule, removes most of that stress because you've already tested the process.

The sequence for a clean rotation:

  1. Generate the new key in the provider's dashboard (Anthropic console, Telegram BotFather, Discord developer portal, etc.). Don't revoke the old one yet.
  2. Update the secret store with the new value. For env-based secrets, update ~/.openclaw/.env. For external stores, update the secret value there.
  3. Test resolution without restarting the live Gateway: openclaw secrets list shows masked values and confirms the provider can resolve each reference.
  4. Restart the Gateway to pick up the new value atomically. The Gateway fails fast at startup if any secret is unresolvable, so a misconfigured rotation surfaces immediately before traffic hits the new credential.
  5. Verify connections with openclaw channels status --probe to confirm each channel authenticates with the new token.
  6. Revoke the old key only after confirming the new one works. This is the step people skip when they're in a hurry and then regret.

Least privilege per integration

Using a single API key for everything is convenient and dangerous. If that key leaks, every integration is exposed simultaneously. The better approach is separate keys per integration and per agent, scoped to the minimum permissions each one actually needs.

In practice this means: one Anthropic key for your main agent, a separate one for background cron agents (possibly on a restricted tier), per-channel bot tokens for Telegram and Discord, and separate OAuth credentials for Gmail and Google Calendar integrations. See the Gmail integration guide and Slack integration guide for how to scope OAuth credentials to specific permissions rather than full account access.

For agents running in public channels with untrusted input, deny exec and webhook tools in the tool allow/deny configuration even if the agent's API key has broader permissions. Defense in depth: the token shouldn't be scoped broadly, and the tool access shouldn't be either.

Auditing for leaks

OpenClaw includes a secrets audit command that scans known credential locations for plaintext tokens:

openclaw secrets audit --check

This checks auth-profiles.json, legacy auth.json files, and other locations where plaintext tokens commonly end up. Run it after any config change and after upgrades, since upgrades sometimes generate new credential files in the old plaintext format.

Beyond the native audit, a few external tools are worth adding to your workflow:

  • truffleHog or gitleaks as pre-commit hooks on any repo that touches OpenClaw config. These scan for high-entropy strings and known token patterns before they can be committed.
  • Manual grep of log files if you've run at debug log level: grep -r "sk-ant\|sk-\|Bearer" ~/.openclaw/logs/. Token values appearing in logs is a sign that something in the resolution or logging pipeline is more verbose than it should be.
  • Permission audit on backup files: any .tgz backup containing ~/.openclaw/ should be encrypted. Check that you didn't create any unencrypted archives during troubleshooting sessions and forget to delete them.

For OTEL-based monitoring, OpenClaw redacts secret values from traces and logs by default. If you're seeing token values appearing in Datadog or Grafana traces, check whether a custom skill or tool is logging environment variables explicitly.

The security best practices guide covers the broader operational security picture beyond secrets specifically.

Your idea deserves better hosting

24/7 support 30-day money-back guarantee Cancel anytime
Billing Cycle

1 GB RAM VPS

17.22 RON Save  50 %
8.59 RON Monthly
  • 1 vCPU AMD EPYC
  • 30 GB NVMe storage
  • Unmetered bandwidth
  • IPv4 & IPv6 included IPv6 support is currently unavailable in France, Finland or the Netherlands.
  • 1 Gbps network
  • Firewall management
  • Free server monitoring

2 GB RAM VPS

21.54 RON Save  20 %
17.22 RON Monthly
  • 2 vCPU AMD EPYC
  • 30 GB NVMe storage
  • Unmetered bandwidth
  • IPv4 & IPv6 included IPv6 support is currently unavailable in France, Finland or the Netherlands.
  • 1 Gbps network
  • Firewall management
  • Free server monitoring

6 GB RAM VPS

60.39 RON Save  29 %
43.12 RON Monthly
  • 6 vCPU AMD EPYC
  • 70 GB NVMe storage
  • Unmetered bandwidth
  • IPv4 & IPv6 included IPv6 support is currently unavailable in France, Finland or the Netherlands.
  • 1 Gbps network
  • Firewall management
  • Free server monitoring

AMD EPYC VPS.P1

30.17 RON Save  29 %
21.54 RON Monthly
  • 2 vCPU AMD EPYC
  • 4 GB RAM memory
  • 40 GB NVMe storage
  • Unmetered bandwidth
  • IPv4 & IPv6 included IPv6 support is currently unavailable in France, Finland or the Netherlands.
  • 1 Gbps network
  • Automatic backup included
  • Firewall management
  • Free server monitoring

AMD EPYC VPS.P2

56.07 RON Save  31 %
38.81 RON Monthly
  • 2 vCPU AMD EPYC
  • 8 GB RAM memory
  • 80 GB NVMe storage
  • Unmetered bandwidth
  • IPv4 & IPv6 included IPv6 support is currently unavailable in France, Finland or the Netherlands.
  • 1 Gbps network
  • Automatic backup included
  • Firewall management
  • Free server monitoring

AMD EPYC VPS.P4

112.19 RON Save  31 %
77.66 RON Monthly
  • 4 vCPU AMD EPYC
  • 16 GB RAM memory
  • 160 GB NVMe storage
  • Unmetered bandwidth
  • IPv4 & IPv6 included IPv6 support is currently unavailable in France, Finland or the Netherlands.
  • 1 Gbps network
  • Automatic backup included
  • Firewall management
  • Free server monitoring

AMD EPYC VPS.P5

140.25 RON Save  29 %
99.24 RON Monthly
  • 8 vCPU AMD EPYC
  • 16 GB RAM memory
  • 180 GB NVMe storage
  • Unmetered bandwidth
  • IPv4 & IPv6 included IPv6 support is currently unavailable in France, Finland or the Netherlands.
  • 1 Gbps network
  • Automatic backup included
  • Firewall management
  • Free server monitoring

AMD EPYC VPS.P6

211.47 RON Save  31 %
146.72 RON Monthly
  • 8 vCPU AMD EPYC
  • 32 GB RAM memory
  • 200 GB NVMe storage
  • Unmetered bandwidth
  • IPv4 & IPv6 included IPv6 support is currently unavailable in France, Finland or the Netherlands.
  • 1 Gbps network
  • Automatic backup included
  • Firewall management
  • Free server monitoring

AMD EPYC VPS.P7

267.58 RON Save  35 %
172.62 RON Monthly
  • 16 vCPU AMD EPYC
  • 32 GB RAM memory
  • 240 GB NVMe storage
  • Unmetered bandwidth
  • IPv4 & IPv6 included IPv6 support is currently unavailable in France, Finland or the Netherlands.
  • 1 Gbps network
  • Automatic backup included
  • Firewall management
  • Free server monitoring

EPYC Genoa VPS.G1

21.54 RON Save  20 %
17.22 RON Monthly
  • 1 vCPU AMD EPYC Gen4 AMD EPYC Genoa 4th generation 9xx4 with 3.25 GHz or similar, on Zen 4 architecture.
  • 1 GB DDR5 memory
  • 25 GB NVMe storage
  • Unmetered bandwidth
  • IPv4 & IPv6 included IPv6 support is currently unavailable in France, Finland or the Netherlands.
  • 1 Gbps network
  • Automatic backup included
  • Firewall management
  • Free server monitoring

EPYC Genoa VPS.G2

43.12 RON Save  20 %
34.49 RON Monthly
  • 2 vCPU AMD EPYC Gen4 AMD EPYC Genoa 4th generation 9xx4 with 3.25 GHz or similar, on Zen 4 architecture.
  • 4 GB DDR5 memory
  • 50 GB NVMe storage
  • Unmetered bandwidth
  • IPv4 & IPv6 included IPv6 support is currently unavailable in France, Finland or the Netherlands.
  • 1 Gbps network
  • Automatic backup included
  • Firewall management
  • Free server monitoring

EPYC Genoa VPS.G4

81.97 RON Save  32 %
56.07 RON Monthly
  • 4 vCPU AMD EPYC Gen4 AMD EPYC Genoa 4th generation 9xx4 with 3.25 GHz or similar, on Zen 4 architecture.
  • 8 GB DDR5 memory
  • 100 GB NVMe storage
  • Unmetered bandwidth
  • IPv4 & IPv6 included IPv6 support is currently unavailable in France, Finland or the Netherlands.
  • 1 Gbps network
  • Automatic backup included
  • Firewall management
  • Free server monitoring

EPYC Genoa VPS.G5

129.45 RON Save  27 %
94.92 RON Monthly
  • 4 vCPU AMD EPYC Gen4 AMD EPYC Genoa 4th generation 9xx4 with 3.25 GHz or similar, on Zen 4 architecture.
  • 16 GB DDR5 memory
  • 150 GB NVMe storage
  • Unmetered bandwidth
  • IPv4 & IPv6 included IPv6 support is currently unavailable in France, Finland or the Netherlands.
  • 1 Gbps network
  • Automatic backup included
  • Firewall management
  • Free server monitoring

EPYC Genoa VPS.G6

151.04 RON Save  23 %
116.50 RON Monthly
  • 8 vCPU AMD EPYC Gen4 AMD EPYC Genoa 4th generation 9xx4 with 3.25 GHz or similar, on Zen 4 architecture.
  • 16 GB DDR5 memory
  • 200 GB NVMe storage
  • Unmetered bandwidth
  • IPv4 & IPv6 included IPv6 support is currently unavailable in France, Finland or the Netherlands.
  • 1 Gbps network
  • Automatic backup included
  • Firewall management
  • Free server monitoring

EPYC Genoa VPS.G7

250.32 RON Save  26 %
185.57 RON Monthly
  • 8 vCPU AMD EPYC Gen4 AMD EPYC Genoa 4th generation 9xx4 with 3.25 GHz or similar, on Zen 4 architecture.
  • 32 GB DDR5 memory
  • 250 GB NVMe storage
  • Unmetered bandwidth
  • IPv4 & IPv6 included IPv6 support is currently unavailable in France, Finland or the Netherlands.
  • 1 Gbps network
  • Automatic backup included
  • Firewall management
  • Free server monitoring

FAQ

Are secrets in .env safer than secrets in openclaw.json?

Marginally, but not dramatically. Both are plaintext files on disk. The real advantage of .env is separation: you can back up openclaw.json (which contains your configuration logic) without including the actual secret values. The SecretRef system is the proper solution for secrets that need to be genuinely protected, because the values never touch the config files at all.

Automate faster, for less

Bring your winning ideas to life with AMD power, NVMe speed and unmetered bandwidth. Deploy your VPS in seconds, with a pre-installed OpenClaw template on Ubuntu 24.04.